From fabb1feaf554a0729513bc3aedae56fe41bab984 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Tue, 21 Jul 2026 11:49:21 +0200 Subject: [PATCH 001/189] fix: skip loading state on account page reload, enable prerelease versioning --- lib/pages/account.dart | 2 ++ release-please-config.json | 3 +++ 2 files changed, 5 insertions(+) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 6b8ed88ff..3fc732d4e 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -157,6 +157,7 @@ class AccountViewPageState extends ConsumerState with SingleTic final selectedAccountAV = ref.watch(selectedAccountProvider); ref.watch(appSettingsProvider); // rebuild when settings change (e.g. list/table toggle) return selectedAccountAV.when( + skipLoadingOnReload: true, loading: () => blank(context), error: (error, stack) => showError(error), data: (selectedAccount) { @@ -170,6 +171,7 @@ class AccountViewPageState extends ConsumerState with SingleTic final fullDataAV = ref.watch(fullAccountPageDataProvider); return fullDataAV.when( + skipLoadingOnReload: true, loading: () => blank(context), error: (error, stack) => showError(error), data: (fullData) => _buildAccountScaffold(context, fullData), diff --git a/release-please-config.json b/release-please-config.json index 64e021bb6..a056d2f03 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -4,6 +4,9 @@ "release-type": "simple", "component": "zkool", "include-component-in-tag": true, + "prerelease": true, + "versioning": "prerelease", + "prerelease-type": "rc", "changelog-path": "CHANGELOG.md", "extra-files": [ "version.txt", From 4fd9c66f1bc620ddc4821fe9d2279ac58b1a81c3 Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Thu, 23 Jul 2026 00:59:03 +0200 Subject: [PATCH 002/189] feat: re-enable ZSA support (#1164) - ZSA asset tracking in coin selection (asset_index on notes/outputs) - Per-asset balance and change computation - ZSA memo decryption (612-byte ciphertexts via OrchardZSADomain) - Wire format: read/write full ZSA enc_ciphertexts with asset field - V2/V3 bundle signing: add_orchard_change_output for Ironwood/V3, add_orchard_output for V2 (IO Finalizer handles dummies) - Sync refactor: CompactTx instead of SyncTx, drop issuance synthesis - Schema: UNIQUE(asset_base), idx_assets_asset_base, asset_name column - Cargo.toml: switch path overrides to git revs (orchard bd4be3b, lrz f53afe2a) --- Cargo.lock | 439 +++--- Cargo.toml | 24 +- protos/compact_formats.proto | 2 +- rust/src/db.rs | 11 +- rust/src/memo.rs | 109 +- rust/src/pay/plan.rs | 1898 +++-------------------- rust/src/pay/solve.rs | 191 ++- rust/src/warp/decrypter.rs | 8 +- rust/src/warp/sync.rs | 149 +- rust/src/warp/sync/block.rs | 51 - rust/src/warp/sync/shielded.rs | 166 +- rust/src/warp/sync/shielded/ironwood.rs | 20 +- rust/src/warp/sync/shielded/orchard.rs | 214 ++- rust/src/warp/sync/shielded/sapling.rs | 17 +- rust/tests/zsa_transfer_test.rs | 236 +++ 15 files changed, 1219 insertions(+), 2316 deletions(-) delete mode 100644 rust/src/warp/sync/block.rs create mode 100644 rust/tests/zsa_transfer_test.rs diff --git a/Cargo.lock b/Cargo.lock index 821324f62..c967eaa23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,9 +255,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arbitrary" @@ -330,7 +330,7 @@ dependencies = [ "rand 0.9.5", "safelog", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tor-async-utils", "tor-basic-utils", @@ -375,7 +375,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -546,13 +546,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -567,7 +567,7 @@ dependencies = [ "futures-util", "pin-project", "rustc_version", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -651,9 +651,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.1" +version = "1.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" +checksum = "00bdb5da18dac48ca2cc7cd4a98e533e8635a58e2361d13a1a4ee3888e0d72f1" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -662,9 +662,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.42.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" +checksum = "43103168cc76fe62678a375e722fc9cb3a0146159ac5828bc4f0dfd755c2224c" dependencies = [ "cc", "cmake", @@ -1001,7 +1001,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09dc0086e469182132244e9b8d313a0742e1132da43a08c24b9dd3c18e0faf3a" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -1051,9 +1051,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.25.1" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" [[package]] name = "byteorder" @@ -1105,9 +1105,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.67" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" +checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" dependencies = [ "find-msvc-tools", "jobserver", @@ -1129,9 +1129,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" @@ -1195,9 +1195,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.2" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd059f9da4f5c36b3787f65d38ccaab1cc315f07b01f89abc8359ee6a8205011" +checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" dependencies = [ "clap_builder", "clap_derive", @@ -1217,14 +1217,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -1268,7 +1268,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -1745,7 +1745,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", ] @@ -2255,9 +2255,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "ff" @@ -2414,7 +2414,7 @@ dependencies = [ "oslog", "portable-atomic", "threadpool", - "tokio 1.52.3", + "tokio 1.53.1", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -2526,7 +2526,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect", - "thiserror 2.0.18", + "thiserror 2.0.19", "visibility", "zeroize", ] @@ -2556,7 +2556,7 @@ dependencies = [ "once_cell", "pwd-grp", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "walkdir", ] @@ -2606,9 +2606,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" dependencies = [ "futures-channel", "futures-core", @@ -2621,9 +2621,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" dependencies = [ "futures-core", "futures-sink", @@ -2631,15 +2631,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-executor" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" dependencies = [ "futures-core", "futures-task", @@ -2659,9 +2659,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" [[package]] name = "futures-lite" @@ -2678,9 +2678,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" dependencies = [ "proc-macro2", "quote", @@ -2689,21 +2689,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-channel", "futures-core", @@ -2787,9 +2787,9 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "glob-match" @@ -2873,7 +2873,7 @@ dependencies = [ "http 0.2.12", "indexmap 2.14.0", "slab", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-util", "tracing", ] @@ -2892,7 +2892,7 @@ dependencies = [ "http 1.4.2", "indexmap 2.14.0", "slab", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-util", "tracing", ] @@ -3105,7 +3105,7 @@ dependencies = [ "ring", "thiserror 1.0.69", "tinyvec", - "tokio 1.52.3", + "tokio 1.53.1", "tracing", "url", ] @@ -3127,7 +3127,7 @@ dependencies = [ "resolv-conf", "smallvec", "thiserror 1.0.69", - "tokio 1.52.3", + "tokio 1.53.1", "tracing", ] @@ -3317,7 +3317,7 @@ dependencies = [ "itoa", "pin-project-lite 0.2.17", "socket2 0.5.10", - "tokio 1.52.3", + "tokio 1.53.1", "tower-service", "tracing", "want", @@ -3325,9 +3325,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" dependencies = [ "atomic-waker", "bytes 1.12.1", @@ -3341,7 +3341,7 @@ dependencies = [ "itoa", "pin-project-lite 0.2.17", "smallvec", - "tokio 1.52.3", + "tokio 1.53.1", "want", ] @@ -3352,13 +3352,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http 1.4.2", - "hyper 1.10.1", + "hyper 1.11.0", "hyper-util", "rustls 0.23.42", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-rustls", "tower-service", - "webpki-roots 1.0.8", + "webpki-roots 1.0.9", ] [[package]] @@ -3367,10 +3367,10 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.10.1", + "hyper 1.11.0", "hyper-util", "pin-project-lite 0.2.17", - "tokio 1.52.3", + "tokio 1.53.1", "tower-service", ] @@ -3383,7 +3383,7 @@ dependencies = [ "bytes 1.12.1", "hyper 0.14.32", "native-tls", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-native-tls", ] @@ -3395,10 +3395,10 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes 1.12.1", "http-body-util", - "hyper 1.10.1", + "hyper 1.11.0", "hyper-util", "native-tls", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-native-tls", "tower-service", ] @@ -3415,14 +3415,14 @@ dependencies = [ "futures-util", "http 1.4.2", "http-body 1.1.0", - "hyper 1.10.1", + "hyper 1.11.0", "ipnet", "libc", "percent-encoding", "pin-project-lite 0.2.17", "socket2 0.6.5", "system-configuration 0.7.0", - "tokio 1.52.3", + "tokio 1.53.1", "tower-service", "tracing", "windows-registry", @@ -3805,11 +3805,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.32" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961d16382652bfdd8c6f68b223b26a8c93e0d475c672f414411db31c6c5c900e" +checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16" dependencies = [ "defmt", + "jiff-core", "jiff-static", "log", "portable-atomic", @@ -3817,12 +3818,22 @@ dependencies = [ "serde_core", ] +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + [[package]] name = "jiff-static" -version = "0.2.32" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" +checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de" dependencies = [ + "jiff-core", "proc-macro2", "quote", "syn 2.0.119", @@ -3929,7 +3940,7 @@ dependencies = [ "juniper", "juniper_subscriptions", "serde", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -3955,7 +3966,7 @@ dependencies = [ "juniper_graphql_ws", "log", "serde_json", - "tokio 1.52.3", + "tokio 1.53.1", "warp", ] @@ -4067,9 +4078,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "liblzma" @@ -4701,7 +4712,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=7bc6c6f3b48ace8db768f3145f86ffb1593b83e0#7bc6c6f3b48ace8db768f3145f86ffb1593b83e0" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=bd4be3bd585389ae7e2870b0c4899027dfd1afcd#bd4be3bd585389ae7e2870b0c4899027dfd1afcd" dependencies = [ "aes", "bitvec", @@ -4884,7 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "bls12_381", @@ -5096,9 +5107,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" [[package]] name = "portable-atomic-util" @@ -5224,9 +5235,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] @@ -5366,7 +5377,7 @@ dependencies = [ "derive-deftly", "libc", "paste", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -5398,8 +5409,8 @@ dependencies = [ "rustc-hash 2.1.3", "rustls 0.23.42", "socket2 0.6.5", - "thiserror 2.0.18", - "tokio 1.52.3", + "thiserror 2.0.19", + "tokio 1.53.1", "tracing", "web-time", ] @@ -5420,7 +5431,7 @@ dependencies = [ "rustls 0.23.42", "rustls-pki-types", "slab", - "thiserror 2.0.18", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -5442,9 +5453,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -5753,7 +5764,7 @@ dependencies = [ "pasta_curves", "rand_core 0.6.4", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "zeroize", ] @@ -5796,27 +5807,27 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "ref-cast" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -5893,7 +5904,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 0.1.2", "system-configuration 0.5.1", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-native-tls", "tower-service", "url", @@ -5917,7 +5928,7 @@ dependencies = [ "http 1.4.2", "http-body 1.1.0", "http-body-util", - "hyper 1.10.1", + "hyper 1.11.0", "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", @@ -5934,7 +5945,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-native-tls", "tokio-rustls", "tower", @@ -5944,7 +5955,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 1.0.8", + "webpki-roots 1.0.9", ] [[package]] @@ -6104,8 +6115,8 @@ dependencies = [ "serde_with", "sha2 0.10.9", "sqlx", - "thiserror 2.0.18", - "tokio 1.52.3", + "thiserror 2.0.19", + "tokio 1.53.1", "tokio-rustls", "tokio-socks", "tokio-stream", @@ -6119,7 +6130,7 @@ dependencies = [ "tracing-subscriber", "vcard4", "warp", - "webpki-roots 1.0.8", + "webpki-roots 1.0.9", "x25519-dalek", "zcash-trees", "zcash_address", @@ -6360,7 +6371,7 @@ dependencies = [ "educe", "either", "fluid-let", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -6591,9 +6602,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -6611,22 +6622,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -6641,9 +6652,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -6818,7 +6829,7 @@ checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", ] @@ -6863,7 +6874,7 @@ dependencies = [ "paste", "serde", "slotmap", - "thiserror 2.0.18", + "thiserror 2.0.19", "void", ] @@ -6995,8 +7006,8 @@ dependencies = [ "serde_json", "sha2 0.10.9", "smallvec", - "thiserror 2.0.18", - "tokio 1.52.3", + "thiserror 2.0.19", + "tokio 1.53.1", "tokio-stream", "tracing", "url", @@ -7036,7 +7047,7 @@ dependencies = [ "sqlx-postgres", "sqlx-sqlite", "syn 2.0.119", - "tokio 1.52.3", + "tokio 1.53.1", "url", ] @@ -7077,7 +7088,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.18", + "thiserror 2.0.19", "tracing", "whoami", ] @@ -7114,7 +7125,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.18", + "thiserror 2.0.19", "tracing", "whoami", ] @@ -7138,7 +7149,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.18", + "thiserror 2.0.19", "tracing", "url", ] @@ -7268,6 +7279,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -7385,11 +7407,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.19", ] [[package]] @@ -7405,13 +7427,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -7434,9 +7456,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.53" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" +checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" dependencies = [ "deranged", "num-conv", @@ -7454,9 +7476,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -7537,9 +7559,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes 1.12.1", "libc", @@ -7554,9 +7576,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" dependencies = [ "proc-macro2", "quote", @@ -7570,7 +7592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -7580,7 +7602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls 0.23.42", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -7592,18 +7614,18 @@ dependencies = [ "either", "futures-util", "thiserror 1.0.69", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] name = "tokio-stream" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite 0.2.17", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -7614,22 +7636,23 @@ checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" dependencies = [ "futures-util", "log", - "tokio 1.52.3", + "tokio 1.53.1", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes 1.12.1", "futures-core", "futures-io", "futures-sink", + "libc", "pin-project-lite 0.2.17", - "tokio 1.52.3", + "tokio 1.53.1", ] [[package]] @@ -7726,21 +7749,21 @@ dependencies = [ "http 1.4.2", "http-body 1.1.0", "http-body-util", - "hyper 1.10.1", + "hyper 1.11.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "socket2 0.6.5", "sync_wrapper 1.0.2", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-rustls", "tokio-stream", "tower", "tower-layer", "tower-service", "tracing", - "webpki-roots 1.0.8", + "webpki-roots 1.0.9", ] [[package]] @@ -7794,7 +7817,7 @@ dependencies = [ "oneshot-fused-workaround", "pin-project", "postage", - "thiserror 2.0.18", + "thiserror 2.0.19", "void", ] @@ -7814,7 +7837,7 @@ dependencies = [ "serde", "slab", "smallvec", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -7829,7 +7852,7 @@ dependencies = [ "educe", "getrandom 0.3.4", "safelog", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-error", "tor-llcrypto", "zeroize", @@ -7851,7 +7874,7 @@ dependencies = [ "paste", "rand 0.9.5", "smallvec", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-basic-utils", "tor-bytes", "tor-cert", @@ -7875,7 +7898,7 @@ dependencies = [ "derive_builder_fork_arti", "derive_more", "digest 0.10.7", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-bytes", "tor-checkable", "tor-llcrypto", @@ -7898,7 +7921,7 @@ dependencies = [ "rand 0.9.5", "safelog", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-async-utils", "tor-basic-utils", "tor-cell", @@ -7924,7 +7947,7 @@ checksum = "55af8d517e87c07f385bbdf8ea1fdd6e71830ecba5285b9a7bb249f7e4e47a85" dependencies = [ "humantime", "signature", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-llcrypto", ] @@ -7954,7 +7977,7 @@ dependencies = [ "safelog", "serde", "static_assertions", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-async-utils", "tor-basic-utils", "tor-chanmgr", @@ -8001,7 +8024,7 @@ dependencies = [ "serde-value", "serde_ignored", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "toml 0.8.23", "tor-basic-utils", "tor-error", @@ -8020,7 +8043,7 @@ dependencies = [ "once_cell", "serde", "shellexpand", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-error", "tor-general-addr", ] @@ -8033,7 +8056,7 @@ checksum = "2da1b81654807c5652286cb9bfad117c0cc0f7a58f945f34fb6be30d10eb071c" dependencies = [ "digest 0.10.7", "hex", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-llcrypto", ] @@ -8053,7 +8076,7 @@ dependencies = [ "httpdate", "itertools 0.14.0", "memchr", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-circmgr", "tor-error", "tor-hscrypto", @@ -8099,7 +8122,7 @@ dependencies = [ "signature", "static_assertions", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tor-async-utils", "tor-basic-utils", @@ -8133,7 +8156,7 @@ dependencies = [ "retry-error", "static_assertions", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "tracing", "void", ] @@ -8145,7 +8168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be71b2de02947b2f8711881fe7262002b8ac2c7283937c8d7144d0a902ce7fe2" dependencies = [ "derive_more", - "thiserror 2.0.18", + "thiserror 2.0.19", "void", ] @@ -8174,7 +8197,7 @@ dependencies = [ "safelog", "serde", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-async-utils", "tor-basic-utils", "tor-config", @@ -8211,7 +8234,7 @@ dependencies = [ "safelog", "slotmap-careful", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-async-utils", "tor-basic-utils", "tor-bytes", @@ -8254,7 +8277,7 @@ dependencies = [ "serde", "signature", "subtle", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-basic-utils", "tor-bytes", "tor-error", @@ -8278,7 +8301,7 @@ dependencies = [ "rand 0.9.5", "signature", "ssh-key", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-bytes", "tor-cert", "tor-checkable", @@ -8309,7 +8332,7 @@ dependencies = [ "serde", "signature", "ssh-key", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-basic-utils", "tor-bytes", "tor-config", @@ -8342,7 +8365,7 @@ dependencies = [ "serde", "serde_with", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-basic-utils", "tor-bytes", "tor-config", @@ -8384,7 +8407,7 @@ dependencies = [ "sha3", "signature", "subtle", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-memquota", "visibility", "x25519-dalek", @@ -8400,7 +8423,7 @@ dependencies = [ "futures", "humantime", "once_cell", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-error", "tor-rtcompat", "tracing", @@ -8424,7 +8447,7 @@ dependencies = [ "serde", "slotmap-careful", "static_assertions", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-async-utils", "tor-basic-utils", "tor-config", @@ -8454,7 +8477,7 @@ dependencies = [ "serde", "static_assertions", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tor-basic-utils", "tor-error", @@ -8494,7 +8517,7 @@ dependencies = [ "signature", "smallvec", "subtle", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tinystr", "tor-basic-utils", @@ -8531,7 +8554,7 @@ dependencies = [ "sanitize-filename", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tor-async-utils", "tor-basic-utils", @@ -8572,8 +8595,8 @@ dependencies = [ "slotmap-careful", "static_assertions", "subtle", - "thiserror 2.0.18", - "tokio 1.52.3", + "thiserror 2.0.19", + "tokio 1.53.1", "tokio-util", "tor-async-utils", "tor-basic-utils", @@ -8608,7 +8631,7 @@ dependencies = [ "caret", "paste", "serde_with", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-bytes", ] @@ -8646,8 +8669,8 @@ dependencies = [ "native-tls", "paste", "pin-project", - "thiserror 2.0.18", - "tokio 1.52.3", + "thiserror 2.0.19", + "tokio 1.53.1", "tokio-util", "tor-error", "tor-general-addr", @@ -8675,7 +8698,7 @@ dependencies = [ "priority-queue", "slotmap-careful", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-error", "tor-general-addr", "tor-rtcompat", @@ -8696,7 +8719,7 @@ dependencies = [ "educe", "safelog", "subtle", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-bytes", "tor-error", ] @@ -8710,7 +8733,7 @@ dependencies = [ "derive-deftly", "derive_more", "serde", - "thiserror 2.0.18", + "thiserror 2.0.19", "tor-memquota", ] @@ -8726,7 +8749,7 @@ dependencies = [ "pin-project-lite 0.2.17", "slab", "sync_wrapper 1.0.2", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-util", "tower-layer", "tower-service", @@ -8878,7 +8901,7 @@ dependencies = [ "log", "rand 0.9.5", "sha1", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -9079,9 +9102,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd4ec1eb1d240636e354a30110a1dfcb37047169a4d9bd6d9d3469df574b5c4" +checksum = "ef73bfbaf3216cb59c205d7176bee1194e0d84348979da31f4a71fefe3c2054e" [[package]] name = "vcard4" @@ -9165,7 +9188,7 @@ dependencies = [ "http 1.4.2", "http-body 1.1.0", "http-body-util", - "hyper 1.10.1", + "hyper 1.11.0", "hyper-util", "log", "mime", @@ -9176,7 +9199,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "tokio 1.52.3", + "tokio 1.53.1", "tokio-tungstenite", "tokio-util", "tower-service", @@ -9302,9 +9325,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" dependencies = [ "rustls-pki-types", ] @@ -9798,7 +9821,7 @@ dependencies = [ "rayon", "sapling-crypto", "secp256k1", - "thiserror 2.0.18", + "thiserror 2.0.19", "zcash_encoding", "zcash_protocol", "zcash_transparent", @@ -9808,7 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bech32 0.11.1", "bs58", @@ -9821,7 +9844,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "corez", "hex", @@ -9831,7 +9854,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bech32 0.11.1", "bip32", @@ -9871,7 +9894,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9901,7 +9924,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bellman", "blake2b_simd", @@ -9923,7 +9946,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "corez", "document-features", @@ -9946,7 +9969,7 @@ dependencies = [ "secp256k1", "sha1", "sha2 0.10.9", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] @@ -9960,7 +9983,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bip32", "bs58", @@ -9983,18 +10006,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.54" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.54" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" dependencies = [ "proc-macro2", "quote", @@ -10089,7 +10112,7 @@ dependencies = [ "flate2", "indexmap 2.14.0", "memchr", - "thiserror 2.0.18", + "thiserror 2.0.19", "zopfli", ] @@ -10109,7 +10132,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=20f1c954a029ba6762a130bf9824887b105037c9#20f1c954a029ba6762a130bf9824887b105037c9" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 45c0de0c8..b0abb16b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,21 +6,21 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7bc6c6f3b48ace8db768f3145f86ffb1593b83e0" } -#orchard = { path = "../zsa/orchard" } +#orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7bc6c6f3b48ace8db768f3145f86ffb1593b83e0" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "bd4be3bd585389ae7e2870b0c4899027dfd1afcd" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } -# -- lrz ZSA branch -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "20f1c954a029ba6762a130bf9824887b105037c9" } +# -- lrz ZSA branch (rev f53afe2a) -- +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/protos/compact_formats.proto b/protos/compact_formats.proto index 2e1cda5f8..d44210f9f 100644 --- a/protos/compact_formats.proto +++ b/protos/compact_formats.proto @@ -40,7 +40,7 @@ message CompactTx { repeated CompactSaplingSpend spends = 4; // inputs repeated CompactSaplingOutput outputs = 5; // outputs repeated CompactOrchardAction actions = 6; - repeated CompactOrchardAction ironwoodActions = 9; // Ironwood actions (canonical) + repeated CompactOrchardAction ironwoodActions = 9; repeated CompactIssuance issuances = 10; // ZSA issuance actions } diff --git a/rust/src/db.rs b/rust/src/db.rs index 02bf0e9e8..6281ff54d 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -249,7 +249,8 @@ pub async fn create_schema(connection: &mut SqliteConnection) -> Result<()> { asset_base BLOB NOT NULL, finalized BOOL NOT NULL DEFAULT FALSE, first_seen_height INTEGER NOT NULL, - UNIQUE (asset_desc_hash, ik))", + UNIQUE (asset_desc_hash, ik), + UNIQUE (asset_base))", ) .execute(&mut *connection) .await?; @@ -275,6 +276,14 @@ pub async fn create_schema(connection: &mut SqliteConnection) -> Result<()> { .execute(&mut *connection) .await; + // Migration: ensure asset_base is unique to prevent duplicate note inserts + // caused by duplicate issuances with the same asset_base. + let _ = sqlx::query( + "CREATE UNIQUE INDEX IF NOT EXISTS idx_assets_asset_base ON assets(asset_base)", + ) + .execute(&mut *connection) + .await; + sqlx::query( "CREATE TABLE IF NOT EXISTS dkg_params ( account INTEGER PRIMARY KEY, diff --git a/rust/src/memo.rs b/rust/src/memo.rs index cf9383f6a..b25147d79 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -1,5 +1,6 @@ use anyhow::{Context as _, Result}; -use orchard::{keys::Scope, note::ExtractedNoteCommitment, note_encryption::{IronwoodDomain, OrchardDomain}}; +use orchard::{keys::Scope, note::ExtractedNoteCommitment, note_encryption::{IronwoodDomain, OrchardDomain}, zsa::OrchardZSADomain}; +use zcash_note_encryption::note_bytes::NoteBytesData; use sapling_crypto::{keys::PreparedIncomingViewingKey, note_encryption::SaplingDomain}; use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use tracing::debug; @@ -110,6 +111,62 @@ async fn summarize_tx(connection: &mut SqliteConnection, tx: u32) -> Result<(u8, } } +/// Try ZSA decryption using the raw 612-byte enc_ciphertext with OrchardZSADomain. +/// Called when vanilla OrchardDomain decryption fails and raw ZSA ciphertext is available. +fn try_zsa_decrypt( + action: &orchard::Action<::SpendAuth>, + raw_enc: &[u8], + pivk: &orchard::keys::PreparedIncomingViewingKey, + ovk: &orchard::keys::OutgoingViewingKey, +) -> Option<( + orchard::Note, + orchard::Address, + [u8; 512], +)> { + use orchard::note::TransmittedNoteCiphertext; + use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; + + let vanilla_nc = action.encrypted_note(); + + // Reconstruct the ZSA TransmittedNoteCiphertext from raw bytes + let mut enc = NoteBytesData([0u8; 612]); + enc.0.copy_from_slice(raw_enc); + + let zsa_nc = TransmittedNoteCiphertext:: { + epk_bytes: vanilla_nc.epk_bytes, + enc_ciphertext: enc, + out_ciphertext: vanilla_nc.out_ciphertext, + }; + + let zsa_action = orchard::Action::from_parts( + *action.nullifier(), + action.rk().clone(), + orchard::note::ExtractedNoteCommitment::from_bytes(&action.cmx().to_bytes()).unwrap(), + zsa_nc, + action.cv_net().clone(), + (), + ) + .ok()?; + + let zsa_domain = OrchardZSADomain { rho: zsa_action.rho() }; + + if let Some((note, _address, memo_bytes)) = + try_note_decryption(&zsa_domain, pivk, &zsa_action) + { + Some((note, _address, memo_bytes)) + } else if let Some((note, address, memo_bytes)) = try_output_recovery_with_ovk( + &zsa_domain, + ovk, + &zsa_action, + zsa_action.cv_net(), + &zsa_action.encrypted_note().out_ciphertext, + ) { + Some((note, address, memo_bytes)) + } else { + None + } +} + pub async fn decrypt_memo( network: &Network, connection: &mut SqliteConnection, @@ -120,6 +177,9 @@ pub async fn decrypt_memo( debug!("decrypt_memo {account} {}", hex::encode(txid)); let (height, tx) = client.transaction(network, txid).await?; + // Extract raw ZSA enc_ciphertexts before consuming tx with into_data() + let zsa_raw_ciphertexts = tx.zsa_action_enc_ciphertexts.clone(); + let tx_data = tx.into_data(); let (id_tx,): (u32,) = @@ -309,6 +369,53 @@ pub async fn decrypt_memo( &memo_bytes, ) .await?; + } else if pool == 2 && vout < zsa_raw_ciphertexts.len() { + // Try ZSA decryption with the original 612-byte enc_ciphertext + if let Some(zsa_action) = try_zsa_decrypt( + action, + &zsa_raw_ciphertexts[vout], + &pivk, + &ovk, + ) { + let (note, address, memo_bytes) = zsa_action; + let cmx: ExtractedNoteCommitment = note.commitment().into(); + if let Ok(Some(id_note)) = sqlx::query( + "SELECT id_note FROM notes WHERE account = ? AND cmx = ?", + ) + .bind(account) + .bind(&cmx.to_bytes()[..]) + .map(|row: SqliteRow| row.get::(0)) + .fetch_optional(&mut *connection) + .await + { + process_memo( + connection, account, height, id_tx, + Some(id_note), None, pool, vout as u32, &memo_bytes, + ) + .await?; + } else { + let address = UnifiedAddress::from_receivers( + Some(address), None, None, + ) + .unwrap(); + let id_output = store_output( + connection, account, height, id_tx, pool, + vout as u32, + note.value().inner(), + &address.encode(network), + ) + .await?; + process_memo( + connection, account, height, id_tx, + None, Some(id_output), pool, vout as u32, &memo_bytes, + ) + .await?; + } + } else { + debug!( + "decrypt_memo: both ivk and ovk decrypt failed for vout={vout} pool={pool}" + ); + } } else { debug!( "decrypt_memo: both ivk and ovk decrypt failed for vout={vout} pool={pool}" diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 8770d9220..943d1659a 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -7,7 +7,7 @@ use itertools::Itertools; use orchard::{ circuit::ProvingKey, keys::{Scope, SpendAuthorizingKey}, - note::{AssetBase, ExtractedNoteCommitment}, + note::AssetBase, value::NoteValue, Address, }; @@ -58,11 +58,10 @@ use crate::{ keys::{sapling_pgk_for_scope, sapling_ssk_for_scope, SaplingFullViewingKey}, pay::{ error::Error, - fee::{FeeManager, COST_PER_ACTION}, - pool::{PoolMask, ALL_POOLS, NUM_POOLS}, + fee::COST_PER_ACTION, + pool::{PoolMask, NUM_POOLS}, prepare::to_zec, solve, InputNote, Recipient, RecipientState, ReceiverOption, DecomposedRecipient, - TxPlanIn, TxPlanOut, }, warp::hasher::{empty_roots, OrchardHasher, SaplingHasher}, Client, @@ -115,50 +114,6 @@ fn build_zsa_builder(info: &IssuanceInfo, oaddress: orchard::Address) -> Result< Ok(zsa) } -fn build_fee_manager( - input_pools: &[Vec], - buffered_zsaspends: &[InputNote], - single: &[RecipientState], - double: &[RecipientState], - buffered_zsaoutputs: &[RecipientState], - change_pool: u8, - issuance_action_info: Option<(u64, u64)>, - migration: bool, -) -> FeeManager { - let mut fee_manager = FeeManager { - migration, - ..FeeManager::default() - }; - - for pool_inputs in input_pools.iter() { - for inp in pool_inputs.iter() { - if inp.is_used() { - fee_manager.add_input(inp.pool); - } - } - } - - for _spend in buffered_zsaspends { - fee_manager.add_input(2); - } - - for r in single.iter().chain(double.iter()) { - fee_manager.add_output(r.pool_mask.to_best_pool().unwrap()); - } - - for _output in buffered_zsaoutputs { - fee_manager.add_output(2); - } - - fee_manager.add_output(change_pool); - - if let Some((issue_note_count, asset_creation_count)) = issuance_action_info { - fee_manager.add_issuance_actions(issue_note_count, asset_creation_count); - } - - fee_manager -} - /// Decompose a Zcash address into its individual shielded receivers. /// - UA address → S/O/I receivers (transparent stripped) /// - Pre-ironwood: Ironwood removed → max S/O @@ -246,7 +201,7 @@ pub async fn plan_transaction( confirmations: Option, smart_transparent: bool, category: Option, - _issuance: Option<&IssuanceInfo>, + issuance: Option<&IssuanceInfo>, migration: bool, mode: crate::pay::solve::Mode, preselected: Option<&[u32]>, @@ -321,9 +276,43 @@ pub async fn plan_transaction( }) .collect::>>()?; + // ZSA and Ironwood are mutually exclusive (different V6 version group IDs). + let has_zsa = decomposed.iter().any(|d| d.asset_base != [0u8; 32].to_vec()) + || issuance.is_some(); + if has_zsa && ironwood_active { + anyhow::bail!("ZSA and Ironwood are incompatible"); + } + + // Build asset list for solver: index 0 = ZEC, indices 1+ = ZSA (sorted) + let zec_key = [0u8; 32]; + let zsa_assets: Vec<[u8; 32]> = decomposed + .iter() + .filter(|d| d.asset_base != zec_key.to_vec()) + .map(|d| d.asset_base.clone()) + .sorted() + .dedup() + .filter_map(|b| b.try_into().ok()) + .collect(); + // ── Compute additional context ─────────────────────────────────────── let dindex = get_account_dindex(connection, account).await?; let hw = get_account_hw(&mut *connection, account).await?; + + // Compute weighted average price from recipients that have a price set + let mut total_amount = 0; + let mut total_fiat = 0.0; + for r in &recipients { + if let Some(p) = r.price { + total_fiat += p * r.amount as f64; + total_amount += r.amount; + } + } + let price = if total_amount != 0 { + Some(total_fiat / total_amount as f64) + } else { + None + }; + let (use_internal,): (bool,) = sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") .bind(account) @@ -343,15 +332,39 @@ pub async fn plan_transaction( before_dust[3], input_pools[3].len(), ); + // Build asset→index lookup: 0 = ZEC, 1+ = index into zsa_assets + let zsa_index: HashMap<[u8; 32], u8> = zsa_assets + .iter() + .enumerate() + .map(|(i, a)| (*a, (i + 1) as u8)) + .collect(); + + // Clone for move-capture in closures below + let zi = zsa_index.clone(); + + fn resolve_asset_index( + asset_base: &Vec, + zec_key: [u8; 32], + zsa_index: &HashMap<[u8; 32], u8>, + ) -> u8 { + let asset_bytes: [u8; 32] = asset_base.clone().try_into().unwrap_or(zec_key); + if asset_bytes == zec_key { + 0 + } else { + zsa_index.get(&asset_bytes).copied().unwrap_or(0) + } + } + // ── Coin selection via solve::select_notes ───────────────────────────── + // Stamp asset_index on notes: 0 = ZEC, 1+ = index into zsa_assets let select_notes_input: Vec = input_pools .iter() .enumerate() .flat_map(|(pool, notes)| { - notes.iter().enumerate().map(move |(idx, n)| solve::Note { - pool: pool as u8, - amount: n.amount, - pool_index: idx, + let zi = zi.clone(); + notes.iter().enumerate().map(move |(idx, n)| { + let asset_index = resolve_asset_index(&n.asset_base, zec_key, &zi); + solve::Note { pool: pool as u8, amount: n.amount, pool_index: idx, asset_index } }) }) .collect(); @@ -371,7 +384,10 @@ pub async fn plan_transaction( let select_outputs: Vec = pool_prefs .iter() .zip(decomposed.iter()) - .map(|(&pool, dr)| solve::Output { pool, amount: dr.amount }) + .map(|(&pool, dr)| { + let asset_index = resolve_asset_index(&dr.asset_base, zec_key, &zsa_index); + solve::Output { pool, amount: dr.amount, asset_index } + }) .collect(); info!( @@ -406,7 +422,35 @@ pub async fn plan_transaction( } } - let change_pool = selection.change_pool; + // ZSA assets only exist in Orchard; force change to orchard if any ZSA. + // The ZEC change output satisfies ZIP-226 (no dummy needed). + let change_pool = if has_zsa { 2 } else { selection.change_pool }; + + // ── Compute ZSA change amounts ─────────────────────────────────────── + // Per-asset: sum of selected ZSA notes minus required ZSA outputs. + let mut zsa_changes: Vec<([u8; 32], u64)> = vec![]; + if has_zsa { + let mut zsa_selected: HashMap<[u8; 32], u64> = HashMap::new(); + // Pool 2 (Orchard) is where ZSA notes live + for &idx in &selection.per_pool_indices[2] { + let note = &input_pools[2][idx]; + let asset_bytes: [u8; 32] = note.asset_base.clone().try_into().unwrap_or(zec_key); + if asset_bytes != zec_key { + *zsa_selected.entry(asset_bytes).or_default() += note.amount; + } + } + for asset in &zsa_assets { + let selected = *zsa_selected.get(asset).unwrap_or(&0); + let needed: u64 = decomposed + .iter() + .filter(|d| d.asset_base == asset.to_vec()) + .map(|d| d.amount) + .sum(); + if selected > needed { + zsa_changes.push((*asset, selected - needed)); + } + } + } // ── Build RecipientStates ──────────────────────────────────────────── let mut recipient_states: Vec = pool_prefs @@ -423,1035 +467,66 @@ pub async fn plan_transaction( ..Default::default() }, remaining: 0, // fully funded by select_notes - pool_mask: PoolMask::from_pool(pool), - asset_base: dr.asset_base.clone(), - } - }) - .collect(); - - // ── Fee, totals, and change (select_notes already validated feasibility) ─ - let fee = selection.fee; - info!("Fee (select_notes): {}", to_zec(fee)); - - // When the recipient pays the fee, deduct it from the first recipient - // so the sender only needs to cover (total_output - fee), matching the - // solver's target of `output_sum` (without fee). - if recipient_pays_fee { - if let Some(first) = recipient_states.first_mut() { - first.recipient.amount = first.recipient.amount.saturating_sub(fee); - } - } - - let total_output: u64 = recipient_states.iter().map(|r| r.recipient.amount).sum(); - let total_input: u64 = selection.inputs.iter().map(|n| n.amount).sum(); - let change = total_input.saturating_sub(total_output + fee); - - info!( - "change: {}, pool: {change_pool}, fee: {}", - to_zec(change), - to_zec(fee) - ); - - // ── Log outputs ────────────────────────────────────────────────────── - for r in &recipient_states { - info!( - "address: {}, pool: {}, amount: {}", - r.recipient.address, - r.pool_mask.to_best_pool().unwrap(), - to_zec(r.recipient.amount) - ); - } - - // ── Fetch tree states and anchors ──────────────────────────────────── - let h = crate::sync::get_db_height(connection, account).await?; - let (ts, to, ti) = crate::sync::get_tree_state(network, client, h.height).await?; - let es = ts.to_edge(&SaplingHasher::default()); - let eo = to.to_edge(&OrchardHasher::default()); - let ei = ti.to_edge(&OrchardHasher::default()); - let sapling_anchor = es.root(&SaplingHasher::default()); - let orchard_anchor = eo.root(&OrchardHasher::default()); - let ironwood_anchor = ei.root(&OrchardHasher::default()); - - // Determine which pools are active in this transaction - let mut has_pool = [false; NUM_POOLS as usize]; - for pool in 1..NUM_POOLS { - let p = pool as u8; - has_pool[pool] = input_pools[pool].iter().any(|inp| inp.is_used()) - || recipient_states.iter().any(|r| r.pool_mask.to_best_pool() == Some(p)) - || change_pool == p; - } - has_pool[3] &= ironwood_active; - - // ── Fetch change address ───────────────────────────────────────────── - let change_scope = if use_internal { 1 } else { 0 }; - let mut change_address = - get_account_full_address(network, connection, account, change_scope, hw).await?; - let tkeys = select_account_transparent(connection, account, dindex).await?; - if change_pool == 0 && tkeys.xvk.is_some() { - change_address = generate_next_change_address(network, connection, account) - .await? - .unwrap(); - } - - // ── Fetch keys ─────────────────────────────────────────────────────── - let svk = get_sapling_vk(connection, account).await?; - let ovk = get_orchard_vk(connection, account).await?; - let ssk = get_sapling_sk(&mut *connection, account).await?; - let osk = get_orchard_sk(&mut *connection, account).await?; - - // ── Build transaction ──────────────────────────────────────────────── - let current_height = client.latest_height().await?; - let target_height = current_height; - - let build_config = BuildConfig::Standard { - sapling_anchor: if has_pool[1] { - sapling_crypto::Anchor::from_bytes(sapling_anchor).into_option() - } else { - None - }, - orchard_anchor: if has_pool[2] { - orchard::Anchor::from_bytes(orchard_anchor).into_option() - } else { - None - }, - ironwood_anchor: if has_pool[3] { - orchard::Anchor::from_bytes(ironwood_anchor).into_option() - } else { - None - }, - }; - let mut builder = Builder::new(network, BlockHeight::from_u32(target_height), build_config); - - let es = es.to_auth_path(&SaplingHasher::default()); - let eo = eo.to_auth_path(&OrchardHasher::default()); - let ei = ei.to_auth_path(&OrchardHasher::default()); - let ers = empty_roots(&SaplingHasher::default()); - let ero = empty_roots(&OrchardHasher::default()); - - let mut tsk_dindex = vec![]; - let mut s_scope = vec![]; - - event!(Level::INFO, "Adding Inputs"); - - let mut n_spends: [usize; NUM_POOLS as usize] = [0; NUM_POOLS as usize]; - let mut can_sign = true; - - for pool in input_pools.iter() { - for inp in pool.iter() { - if inp.is_used() { - let InputNote { - id, amount, pool, .. - } = inp; - n_spends[*pool as usize] += 1; - match pool { - 0 => { - let row = sqlx::query( - "SELECT nullifier, t.pk, t.sk, t.scope, t.dindex, t.address, t.uncompressed FROM notes - JOIN transparent_address_accounts t ON notes.taddress = t.id_taddress - WHERE id_note = ?", - ) - .bind(*id) - .fetch_one(&mut *connection) - .await?; - - let _nf: Vec = row.get(0); - let pk: Vec = row.get(1); - let sk: Option> = row.get(2); - let scope: u32 = row.get(3); - let dindex_t: u32 = row.get(4); - let taddress: String = row.get(5); - let uncompressed: bool = row.get(6); - - if sk.is_none() { - can_sign = false; - } - - let pubkey = PublicKey::from_slice(&pk).unwrap(); - let mut hash = [0u8; 32]; - hash.copy_from_slice(&_nf[0..32]); - let n = u32::from_le_bytes(_nf[32..36].try_into().unwrap()); - let utxo = OutPoint::new(hash, n); - let pk_bytes = if uncompressed { - pubkey.serialize_uncompressed().to_vec() - } else { - pubkey.serialize().to_vec() - }; - let pkh: [u8; 20] = - Ripemd160::digest(Sha256::digest(&pk_bytes)).into(); - let addr = TransparentAddress::PublicKeyHash(pkh); - let coin = TxOut::new( - Zatoshis::from_u64(*amount).unwrap(), - addr.script().into(), - ); - - builder - .add_transparent_input( - TransparentInputInfo::from_parts( - utxo, - coin, - SpendInfo::P2pkh { pubkey }, - ) - .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?, - ); - tsk_dindex.push((pubkey, scope, dindex_t, taddress, uncompressed)); - } - 1 => { - let (note, scope, merkle_path) = get_sapling_note( - connection, - *id, - h.height, - svk.as_ref().unwrap(), - &es, - &ers, - ) - .await?; - - if ssk.is_none() { - can_sign = false; - } - - let dfvk = svk.as_ref().unwrap(); - let fvk = dfvk.to_fvk(scope); - builder.add_sapling_spend::(fvk, note, merkle_path)?; - s_scope.push(scope); - } - 2 => { - let (note, merkle_path) = get_orchard_note( - connection, - *id, - h.height, - ovk.as_ref().unwrap(), - &eo, - &ero, - orchard::NoteVersion::V2, - ) - .await?; - - if osk.is_none() { - can_sign = false; - } - - builder.add_orchard_spend::( - ovk.clone().unwrap(), - note, - merkle_path, - )?; - } - 3 => { - let (note, merkle_path) = get_orchard_note( - connection, - *id, - h.height, - ovk.as_ref().unwrap(), - &ei, - &ero, - orchard::NoteVersion::V3, - ) - .await?; - - if osk.is_none() { - can_sign = false; - } - - builder.add_ironwood_spend::( - ovk.clone().unwrap(), - note, - merkle_path, - )?; - } - _ => unreachable!(), - } - } - } - } - - // ── Add outputs ────────────────────────────────────────────────────── - event!(Level::INFO, "Adding Outputs"); - let mut n_outputs: [usize; NUM_POOLS as usize] = [0; NUM_POOLS as usize]; - - for r in &recipient_states { - let pool = r.pool_mask.to_best_pool().unwrap(); - let value = Zatoshis::from_u64(r.recipient.amount)?; - let memo = encode_memo(&r.recipient)?.unwrap_or(MemoBytes::empty()); - - n_outputs[pool as usize] += 1; - match pool { - 0 => { - if value != Zatoshis::ZERO { - let to = get_transparent_address(network, &r.recipient.address)?; - builder - .add_transparent_output(&to, value) - .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?; - } - } - 1 => { - let to = get_sapling_address(network, &r.recipient.address)?; - builder.add_sapling_output::( - svk.as_ref().map(|svk| svk.to_ovk(Scope::External)), - to, - value, - memo, - )?; - } - 2 => { - let to = get_orchard_address(network, &r.recipient.address)?; - let asset_base = if r.asset_base == [0u8; 32].to_vec() { - AssetBase::zatoshi() - } else { - let asset_bytes: [u8; 32] = r.asset_base.clone().try_into().map_err( - |v: Vec| anyhow!("Invalid asset_base length: expected 32, got {}", v.len()), - )?; - Option::from(AssetBase::from_bytes(&asset_bytes)) - .ok_or_else(|| anyhow!("Invalid asset_base bytes: {}", hex::encode(&asset_bytes)))? - }; - if migration { - // O->O self-send: use change output to avoid dummy-spend - // fee inflation (Orchard V3 disables cross-address transfers). - if let Some(ref fvk) = ovk { - builder.add_orchard_change_output::( - fvk.clone(), - Some(fvk.to_ovk(Scope::External)), - to, - value, - asset_base, - MemoBytes::empty(), - )?; - } else { - anyhow::bail!("No orchard key for migration change output"); - } - } else { - builder.add_orchard_output::( - ovk.as_ref().map(|ovk| ovk.to_ovk(Scope::External)), - to, - value, - asset_base, - memo, - )?; - } - } - 3 => { - let to = get_orchard_address(network, &r.recipient.address)?; - builder.add_ironwood_output::( - ovk.as_ref().map(|ovk| ovk.to_ovk(Scope::External)), - to, - value, - memo, - )?; - } - _ => {} - } - } - - // ── Add change output ──────────────────────────────────────────────── - if change > 0 { - let change_addr = if change_pool == 0 && tkeys.xvk.is_some() { - generate_next_change_address(network, connection, account) - .await? - .unwrap() - } else { - change_address.clone() - }; - match change_pool { - 0 => { - let to = get_transparent_address(network, &change_addr)?; - builder - .add_transparent_output(&to, Zatoshis::const_from_u64(change)) - .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?; - } - 1 => { - let to = get_sapling_address(network, &change_addr)?; - builder.add_sapling_output::( - svk.as_ref().map(|svk| svk.to_ovk(Scope::External)), - to, - Zatoshis::const_from_u64(change), - MemoBytes::empty(), - )?; - } - 2 => { - let to = get_orchard_address(network, &change_addr)?; - if let Some(ref fvk) = ovk { - builder.add_orchard_change_output::( - fvk.clone(), - Some(fvk.to_ovk(Scope::External)), - to, - Zatoshis::const_from_u64(change), - AssetBase::zatoshi(), - MemoBytes::empty(), - )?; - } else { - anyhow::bail!("No orchard key for change output"); - } - } - 3 => { - let to = get_orchard_address(network, &change_addr)?; - if let Some(ref fvk) = ovk { - builder.add_ironwood_output::( - Some(fvk.to_ovk(Scope::External)), - to, - Zatoshis::const_from_u64(change), - MemoBytes::empty(), - )?; - } else { - anyhow::bail!("No orchard key for ironwood change output"); - } - } - _ => {} - } - } - - // ── Build PCZT ─────────────────────────────────────────────────────── - info!("Building"); - event!(Level::INFO, "Preparing PCZT"); - - let r = builder.build_for_pczt(OsRng, &FeeRule::standard(), |_asset: &AssetBase| false)?; - let sapling_meta = &r.sapling_meta; - let orchard_meta = &r.orchard_meta; - let ironwood_meta = &r.ironwood_meta; - - let pczt = Creator::build_from_parts(r.pczt_parts).unwrap(); - info!("Created"); - - let updater = Updater::new(pczt); - let updater = updater - .update_transparent_with(|mut u| { - for (i, (pubkey, scope, dindex_t, taddress, uncompressed)) in - tsk_dindex.into_iter().enumerate() - { - u.update_input_with(i, |mut u| { - let derivation_path = vec![scope, dindex_t]; - let path = Bip32Derivation::parse([0u8; 32], derivation_path).unwrap(); - u.set_bip32_derivation(pubkey.serialize(), path); - u.set_proprietary("scope".to_string(), scope.to_le_bytes().to_vec()); - u.set_proprietary("dindex".to_string(), dindex_t.to_le_bytes().to_vec()); - u.set_proprietary("address".to_string(), taddress.into_bytes()); - u.set_proprietary("uncompressed".to_string(), vec![uncompressed as u8]); - let pk_bytes = if uncompressed { - pubkey.serialize_uncompressed().to_vec() - } else { - pubkey.serialize().to_vec() - }; - u.set_hash160_preimage(pk_bytes); - Ok(()) - })?; - } - Ok(()) - }) - .unwrap(); - - let updater = updater - .update_sapling_with(|mut u| { - for (c_input, scope) in s_scope.iter().enumerate() { - let bundle_index = sapling_meta.spend_index(c_input).unwrap(); - u.update_spend_with(bundle_index, |mut u| { - u.set_proprietary("scope".to_string(), scope.to_le_bytes().to_vec()); - Ok(()) - })?; - } - Ok(()) - }) - .unwrap(); - - let pczt = updater.finish(); - - let (pczt, _shielded_sighash) = IoFinalizer::new(pczt).finalize_io().unwrap(); - info!("IO Finalized"); - - let pczt_package = PcztPackage { - pczt: pczt.serialize().unwrap(), - n_spends: [n_spends[0], n_spends[1], n_spends[2], n_spends[3]], - sapling_indices: (0..n_spends[1]) - .map(|n| sapling_meta.spend_index(n).unwrap()) - .collect(), - orchard_indices: { - let mut indices: Vec = (0..n_spends[2]) - .map(|n| orchard_meta.spend_action_index(n).unwrap()) - .collect(); - // Change outputs (and migration recipient outputs) pair with - // a fabricated spend that needs signing. - // Applicable when change goes to Orchard, or when migration - // (all Orchard outputs use add_orchard_change_output). - if migration || (change_pool == 2 && change > 0) { - let mut n = 0; - while let Some(idx) = orchard_meta.output_action_index(n) { - if !indices.contains(&idx) { - indices.push(idx); - } - n += 1; - } - } - indices - }, - ironwood_indices: (0..n_spends[3]) - .map(|n| ironwood_meta.spend_action_index(n).unwrap()) - .collect(), - can_sign, - can_broadcast: false, - price: None, - category, - is_issuance: false, - }; - - Ok(pczt_package) -} - -#[allow(clippy::too_many_arguments)] -pub async fn plan_transaction_old( - network: &Network, - connection: &mut SqliteConnection, - client: &mut Client, - account: u32, - src_pools: u8, - recipients: &[Recipient], - recipient_pays_fee: bool, - confirmations: Option, - smart_transparent: bool, - category: Option, - issuance: Option<&IssuanceInfo>, - migration: bool, - preselected: Option<&[u32]>, -) -> Result { - let span = span!(Level::INFO, "transaction"); - span.in_scope(|| { - info!("Computing plan"); - }); - - let dindex = get_account_dindex(connection, account).await?; - let mut total_amount = 0; - let mut total_fiat = 0.0; - for r in recipients { - if let Some(price) = r.price { - total_fiat += price * r.amount as f64; - total_amount += r.amount; - } - } - let price = if total_amount != 0 { - Some(total_fiat / total_amount as f64) - } else { - None - }; - - let has_tex = recipients - .iter() - .any(|r| is_tex(network, &r.address).unwrap_or_default()); - info!("has_tex: {account} {has_tex}"); - - let mut can_sign = true; - let hw = get_account_hw(&mut *connection, account).await?; - let (use_internal,): (bool,) = - sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") - .bind(account) - .fetch_one(&mut *connection) - .await?; - - let height = client.latest_height().await?; - let ironwood_active = - network.is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height)); - info!("ironwood_active: {ironwood_active}"); - - let effective_src_pools = if has_tex || smart_transparent { - PoolMask::from_pool(0) // restrict to transparent pool - } else { - crate::pay::plan::get_effective_src_pools(&mut *connection, account, src_pools).await? - }; - // Include Ironwood (pool 3) in source pools when active, strip when not. - // Orchard and Ironwood share keys/addresses, and notes are stored in the - // Ironwood pool when NU6.3 is active. The caller's src_pools value predates - // Ironwood (typically T|S|O = 7), so we OR in the Ironwood bit here. - let effective_src_pools = if ironwood_active { - PoolMask(effective_src_pools.0 | 8) - } else { - PoolMask(effective_src_pools.0 & !8) - }; - - let recipients = recipients.to_vec(); - let mut recipient_pools = PoolMask(0); - for recipient in recipients.iter() { - let pool = PoolMask::from_address(&recipient.address)? - .intersect(&PoolMask(recipient.pools.unwrap_or(ALL_POOLS))); - // Orchard (pool 2) is spend-only when Ironwood is active. - // Migration mode allows Orchard outputs for the splitting phase. - let pool = if ironwood_active && !migration { - PoolMask(pool.0 & !4) - } else { - PoolMask(pool.0 & !8) - }; - recipient_pools = recipient_pools.union(&pool); - } - info!( - "effective_src_pools: {src_pools} {:#b}", - effective_src_pools.0 - ); - info!("recipient_pools: {:#b}", recipient_pools.0); - let change_pool = get_change_pool(effective_src_pools, recipient_pools); - // Orchard (pool 2) is spend-only when Ironwood is active; - // redirect change to Ironwood (pool 3). - // I and O share the same keys & addresses, so this is transparent to the user. - // Migration mode keeps change in Orchard for the splitting phase. - let change_pool = if ironwood_active && change_pool == 2 && !migration { - 3 - } else { - change_pool - }; - // Migration O→O splits must keep change in Orchard. - let change_pool = if migration { 2 } else { change_pool }; - // ZSA assets only exist in orchard; force change to orchard if any ZSA recipient. - // The ZEC change output also satisfies ZIP-226 (no dummy needed). - // Issuance also forces orchard change (needs orchard ZEC note for nullifier). - let has_zsa = recipients.iter().any(|r| r.asset_base != [0u8; 32]) || issuance.is_some(); - let change_pool = if has_zsa { 2 } else { change_pool }; - info!("change_pool: {:#b}", change_pool); - - // Pre-fetch change address (needed early by ZSA block) - let change_scope = if use_internal { 1 } else { 0 }; - let mut change_address = - get_account_full_address(network, connection, account, change_scope, hw).await?; - - // Issuance action counts stored for post-selection fee computation. - // total_issue_note_count: 2 for first issuance (reference + real), 1 otherwise. - // finalize only sets a flag on the action — it does NOT add a note, - // so it doesn't affect the fee. CREATION_COST is 0 in current zebra. - let issuance_action_info: Option<(u64, u64)> = issuance.map(|info| { - let issue_note_count: u64 = if info.first_issuance { 2 } else { 1 }; - let asset_creation_count: u64 = if info.first_issuance { 1 } else { 0 }; - (issue_note_count, asset_creation_count) - }); - - let confirmations = confirmations.unwrap_or_default(); - let max_height = height.saturating_sub(confirmations); - - let mut input_pools = vec![vec![]; NUM_POOLS as usize]; - let (mut inputs, recipients, recipient_pays_fee) = if smart_transparent { - // Restrict to using one transparent address per shielding - let mut notes = fetch_one_taddr_unspent_notes(connection, account).await?; - notes.retain(|n| n.height <= max_height); - // override the amount to the maximum amount available - let max = notes.iter().map(|n| n.amount).sum::(); - let recipient = Recipient { - amount: max, - ..recipients.first().cloned().unwrap_or_default() - }; - (notes, vec![recipient], true) - } else { - let mut notes = fetch_unspent_notes_grouped_by_pool(connection, account).await?; - notes.retain(|n| n.height <= max_height); - if let Some(ids) = preselected { - notes.retain(|n| ids.contains(&n.id)); - } - (notes, recipients, recipient_pays_fee) - }; - - let recipient_states = recipients - .into_iter() - .map(|r| RecipientState::new(r).unwrap()) - .map(|mut rs| { - if ironwood_active && !migration { - // Orchard (pool 2) is spend-only; strip it from recipient masks. - // Migration mode keeps Orchard for the splitting phase. - rs.pool_mask = PoolMask(rs.pool_mask.0 & !4); - } else { - // Ironwood (pool 3) is not active; strip it from recipient masks. - rs.pool_mask = PoolMask(rs.pool_mask.0 & !8); - } - rs - }) - .collect::>(); - - // ── ZSA block: handle non-ZEC recipients separately ────────────────── - let zec_key = [0u8; 32].to_vec(); - let (zsa_recipients, zec_recipients): (Vec<_>, Vec<_>) = recipient_states - .into_iter() - .partition(|r| r.asset_base != zec_key); - - let mut buffered_zsaspends: Vec = Vec::new(); - let mut buffered_zsaoutputs: Vec = Vec::new(); - - if !zsa_recipients.is_empty() { - // Aggregate needed amount per asset - let mut zsa_needed: HashMap, u64> = HashMap::new(); - for r in &zsa_recipients { - *zsa_needed.entry(r.asset_base.clone()).or_default() += r.recipient.amount; - } - - // Split orchard notes: ZSA notes get handled here, ZEC notes stay in inputs - let mut zsa_orchard_notes: HashMap, Vec> = HashMap::new(); - for note in inputs.iter() { - if note.pool == 2 && note.asset_base != zec_key { - zsa_orchard_notes - .entry(note.asset_base.clone()) - .or_default() - .push(note.clone()); - } - } - - // For each ZSA asset: select notes, track fees, buffer spends+outputs - for (asset_key, mut notes) in zsa_orchard_notes { - let needed = *zsa_needed.get(&asset_key).unwrap_or(&0); - if needed == 0 { - continue; - } - - let mut used = 0u64; - let mut total_selected = 0u64; - for note in notes.iter_mut() { - if used >= needed { - break; - } - let take = (note.remaining).min(needed - used); - note.remaining -= take; - used += take; - if note.is_used() { - total_selected += note.amount; - buffered_zsaspends.push(note.clone()); - info!( - "ZSA spend: id={} amount={} asset={}", - note.id, - note.amount, - hex::encode(&asset_key) - ); - } - } - if used < needed { - return Err(anyhow!( - "Not enough funds for asset {}: needed {}, available {}", - hex::encode(&asset_key), - needed, - used - )); - } - - // Buffer ZSA recipient outputs - for r in &zsa_recipients { - if r.asset_base == asset_key { - let mut rs = r.clone(); - rs.remaining = 0; - rs.pool_mask = PoolMask::from_pool(2); // ZSA only exists in orchard - buffered_zsaoutputs.push(rs); - } - } - - // ZSA change output (only if actual change) - let asset_change = total_selected.saturating_sub(needed); - if asset_change > 0 { - buffered_zsaoutputs.push(RecipientState { - recipient: Recipient { - address: change_address.clone(), - amount: asset_change, - asset_base: asset_key.clone(), - ..Recipient::default() - }, - remaining: 0, - pool_mask: PoolMask::from_pool(2), - asset_base: asset_key.clone(), - }); - } - } - } - - // Filter ZSA orchard notes from inputs — they're handled above or are - // non-ZEC and shouldn't be selected for ZEC payments. This must run - // regardless of whether there were ZSA recipients. - inputs = inputs - .into_iter() - .filter(|n| !(n.pool == 2 && n.asset_base != zec_key)) - .collect(); - - let recipient_states = zec_recipients; - - info!("Unspent notes:"); - for inp in inputs.iter() { - info!( - "id: {}, pool: {}, amount: {}", - inp.id, - inp.pool, - to_zec(inp.amount) - ); - } - - // group the inputs by pool - for (group, items) in inputs.into_iter().chunk_by(|inp| inp.pool).into_iter() { - // skip if the pool is not in the source pools - if effective_src_pools.0 & (1 << group) == 0 { - continue; - } - input_pools[group as usize].extend(items); - } - - // Remove notes too small to pay for even a single logical action. - for pool in input_pools.iter_mut() { - pool.retain(|n| n.amount >= COST_PER_ACTION); - } - - // we can merge notes from the same pool because they are fully fungible - // but we should keep the funds from different pools separate - // because even though they can participate in the same transaction - // they don't have the same properties. - // calculate_balance will return the balance for each pool - // and we have to pick up notes to send to the recipients - // There can be multiple recipients in the single transaction - // Recipients can accept multiple receivers when they use a unified address - // The simplest way to do this would be to choose any allowed receiver - // and then pick up randomly notes from the wallet until we cover the - // amount needed for the transaction - // but this could be inefficient and leak information about the wallet - // Instead we will choose based on the balances available and the - // recipients - // - // We use two passes. In the first pass, we only consider the recipients - // that have single receiver addresses. For these, there is no option - // to choose the receiver. The only decision we need to make is to - // choose what pool to use for the inputs. - // This is handled by the function fill_single_receivers - // - let double_mask = if ironwood_active { - // Migration mode: allow Orchard outputs, so double receivers are S|O - if migration { - PoolMask(6) - } else { - PoolMask(10) - } // S(2)|O(4) or S(2)|I(8) - } else { - PoolMask(6) // S(2) | O(4) - }; - let (mut single, mut double) = recipient_states - .into_iter() - .partition::, _>(|r| r.pool_mask != double_mask); - - fill_single_receivers(&mut input_pools, &mut single, ironwood_active, migration)?; - - // In the second pass, we will consider the recipients that have - // multiple receivers. We always favor shielded receivers over - // transparent ones. Hence, if a UA has a transparent and a - // sapling receiver, it counts as a single sapling receiver. - // Then, the only time we can have a multiple receiver recipient - // is when we have a sapling and an ironwood receiver, ie. - // when we have to choose between shielded pools. - // (Orchard is spend-only when Ironwood is active.) - - let balances = input_pools - .iter() - .map(|pool| pool.iter().map(|n| n.remaining).sum::()) - .collect::>(); - - // In the second pass, we constrain the receiver to be the change pool - // or the pool that we have the most balance in if the change pool is transparent - // This is because we hope to minimize the amount that would have to go through the - // turnstile. - - let largest_shielded_pool = if change_pool != 0 { - PoolMask::from_pool(change_pool) - } else if ironwood_active && balances[3] > balances[1] { - PoolMask(8) // Ironwood - } else { - PoolMask(2) // Sapling - }; - - for d in double.iter_mut() { - d.pool_mask = largest_shielded_pool; - } - - fill_single_receivers(&mut input_pools, &mut double, ironwood_active, migration)?; - - // ── Build FeeManager from actual inputs and outputs ────────────────── - let mut fee_manager = build_fee_manager( - &input_pools, - &buffered_zsaspends, - &single, - &double, - &buffered_zsaoutputs, - change_pool, - issuance_action_info, - migration, - ); - - info!("Fee {}", &fee_manager); - let mut fee = fee_manager.fee(); - - // ── Check all recipients fully funded ──────────────────────────────── - { - let recipients = single.iter().chain(double.iter()); - for r in recipients { - if r.remaining > 0 { - return Err(Error::NotEnoughFunds(to_zec(r.remaining)).into()); - } - } - } - - // ── Handle fee payment ─────────────────────────────────────────────── - if recipient_pays_fee { - let first = single - .first_mut() - .or_else(|| double.first_mut()) - .ok_or_else(|| Error::NotEnoughFunds(to_zec(fee)))?; - if first.recipient.amount < fee { - return Err(Error::NotEnoughFunds(to_zec(fee - first.recipient.amount)).into()); - } - first.recipient.amount -= fee; - } - - // Compute total input and output - let total_output = single - .iter() - .chain(double.iter()) - .map(|r| r.recipient.amount) - .sum::(); - - let compute_total_input = |input_pools: &[Vec]| -> u64 { - input_pools - .iter() - .map(|pool| { - pool.iter() - .map(|n| if n.is_used() { n.amount } else { 0 }) - .sum::() - }) - .sum() - }; - - let mut total_input = compute_total_input(&input_pools); - - if !recipient_pays_fee { - // Preliminary change before fee - let change_before_fee = total_input.saturating_sub(total_output); - - if change_before_fee >= fee { - // Fee fully covered by change — no additional notes needed - } else { - // Need to select additional notes to cover the fee shortfall - let deficit = total_output + fee - total_input; - - // Track current inputs per pool (for marginal fee cost computation) - let mut input_counts: [u8; NUM_POOLS as usize] = [0; NUM_POOLS as usize]; - for (pi, pool_inputs) in input_pools.iter().enumerate() { - input_counts[pi] = pool_inputs.iter().filter(|n| n.is_used()).count() as u8; - } - // Include buffered ZSA spends - input_counts[2] += buffered_zsaspends.len() as u8; - - // Helper: compute marginal fee cost of adding one input to a pool. - // Uses FeeManager so migration-mode (O→O sum) is handled correctly. - let marginal_cost = |pool: u8| -> u64 { - let mut fm = fee_manager.clone(); - fm.add_input(pool); - fm.fee().saturating_sub(fee_manager.fee()) - }; - - // Determine which pools already have used inputs - let used_bitmap: u8 = input_counts - .iter() - .enumerate() - .filter(|(_, &c)| c > 0) - .fold(0u8, |acc, (i, _)| acc | (1 << i as u8)); - - // Priority order: used pools (I→O→S→T), then unused pools (I→O→S→T) - let priority_pools: Vec = [3u8, 2, 1, 0] - .iter() - .filter(|&&p| used_bitmap & (1 << p) != 0) - .chain( - [3u8, 2, 1, 0] - .iter() - .filter(|&&p| used_bitmap & (1 << p) == 0), - ) - .copied() - .collect(); - - let mut deficit = deficit as i64; - - for &pool in &priority_pools { - if deficit <= 0 { - break; - } - for inp in input_pools[pool as usize].iter_mut() { - if deficit <= 0 { - break; - } - if inp.remaining == 0 { - continue; - } - - // If already counted by FeeManager, no marginal action cost. - let is_new = !inp.is_used(); - let mc = if is_new { - marginal_cost(pool) as i64 - } else { - 0 - }; - let take = (inp.remaining as i64).min(deficit + mc); - inp.remaining -= take as u64; - deficit = deficit + mc - take; - if is_new { - input_counts[pool as usize] += 1; - } - - info!( - "Fee note: id={}, amount={}, taken={}, deficit_after={}", - inp.id, - to_zec(inp.amount), - to_zec(take as u64), - to_zec(if deficit > 0 { deficit as u64 } else { 0 }) - ); - } - } - - if deficit > 0 { - return Err(Error::NotEnoughFunds(to_zec(deficit as u64)).into()); + pool_mask: PoolMask::from_pool(pool), + asset_base: dr.asset_base.clone(), } + }) + .collect(); - // Rebuild fee_manager with the new inputs and recompute fee - fee_manager = build_fee_manager( - &input_pools, - &buffered_zsaspends, - &single, - &double, - &buffered_zsaoutputs, - change_pool, - issuance_action_info, - migration, - ); - fee = fee_manager.fee(); - total_input = compute_total_input(&input_pools); - info!("Fee (after fee-note selection) {}", &fee_manager); - - // Ensure recomputed fee doesn't exceed available funds - if total_input < total_output + fee { - return Err(anyhow!( - "Insufficient funds after fee recomputation: total_input={} < total_output={} + fee={}", - to_zec(total_input), - to_zec(total_output), - to_zec(fee) - )); - } - } + // Append ZSA change outputs (ZIP-226: ZEC outputs before ZSA outputs) + for (asset, change_amount) in &zsa_changes { + recipient_states.push(RecipientState { + recipient: Recipient { + address: String::new(), // filled in below with change_address + amount: *change_amount, + asset_base: asset.to_vec(), + ..Recipient::default() + }, + remaining: 0, + pool_mask: PoolMask::from_pool(2), // ZSA always Orchard + asset_base: asset.to_vec(), + }); } - let change = total_input.saturating_sub(total_output + fee); + // ── Fee, totals, and change (select_notes already validated feasibility) ─ + // Issuance actions add separate logical actions on top of regular pool + // actions (ZIP-233). First issuance: 2 notes (reference + real), reissuance: 1. + let issuance_fee = issuance + .map(|info| if info.first_issuance { 2 } else { 1 } * COST_PER_ACTION) + .unwrap_or(0); + let fee = selection.fee + issuance_fee; + info!("Fee (select_notes + issuance): {}", to_zec(fee)); - for o in single.iter_mut().chain(double.iter_mut()) { - let RecipientState { - recipient, - remaining, - pool_mask, - .. - } = o; - if *remaining != 0 { - return Err(anyhow!( - "Recipient {} not fully funded: remaining {}", - recipient.address, - to_zec(*remaining) - )); + // When the recipient pays the fee, deduct it from the first recipient + // so the sender only needs to cover (total_output - fee), matching the + // solver's target of `output_sum` (without fee). + if recipient_pays_fee { + if let Some(first) = recipient_states.first_mut() { + first.recipient.amount = first.recipient.amount.saturating_sub(fee); } - info!( - "address: {}, pool: {}, amount: {}", - recipient.address, - pool_mask.to_best_pool().unwrap(), - to_zec(recipient.amount) - ); } + let total_output: u64 = recipient_states.iter().map(|r| r.recipient.amount).sum(); + let total_input: u64 = selection.inputs.iter().map(|n| n.amount).sum(); + let change = total_input.saturating_sub(total_output + fee); + info!( "change: {}, pool: {change_pool}, fee: {}", to_zec(change), to_zec(fee) ); + // ── Log outputs ────────────────────────────────────────────────────── + for r in &recipient_states { + info!( + "address: {}, pool: {}, amount: {}", + r.recipient.address, + r.pool_mask.to_best_pool().unwrap(), + to_zec(r.recipient.amount) + ); + } + + // ── Fetch tree states and anchors ──────────────────────────────────── let h = crate::sync::get_db_height(connection, account).await?; let (ts, to, ti) = crate::sync::get_tree_state(network, client, h.height).await?; let es = ts.to_edge(&SaplingHasher::default()); @@ -1461,22 +536,23 @@ pub async fn plan_transaction_old( let orchard_anchor = eo.root(&OrchardHasher::default()); let ironwood_anchor = ei.root(&OrchardHasher::default()); - // Check if there are any inputs or outputs for each shielded pool; - // if not, skip the respective anchor to avoid unnecessary anchor requirements. + // Determine which pools are active in this transaction let mut has_pool = [false; NUM_POOLS as usize]; for pool in 1..NUM_POOLS { let p = pool as u8; has_pool[pool] = input_pools[pool].iter().any(|inp| inp.is_used()) - || single.iter().any(|r| r.pool_mask.to_best_pool() == Some(p)) - || double.iter().any(|r| r.pool_mask.to_best_pool() == Some(p)) + || recipient_states.iter().any(|r| r.pool_mask.to_best_pool() == Some(p)) || change_pool == p; } - // Orchard (pool 2) also includes buffered ZSA spends and outputs. - has_pool[2] |= !buffered_zsaspends.is_empty() || !buffered_zsaoutputs.is_empty(); - // Ironwood (pool 3) only when the network upgrade is active. has_pool[3] &= ironwood_active; + // ZSA assets only exist in Orchard pool; ensure pool 2 is active + // when ZSA is present (covers issuance-only case with no ZSA notes). + has_pool[2] |= has_zsa; - // Update change address for transparent pool (orchard was pre-fetched) + // ── Fetch change address ───────────────────────────────────────────── + let change_scope = if use_internal { 1 } else { 0 }; + let mut change_address = + get_account_full_address(network, connection, account, change_scope, hw).await?; let tkeys = select_account_transparent(connection, account, dindex).await?; if change_pool == 0 && tkeys.xvk.is_some() { change_address = generate_next_change_address(network, connection, account) @@ -1484,17 +560,20 @@ pub async fn plan_transaction_old( .unwrap(); } - let mut outputs = single - .iter() - .chain(double.iter()) - .cloned() - .collect::>(); - - // Flush buffered ZSA outputs (ZSA-after-ZEC for ZIP-226) - outputs.extend(buffered_zsaoutputs); + // Fill in ZSA change output addresses + for rs in &mut recipient_states { + if rs.recipient.address.is_empty() && rs.asset_base != zec_key.to_vec() { + rs.recipient.address = change_address.clone(); + } + } - info!("Initializing Builder"); + // ── Fetch keys ─────────────────────────────────────────────────────── + let svk = get_sapling_vk(connection, account).await?; + let ovk = get_orchard_vk(connection, account).await?; + let ssk = get_sapling_sk(&mut *connection, account).await?; + let osk = get_orchard_sk(&mut *connection, account).await?; + // ── Build transaction ──────────────────────────────────────────────── let current_height = client.latest_height().await?; let target_height = current_height; @@ -1520,27 +599,17 @@ pub async fn plan_transaction_old( let es = es.to_auth_path(&SaplingHasher::default()); let eo = eo.to_auth_path(&OrchardHasher::default()); let ei = ei.to_auth_path(&OrchardHasher::default()); - let ers = empty_roots(&SaplingHasher::default()); let ero = empty_roots(&OrchardHasher::default()); - // Ironwood shares the same hasher (and empty roots) as Orchard. - - let svk = get_sapling_vk(connection, account).await?; - let ovk = get_orchard_vk(connection, account).await?; let mut tsk_dindex = vec![]; let mut s_scope = vec![]; event!(Level::INFO, "Adding Inputs"); - let ssk = get_sapling_sk(&mut *connection, account).await?; - let osk = get_orchard_sk(&mut *connection, account).await?; - - // Flush buffered ZSA orchard spends into input_pools[2] (ZEC spends already there) - input_pools[2].extend(buffered_zsaspends); - let mut n_spends: [usize; NUM_POOLS as usize] = [0; NUM_POOLS as usize]; - let mut inputs = vec![]; + let mut can_sign = true; + for pool in input_pools.iter() { for inp in pool.iter() { if inp.is_used() { @@ -1548,11 +617,6 @@ pub async fn plan_transaction_old( id, amount, pool, .. } = inp; n_spends[*pool as usize] += 1; - inputs.push(TxPlanIn { - amount: Some(*amount), - pool: *pool, - asset_name: "ZEC".to_string(), - }); match pool { 0 => { let row = sqlx::query( @@ -1568,7 +632,7 @@ pub async fn plan_transaction_old( let pk: Vec = row.get(1); let sk: Option> = row.get(2); let scope: u32 = row.get(3); - let dindex: u32 = row.get(4); + let dindex_t: u32 = row.get(4); let taddress: String = row.get(5); let uncompressed: bool = row.get(6); @@ -1586,21 +650,24 @@ pub async fn plan_transaction_old( } else { pubkey.serialize().to_vec() }; - let pkh: [u8; 20] = Ripemd160::digest(Sha256::digest(&pk_bytes)).into(); + let pkh: [u8; 20] = + Ripemd160::digest(Sha256::digest(&pk_bytes)).into(); let addr = TransparentAddress::PublicKeyHash(pkh); - let coin = - TxOut::new(Zatoshis::from_u64(*amount).unwrap(), addr.script().into()); - - info!("Adding transparent input {}", hex::encode(utxo.hash())); - builder.add_transparent_input( - TransparentInputInfo::from_parts( - utxo, - coin, - SpendInfo::P2pkh { pubkey }, - ) - .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?, + let coin = TxOut::new( + Zatoshis::from_u64(*amount).unwrap(), + addr.script().into(), ); - tsk_dindex.push((pubkey, scope, dindex, taddress, uncompressed)); + + builder + .add_transparent_input( + TransparentInputInfo::from_parts( + utxo, + coin, + SpendInfo::P2pkh { pubkey }, + ) + .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?, + ); + tsk_dindex.push((pubkey, scope, dindex_t, taddress, uncompressed)); } 1 => { let (note, scope, merkle_path) = get_sapling_note( @@ -1617,16 +684,13 @@ pub async fn plan_transaction_old( can_sign = false; } - info!( - "Adding sapling input {}", - hex::encode(note.cmu().to_bytes()) - ); let dfvk = svk.as_ref().unwrap(); let fvk = dfvk.to_fvk(scope); builder.add_sapling_spend::(fvk, note, merkle_path)?; s_scope.push(scope); } 2 => { + let (note, merkle_path) = get_orchard_note( connection, *id, @@ -1642,12 +706,6 @@ pub async fn plan_transaction_old( can_sign = false; } - info!( - "Adding orchard input {}", - hex::encode( - ExtractedNoteCommitment::from(note.commitment()).to_bytes() - ) - ); builder.add_orchard_spend::( ovk.clone().unwrap(), note, @@ -1655,7 +713,6 @@ pub async fn plan_transaction_old( )?; } 3 => { - // Ironwood reuses Orchard keys and note structure. let (note, merkle_path) = get_orchard_note( connection, *id, @@ -1671,12 +728,6 @@ pub async fn plan_transaction_old( can_sign = false; } - info!( - "Adding ironwood input {}", - hex::encode( - ExtractedNoteCommitment::from(note.commitment()).to_bytes() - ) - ); builder.add_ironwood_spend::( ovk.clone().unwrap(), note, @@ -1685,85 +736,31 @@ pub async fn plan_transaction_old( } _ => unreachable!(), } - - let (nf,): (Vec,) = - sqlx::query_as("SELECT nullifier FROM notes WHERE id_note = ?") - .bind(id) - .fetch_one(&mut *connection) - .await?; - - info!( - "id: {id}, pool: {pool}, nullifier: {}, amount: {}", - hex::encode(nf), - to_zec(*amount) - ); } } } + // ── Add outputs ────────────────────────────────────────────────────── event!(Level::INFO, "Adding Outputs"); let mut n_outputs: [usize; NUM_POOLS as usize] = [0; NUM_POOLS as usize]; - let mut outs = vec![]; - for r in outputs.iter() { - let RecipientState { - recipient, - remaining, - pool_mask, - .. - } = r; - if *remaining != 0 { - return Err(anyhow!( - "Output for {} not fully funded: remaining {}", - recipient.address, - to_zec(*remaining) - )); - } - if !pool_mask.single_pool() { - return Err(anyhow!( - "Output for {} has ambiguous pool mask: {:#b}", - recipient.address, - pool_mask.0 - )); - } - - outs.push(TxPlanOut { - pool: pool_mask.to_best_pool().unwrap(), - amount: recipient.amount, - address: recipient.address.clone(), - asset_name: recipient - .asset_name - .clone() - .unwrap_or_else(|| "ZEC".to_string()), - }); - let pool = pool_mask.to_best_pool().unwrap(); - let value = Zatoshis::from_u64(recipient.amount)?; - let memo = encode_memo(recipient)?.unwrap_or(MemoBytes::empty()); + for r in &recipient_states { + let pool = r.pool_mask.to_best_pool().unwrap(); + let value = Zatoshis::from_u64(r.recipient.amount)?; + let memo = encode_memo(&r.recipient)?.unwrap_or(MemoBytes::empty()); n_outputs[pool as usize] += 1; match pool { 0 => { - // Don't add transparent outputs that have no value - // because it is considered dust by the zcashd nodes if value != Zatoshis::ZERO { - let to = get_transparent_address(network, &recipient.address)?; - info!( - "Adding transparent output {} {}", - &recipient.address, - to_zec(value.into()) - ); + let to = get_transparent_address(network, &r.recipient.address)?; builder .add_transparent_output(&to, value) .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?; } } 1 => { - let to = get_sapling_address(network, &recipient.address)?; - info!( - "Adding sapling output {} {}", - &recipient.address, - to_zec(value.into()) - ); + let to = get_sapling_address(network, &r.recipient.address)?; builder.add_sapling_output::( svk.as_ref().map(|svk| svk.to_ovk(Scope::External)), to, @@ -1772,29 +769,19 @@ pub async fn plan_transaction_old( )?; } 2 => { - // Orchard output (ZSA tokens or ZEC where recipient only has orchard). - // For non-ZSA ZEC, this path should be rare since ironwood is preferred. - let to = get_orchard_address(network, &recipient.address)?; - let asset_base = if r.asset_base == zec_key { + let to = get_orchard_address(network, &r.recipient.address)?; + let asset_base = if r.asset_base == [0u8; 32].to_vec() { AssetBase::zatoshi() } else { - let asset_bytes: [u8; 32] = - r.asset_base.clone().try_into().map_err(|v: Vec| { - anyhow!("Invalid asset_base length: expected 32, got {}", v.len()) - })?; - Option::from(AssetBase::from_bytes(&asset_bytes)).ok_or_else(|| { - anyhow!("Invalid asset_base bytes: {}", hex::encode(&asset_bytes)) - })? + let asset_bytes: [u8; 32] = r.asset_base.clone().try_into().map_err( + |v: Vec| anyhow!("Invalid asset_base length: expected 32, got {}", v.len()), + )?; + Option::from(AssetBase::from_bytes(&asset_bytes)) + .ok_or_else(|| anyhow!("Invalid asset_base bytes: {}", hex::encode(&asset_bytes)))? }; - if migration { - // Migration splitting (O→O self-send): outputs go back to - // the wallet's own address — use change output to avoid - // dummy-spend fee inflation. - info!( - "Adding orchard change output (migration) {} {}", - &recipient.address, - to_zec(value.into()) - ); + if ironwood_active { + // O->O self-send: use change output to avoid dummy-spend + // fee inflation (Orchard V3 disables cross-address transfers). if let Some(ref fvk) = ovk { builder.add_orchard_change_output::( fvk.clone(), @@ -1808,12 +795,6 @@ pub async fn plan_transaction_old( anyhow::bail!("No orchard key for migration change output"); } } else { - info!( - "Adding orchard output {} {} asset={}", - &recipient.address, - to_zec(value.into()), - hex::encode(&r.asset_base) - ); builder.add_orchard_output::( ovk.as_ref().map(|ovk| ovk.to_ovk(Scope::External)), to, @@ -1824,14 +805,7 @@ pub async fn plan_transaction_old( } } 3 => { - // Ironwood output. IW uses the same addresses/keys as Orchard. - // ZSA tokens are not supported in Ironwood (always ZEC). - let to = get_orchard_address(network, &recipient.address)?; - info!( - "Adding ironwood output {} {}", - &recipient.address, - to_zec(value.into()) - ); + let to = get_orchard_address(network, &r.recipient.address)?; builder.add_ironwood_output::( ovk.as_ref().map(|ovk| ovk.to_ovk(Scope::External)), to, @@ -1843,11 +817,9 @@ pub async fn plan_transaction_old( } } - // Add change output using the proper change method (avoids dummy spend - // inflation that would mismatch the FeeManager calculation). + // ── Add change output ──────────────────────────────────────────────── if change > 0 { let change_addr = if change_pool == 0 && tkeys.xvk.is_some() { - // Re-fetch transparent change address generate_next_change_address(network, connection, account) .await? .unwrap() @@ -1871,23 +843,29 @@ pub async fn plan_transaction_old( )?; } 2 => { - info!(""); - // Orchard change (ZSA or pre-ironwood). ZSA forces change_pool=2 - // to satisfy the orchard ZEC nullifier requirement. let to = get_orchard_address(network, &change_addr)?; - if let Some(ref fvk) = ovk { - builder.add_orchard_change_output::( - fvk.clone(), - Some(fvk.to_ovk(Scope::External)), + if ironwood_active { + if let Some(ref fvk) = ovk { + builder.add_orchard_change_output::( + fvk.clone(), + Some(fvk.to_ovk(Scope::External)), + to, + Zatoshis::const_from_u64(change), + AssetBase::zatoshi(), + MemoBytes::empty(), + )?; + } else { + anyhow::bail!("No orchard key for change output"); + } + } else { + builder.add_orchard_output::( + ovk.as_ref().map(|ovk| ovk.to_ovk(Scope::External)), to, Zatoshis::const_from_u64(change), - orchard::note::AssetBase::zatoshi(), + AssetBase::zatoshi(), MemoBytes::empty(), )?; - } else { - anyhow::bail!("No orchard key for change output"); } - info!(""); } 3 => { let to = get_orchard_address(network, &change_addr)?; @@ -1906,6 +884,7 @@ pub async fn plan_transaction_old( } } + // ── Build PCZT ─────────────────────────────────────────────────────── info!("Building"); event!(Level::INFO, "Preparing PCZT"); @@ -1919,137 +898,28 @@ pub async fn plan_transaction_old( builder.set_zsa_builder(zsa); } - // we pass false to the fee rule callback because Zebra does not track new ZSA issuance and does not - // charge the CREATION_COST let r = builder.build_for_pczt(OsRng, &FeeRule::standard(), |_asset: &AssetBase| false)?; let sapling_meta = &r.sapling_meta; let orchard_meta = &r.orchard_meta; let ironwood_meta = &r.ironwood_meta; - info!("Prepared"); - info!( - "orchard_protocol_revision: {:?}", - r.pczt_parts.consensus_branch_id.orchard_protocol_revision() - ); - - // ── Trace builder output ────────────────────────────────────────────── - { - let parts = &r.pczt_parts; - info!("=== Builder Output ==="); - info!( - " version={:?} branch={:?} lock_time={} expiry={} fee={}", - parts.version, - parts.consensus_branch_id, - parts.lock_time, - u32::from(parts.expiry_height), - fee - ); - // Transparent - if let Some(ref t) = parts.transparent { - info!( - " Transparent: inputs={} outputs={}", - t.inputs().len(), - t.outputs().len() - ); - for (i, inp) in t.inputs().iter().enumerate() { - info!( - " txin[{}]: prevout={}:{} seq={}", - i, - hex::encode(inp.prevout_txid().as_ref()), - inp.prevout_index(), - inp.sequence().unwrap_or(0) - ); - } - for (i, out) in t.outputs().iter().enumerate() { - info!(" txout[{}]: value={}", i, u64::from(*out.value())); - } - } else { - info!(" Transparent: "); - } - // Sapling - if let Some(ref s) = parts.sapling { - let vb: i64 = i64::try_from(*s.value_sum()).unwrap_or(0); - info!( - " Sapling: spends={} outputs={} valueBalance={} anchor={}", - s.spends().len(), - s.outputs().len(), - vb, - hex::encode(s.anchor().to_bytes()) - ); - for (i, sp) in s.spends().iter().enumerate() { - let rk_bytes: [u8; 32] = sp.rk().clone().into(); - info!( - " spend[{}]: cv={} nf={} rk={}", - i, - hex::encode(sp.cv().to_bytes()), - hex::encode(sp.nullifier().0), - hex::encode(rk_bytes) - ); - } - for (i, out) in s.outputs().iter().enumerate() { - info!( - " output[{}]: cv={} cmu={} epk={}", - i, - hex::encode(out.cv().to_bytes()), - hex::encode(out.cmu().to_bytes()), - hex::encode(out.ephemeral_key().0) - ); - } - } else { - info!(" Sapling: "); - } - // Orchard - if let Some(ref o) = parts.orchard { - let vb: i64 = i64::try_from(*o.value_sum()).unwrap_or(0); - info!( - " Orchard: actions={} valueBalance={}", - o.actions().len(), - vb - ); - for (i, act) in o.actions().iter().enumerate() { - let nf_bytes = act.spend().nullifier().to_bytes(); - info!(" action[{}]: nf={}", i, hex::encode(nf_bytes)); - } - } else { - info!(" Orchard: "); - } - // Ironwood - if let Some(ref iw) = parts.ironwood { - let vb: i64 = i64::try_from(*iw.value_sum()).unwrap_or(0); - info!( - " Ironwood: actions={} valueBalance={}", - iw.actions().len(), - vb - ); - for (i, act) in iw.actions().iter().enumerate() { - let nf_bytes = act.spend().nullifier().to_bytes(); - info!(" action[{}]: nf={}", i, hex::encode(nf_bytes)); - } - } else { - info!(" Ironwood: "); - } - info!("=== End Builder Output ==="); - } - let pczt = Creator::build_from_parts(r.pczt_parts).unwrap(); info!("Created"); let updater = Updater::new(pczt); let updater = updater .update_transparent_with(|mut u| { - for (i, (pubkey, scope, dindex, taddress, uncompressed)) in + for (i, (pubkey, scope, dindex_t, taddress, uncompressed)) in tsk_dindex.into_iter().enumerate() { u.update_input_with(i, |mut u| { - let derivation_path = vec![scope, dindex]; + let derivation_path = vec![scope, dindex_t]; let path = Bip32Derivation::parse([0u8; 32], derivation_path).unwrap(); u.set_bip32_derivation(pubkey.serialize(), path); u.set_proprietary("scope".to_string(), scope.to_le_bytes().to_vec()); - u.set_proprietary("dindex".to_string(), dindex.to_le_bytes().to_vec()); + u.set_proprietary("dindex".to_string(), dindex_t.to_le_bytes().to_vec()); u.set_proprietary("address".to_string(), taddress.into_bytes()); u.set_proprietary("uncompressed".to_string(), vec![uncompressed as u8]); - // Set the hash160 preimage with the public key in the correct format - // This is needed for the signer to find the correct pubkey when verifying let pk_bytes = if uncompressed { pubkey.serialize_uncompressed().to_vec() } else { @@ -2072,102 +942,6 @@ pub async fn plan_transaction_old( Ok(()) })?; } - - let mut c_output = 0; - for o in outputs.iter() { - let pool = o.pool_mask.to_best_pool().unwrap(); - if pool != 1 { - continue; - } - let bundle_index = sapling_meta.output_index(c_output).unwrap(); - u.update_output_with(bundle_index, |mut u| { - u.set_user_address(o.recipient.address.clone()); - Ok(()) - })?; - c_output += 1; - } - - Ok(()) - }) - .unwrap(); - - // Look up human-readable asset names from the assets table. - let asset_names: HashMap, String> = sqlx::query( - "SELECT asset_base, asset_name FROM assets WHERE asset_name IS NOT NULL AND asset_name != ''", - ) - .map(|row: SqliteRow| { - let base: Vec = row.get(0); - let name: String = row.get(1); - (base, name) - }) - .fetch_all(&mut *connection) - .await? - .into_iter() - .collect(); - - let updater = updater - .update_orchard_with(|mut u| { - // Collect asset info for ALL actions upfront (before any mutable - // access) so we can set proprietary on every action, including - // split spends, dummy outputs, and padding actions. - let action_count = u.bundle().actions().len(); - let action_assets: Vec<(Option, orchard::note::AssetBase)> = - (0..action_count) - .map(|idx| { - let a = &u.bundle().actions()[idx]; - (Some(a.spend().asset()), a.output().asset()) - }) - .collect(); - - for action_idx in 0..action_count { - let (spend_asset_opt, output_asset) = &action_assets[action_idx]; - - let resolve = |a: &orchard::note::AssetBase| -> String { - if bool::from(a.is_zatoshi()) { - "ZEC".to_string() - } else { - let bytes = a.to_bytes().to_vec(); - asset_names - .get(&bytes) - .cloned() - .unwrap_or_else(|| hex::encode(&bytes)) - } - }; - let spend_name = match spend_asset_opt { - Some(a) => resolve(a), - None => "ZEC".to_string(), - }; - let output_name = resolve(output_asset); - - u.update_action_with(action_idx, |mut u| { - u.set_spend_proprietary( - "asset_name".to_string(), - spend_name.as_bytes().to_vec(), - ); - u.set_output_proprietary( - "asset_name".to_string(), - output_name.as_bytes().to_vec(), - ); - Ok(()) - })?; - } - - // Set user_address on actions that have a real output (tracked - // by output_action_index). - let mut i = 0; - for o in outputs.iter() { - let pool = o.pool_mask.to_best_pool().unwrap(); - if pool != 2 { - continue; - } - let bundle_index = orchard_meta.output_action_index(i).unwrap(); - u.update_action_with(bundle_index, |mut u| { - u.set_output_user_address(o.recipient.address.clone()); - Ok(()) - })?; - i += 1; - } - Ok(()) }) .unwrap(); @@ -2200,27 +974,19 @@ pub async fn plan_transaction_old( pczt }; + let n_orchard_actions = pczt.orchard().actions().len(); let pczt_package = PcztPackage { pczt: pczt.serialize().unwrap(), n_spends: [n_spends[0], n_spends[1], n_spends[2], n_spends[3]], sapling_indices: (0..n_spends[1]) .map(|n| sapling_meta.spend_index(n).unwrap()) .collect(), - orchard_indices: { - let mut indices: Vec = (0..n_spends[2]) + orchard_indices: if ironwood_active { + (0..n_orchard_actions).collect() + } else { + (0..n_spends[2]) .map(|n| orchard_meta.spend_action_index(n).unwrap()) - .collect(); - // Include change-output action indices: each change output pairs - // with a fabricated spend that needs signing when cross-address - // transfers are disabled (Orchard V3 / NU6.3+). - let mut n = 0; - while let Some(idx) = orchard_meta.output_action_index(n) { - if !indices.contains(&idx) { - indices.push(idx); - } - n += 1; - } - indices + .collect() }, ironwood_indices: (0..n_spends[3]) .map(|n| ironwood_meta.spend_action_index(n).unwrap()) @@ -2234,7 +1000,6 @@ pub async fn plan_transaction_old( Ok(pczt_package) } - fn encode_memo(recipient: &Recipient) -> Result> { let text_memo = recipient .user_memo @@ -2564,205 +1329,6 @@ fn get_orchard_address(network: &Network, address: &str) -> Result
{ } } -fn fill_single_receivers( - input_pools: &mut [Vec], - recipients: &mut [RecipientState], - ironwood_active: bool, - migration: bool, -) -> Result<()> { - // Fill order: Ironwood > Orchard > Sapling > Transparent. - // When Ironwood is active, Orchard (pool 2) is spend-only \u{2014} no outputs - // to orchard allowed (unless migration mode). - let fill_order: &[(u8, u8)] = if ironwood_active { - if migration { - &[ - (3, 3), // I\u{2192}I - (2, 2), // O\u{2192}O (migration splitting) - (1, 1), // S\u{2192}S (intra-pool) - (3, 1), - (2, 1), // I\u{2192}S, O\u{2192}S - (1, 3), // S\u{2192}I - (2, 3), // O\u{2192}I - (1, 2), // S\u{2192}O (migration splitting) - (3, 2), // I\u{2192}O (migration splitting) - (0, 3), - (0, 2), - (0, 1), // T\u{2192}I, T\u{2192}O, T\u{2192}S - (3, 0), - (2, 0), - (1, 0), // I\u{2192}T, O\u{2192}T, S\u{2192}T - (0, 0), // T\u{2192}T - ] - } else { - &[ - (3, 3), // I\u{2192}I - (1, 1), // S\u{2192}S (intra-pool) - (3, 1), - (2, 1), // I\u{2192}S, O\u{2192}S - (1, 3), // S\u{2192}I - (2, 3), // O\u{2192}I - (0, 3), - (0, 1), // T\u{2192}I, T\u{2192}S - (3, 0), - (2, 0), - (1, 0), // I\u{2192}T, O\u{2192}T, S\u{2192}T - (0, 0), // T\u{2192}T - ] - } - } else { - &[ - (2, 2), - (1, 1), // O\u{2192}O, S\u{2192}S - (2, 1), - (1, 2), // O\u{2192}S, S\u{2192}O - (0, 2), - (0, 1), // T\u{2192}O, T\u{2192}S - (2, 0), - (1, 0), // O\u{2192}T, S\u{2192}T - (0, 0), // T\u{2192}T - ] - }; - - for (src, dst) in fill_order { - for r in recipients.iter_mut() { - if r.remaining == 0 { - continue; - } - for inp in input_pools[*src as usize].iter_mut() { - if inp.remaining == 0 { - continue; - } - // skip if the recipient is not interested in this pool - if r.pool_mask.intersect(&PoolMask::from_pool(*dst)).is_empty() { - continue; - } - let amount = inp.remaining.min(r.remaining); - r.remaining -= amount; - inp.remaining -= amount; - - info!( - "Input id: {}, amount: {}, remaining: {}", - inp.id, - to_zec(inp.amount), - to_zec(inp.remaining) - ); - info!( - "Recipient id: {}, amount: {}, remaining: {}", - r.recipient.address, - to_zec(r.recipient.amount), - to_zec(r.remaining) - ); - if r.remaining == 0 { - break; - } - } - } - } - - Ok(()) -} - -pub async fn get_effective_src_pools( - connection: &mut SqliteConnection, - account: u32, - src_pools: u8, -) -> Result { - let apm = get_account_pool_mask(connection, account).await?; - let spm = PoolMask(src_pools); - let src_pool_mask = apm.intersect(&spm); - Ok(src_pool_mask) -} - -pub fn get_change_pool(src_pool_mask: PoolMask, _dest_pool_mask: PoolMask) -> u8 { - // pick the best pool from the source pools - // because it can minimize the fees and reduce the amount going - // through the turnstile - src_pool_mask.to_best_pool().unwrap() -} - -pub async fn get_account_pool_mask( - connection: &mut SqliteConnection, - account: u32, -) -> Result { - let (has_transparent,): (bool,) = - sqlx::query_as("SELECT EXISTS(SELECT 1 FROM transparent_accounts WHERE account = ?)") - .bind(account) - .fetch_one(&mut *connection) - .await?; - let (has_sapling,): (bool,) = - sqlx::query_as("SELECT EXISTS(SELECT 1 FROM sapling_accounts WHERE account = ?)") - .bind(account) - .fetch_one(&mut *connection) - .await?; - let (has_orchard,): (bool,) = - sqlx::query_as("SELECT EXISTS(SELECT 1 FROM orchard_accounts WHERE account = ?)") - .bind(account) - .fetch_one(&mut *connection) - .await?; - // Ironwood uses the same keys as Orchard; include it when Orchard is available. - let account_pool_mask = PoolMask( - (has_transparent as u8) - | (has_sapling as u8) << 1 - | (has_orchard as u8) << 2 - | (has_orchard as u8) << 3, - ); - - Ok(account_pool_mask) -} - -async fn fetch_one_taddr_unspent_notes( - connection: &mut SqliteConnection, - account: u32, -) -> Result> { - let notes = sqlx::query( - "SELECT a.id_note, a.height, a.value, a.taddress - FROM notes a - LEFT JOIN spends b ON a.id_note = b.id_note - WHERE b.id_note IS NULL AND a.account = ? - AND locked = 0 - AND a.pool = 0 - AND a.value >= 5000 - ORDER BY taddress", - ) - .bind(account) - .map(|row: SqliteRow| { - let id: u32 = row.get(0); - let height: u32 = row.get(1); - let value: u64 = row.get(2); - let taddress: u32 = row.get(3); - ( - taddress, - InputNote { - id, - height, - amount: value, - remaining: value, - pool: 0, // transparent pool - id_asset: None, - asset_base: [0u8; 32].to_vec(), - taddress: Some(taddress), - }, - ) - }) - .fetch_all(connection) - .await?; - - let transparent_notes: Vec> = notes - .into_iter() - .chunk_by(|item| item.0) // group by the transparent address - .into_iter() - .map(|group| group.1.map(|n| n.1).collect()) // collect each group of notes and discard the address - .collect(); // collect all groups into Vec> - - if !transparent_notes.is_empty() { - // pick a random group to shield - let random_note = OsRng.next_u32() as usize % transparent_notes.len(); - let notes = &transparent_notes[random_note]; - return Ok(notes.clone()); - } - - Ok(vec![]) -} pub async fn fetch_unspent_notes_grouped_by_pool( connection: &mut SqliteConnection, diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 4a48d4d33..03f78616b 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -42,6 +42,10 @@ pub(super) struct Note { /// Index within the original per-pool `input_pools[pool]` array so the /// caller can map results back after sorting/reordering. pub pool_index: usize, + /// Asset index: 0 = ZEC, 1+ = ZSA asset. Determines which output + /// asset this note can satisfy. ZEC notes only cover ZEC outputs; + /// ZSA notes only cover outputs of the same asset. + pub asset_index: u8, } /// A required output. Mirrors `select::Output` so callers in `plan.rs` @@ -50,6 +54,9 @@ pub(super) struct Note { pub(super) struct Output { pub pool: u8, pub amount: u64, + /// Asset index: 0 = ZEC, 1+ = ZSA asset. Only notes of the same + /// asset_index can satisfy this output. + pub asset_index: u8, } /// Result of a successful coin-selection run. @@ -75,7 +82,9 @@ const GRACE_ACTIONS: u64 = 2; #[derive(Clone, Debug)] struct State { - sum: u64, + /// Per-asset input sums. Index 0 = ZEC, index 1+ = ZSA asset. + /// Only ZEC (asset 0) can pay the fee. + asset_sums: Vec, /// Per-pool balance: inputs_value - outputs_value (including change). balance: [i64; N_POOLS], /// Number of inputs selected per pool. Drives the fee computation. @@ -91,9 +100,10 @@ struct State { /// Fixed, precomputed context for a single selection run. struct Context<'a> { notes: &'a [Note], // sorted: shielded pools first, then transparent; within pool descending by amount + n_assets: u8, // total number of distinct assets (1 = ZEC only) + asset_output_amounts: Vec, // required output amount per asset (index 0 = ZEC) output_amounts: [u64; N_POOLS], // output value per pool (zats) n_outputs: [u32; N_POOLS], // number of fixed recipient outputs per pool - output_sum: u64, // total output value (zats) f_unit: u64, // COST_PER_ACTION (5000) migration: bool, // orchard fee = inputs+outputs instead of max recipient_pays_fee: bool, @@ -207,13 +217,35 @@ fn evaluate(state: &State, ctx: &Context) -> (u64, u8) { Mode::Privacy => evaluate_privacy(state, ctx), }; if cost == u64::MAX { - info!("evaluate: mode={:?}, sum={}, INFEASIBLE", ctx.mode, state.sum); + info!("evaluate: mode={:?}, asset_sums[0]={}, INFEASIBLE", ctx.mode, state.asset_sums[0]); } else { - info!("evaluate: mode={:?}, sum={}, fee/cost={}, change_pool={}", ctx.mode, state.sum, cost, pool); + info!("evaluate: mode={:?}, asset_sums[0]={}, fee/cost={}, change_pool={}", ctx.mode, state.asset_sums[0], cost, pool); } (cost, pool) } +/// Check whether `state` satisfies all asset requirements with the +/// given `fee` and change-pool assignment. +fn is_feasible(state: &State, ctx: &Context, fee: u64) -> bool { + // Asset 0 (ZEC) must cover ZEC outputs + fee + let zec_needed = if ctx.recipient_pays_fee { + ctx.asset_output_amounts[0] + } else { + ctx.asset_output_amounts[0].saturating_add(fee) + }; + if state.asset_sums[0] < zec_needed { + return false; + } + + // Each ZSA asset (i > 0) must cover its own outputs (no fee) + for i in 1..ctx.n_assets as usize { + if state.asset_sums[i] < ctx.asset_output_amounts[i] { + return false; + } + } + true +} + /// Fee-mode evaluation: return the lowest fee achievable by assigning /// change to any pool. fn evaluate_fee(state: &State, ctx: &Context) -> (u64, u8) { @@ -223,23 +255,18 @@ fn evaluate_fee(state: &State, ctx: &Context) -> (u64, u8) { for cp in 0..N_POOLS as u8 { let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration); - let needed = if ctx.recipient_pays_fee { - if fee > ctx.first_recipient_amount { - info!( - "evaluate_fee: cp={} SKIP — fee({}) > first_recipient_amount({})", - cp, fee, ctx.first_recipient_amount - ); - continue; // fee exceeds what the first recipient can cover - } - ctx.output_sum - } else { - ctx.output_sum.saturating_add(fee) - }; + if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { + info!( + "evaluate_fee: cp={} SKIP — fee({}) > first_recipient_amount({})", + cp, fee, ctx.first_recipient_amount + ); + continue; + } - let feasible = state.sum >= needed; + let feasible = is_feasible(state, ctx, fee); info!( - "evaluate_fee: cp={} fee={} needed={} sum={} feasible={} best_fee={}", - cp, fee, needed, state.sum, feasible, best_fee + "evaluate_fee: cp={} fee={} asset_sums[0]={} feasible={} best_fee={}", + cp, fee, state.asset_sums[0], feasible, best_fee ); if feasible && fee < best_fee { @@ -260,20 +287,20 @@ fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { for cp in 0..N_POOLS as u8 { let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration); - let needed = if ctx.recipient_pays_fee { - if fee > ctx.first_recipient_amount { - continue; - } - ctx.output_sum - } else { - ctx.output_sum.saturating_add(fee) - }; + if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { + continue; + } - if state.sum < needed { + if !is_feasible(state, ctx, fee) { continue; } - let change = state.sum.saturating_sub(needed); + let zec_needed = if ctx.recipient_pays_fee { + ctx.asset_output_amounts[0] + } else { + ctx.asset_output_amounts[0].saturating_add(fee) + }; + let change = state.asset_sums[0].saturating_sub(zec_needed); // Turnstile: transparent value + per-pool shielded imbalance. // All transparent value passes through the turnstile. @@ -318,6 +345,15 @@ fn lower_bound_fee(state: &State, ctx: &Context) -> u64 { if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { continue; } + // Only consider fees that could be feasible given current ZEC sum + let zec_needed = if ctx.recipient_pays_fee { + ctx.asset_output_amounts[0] + } else { + ctx.asset_output_amounts[0].saturating_add(fee) + }; + if state.asset_sums[0] < zec_needed { + continue; + } if fee < min_fee { min_fee = fee; } @@ -367,7 +403,7 @@ fn initial_state(ctx: &Context) -> State { balance[p] = -(ctx.output_amounts[p] as i64); } State { - sum: 0, + asset_sums: vec![0u64; ctx.n_assets as usize], balance, n_inputs: [0; N_POOLS], tin: 0, @@ -379,8 +415,8 @@ fn initial_state(ctx: &Context) -> State { /// Apply picking `note_idx` on top of `state`, returning a new child state. fn apply(state: &State, note_idx: usize, note: &Note) -> State { let mut child = state.clone(); - child.sum += note.amount; child.selected.push(note_idx); + child.asset_sums[note.asset_index as usize] += note.amount; child.n_inputs[note.pool as usize] = child.n_inputs[note.pool as usize].saturating_add(1); match note.pool { @@ -454,13 +490,14 @@ fn top_k_by_local_heuristic<'a>( /// Balances rounded to nearest QUANT zats to bound the `seen` map size. const QUANT: i64 = 1000; -type StateKey = (u64, [i64; N_POOLS], u64, [u32; N_POOLS]); -// = (sum, quantized_balances, tout, n_inputs) +type StateKey = (Vec, [i64; N_POOLS], u64, [u32; N_POOLS]); +// asset_sums(q) balance(q) tout n_inputs fn state_key(state: &State) -> StateKey { let q = |b: i64| (b / QUANT) * QUANT; + let q_u64 = |v: u64| ((v as i64) / QUANT) * QUANT; ( - state.sum, + state.asset_sums.iter().map(|&s| q_u64(s)).collect(), [ q(state.balance[0]), q(state.balance[1]), q(state.balance[2]), q(state.balance[3]), @@ -573,17 +610,23 @@ pub(super) fn select_notes( let mut output_amounts = [0u64; N_POOLS]; let mut n_outputs = [0u32; N_POOLS]; let mut output_sum = 0u64; + + // Derive n_assets and per-asset output amounts from outputs + let n_assets = outputs.iter().map(|o| o.asset_index).max().unwrap_or(0) + 1; + let mut asset_output_amounts = vec![0u64; n_assets as usize]; + for o in outputs { let p = o.pool as usize; if p < N_POOLS { output_amounts[p] = output_amounts[p].saturating_add(o.amount); n_outputs[p] = n_outputs[p].saturating_add(1); - output_sum = output_sum.saturating_add(o.amount); } + output_sum = output_sum.saturating_add(o.amount); + asset_output_amounts[o.asset_index as usize] += o.amount; } info!( - "select_notes: output_sum={} zats, n_outputs={:?}, output_amounts={:?}", - output_sum, n_outputs, output_amounts + "select_notes: output_sum={} zats, n_assets={}, asset_output_amounts={:?}, n_outputs={:?}, output_amounts={:?}", + output_sum, n_assets, asset_output_amounts, n_outputs, output_amounts ); // ---- 3. Sort notes: shielded pools first, then transparent; within each @@ -598,9 +641,10 @@ pub(super) fn select_notes( // ---- 4. Build context ------------------------------------------------- let ctx = Context { notes: &sorted, + n_assets, + asset_output_amounts, output_amounts, n_outputs, - output_sum, f_unit, migration, recipient_pays_fee, @@ -613,8 +657,8 @@ pub(super) fn select_notes( let (mut best_state, mut best_cost, mut best_pool) = match greedy_solution(&ctx) { Some((state, cost, pool)) => { info!( - "select_notes: greedy found solution — sum={}, fee={}, change_pool={}, n_inputs={:?}", - state.sum, cost, pool, state.n_inputs + "select_notes: greedy found solution — asset_sums[0]={}, fee={}, change_pool={}, n_inputs={:?}", + state.asset_sums[0], cost, pool, state.n_inputs ); (state, cost, pool) } @@ -629,14 +673,14 @@ pub(super) fn select_notes( s }; info!( - "select_notes: all-notes state sum={}, n_inputs={:?}", - state.sum, state.n_inputs + "select_notes: all-notes state asset_sums[0]={}, n_inputs={:?}", + state.asset_sums[0], state.n_inputs ); let (cost, pool) = evaluate(&state, &ctx); if cost == u64::MAX { info!( - "select_notes: FAIL — all notes (sum={}) still infeasible. output_sum={}, recipient_pays_fee={}, first_recipient={}", - state.sum, output_sum, recipient_pays_fee, first_recipient_amount + "select_notes: FAIL — all notes (asset_sums[0]={}) still infeasible. output_sum={}, recipient_pays_fee={}, first_recipient={}", + state.asset_sums[0], output_sum, recipient_pays_fee, first_recipient_amount ); return None; } @@ -694,9 +738,10 @@ pub(super) fn select_notes( continue; } - // Overshoot cap + // Overshoot cap: skip if ZEC sum already exceeds output + max single note + // (additional notes beyond this can't improve the solution) let max_remaining = remaining.iter().map(|(_, n)| n.amount).max().unwrap_or(0); - if state.sum > ctx.output_sum.saturating_add(max_remaining) { + if state.asset_sums[0] > ctx.asset_output_amounts[0].saturating_add(max_remaining) { continue; } @@ -743,11 +788,11 @@ pub(super) fn select_notes( }; let change_needed = if recipient_pays_fee { - ctx.output_sum + ctx.asset_output_amounts[0] } else { - ctx.output_sum.saturating_add(fee) + ctx.asset_output_amounts[0].saturating_add(fee) }; - let change_amount = best_state.sum.saturating_sub(change_needed); + let change_amount = best_state.asset_sums[0].saturating_sub(change_needed); // Gather inputs and per-pool indices let inputs: Vec = best_state.selected.iter().map(|&idx| ctx.notes[idx].clone()).collect(); @@ -778,18 +823,18 @@ mod tests { #[test] fn test_select_notes_basic() { let notes = vec![ - Note { pool: 1, amount: 120_000, pool_index: 0 }, - Note { pool: 1, amount: 80_000, pool_index: 1 }, - Note { pool: 1, amount: 30_000, pool_index: 2 }, - Note { pool: 2, amount: 200_000, pool_index: 0 }, - Note { pool: 2, amount: 15_000, pool_index: 1 }, - Note { pool: 3, amount: 60_000, pool_index: 0 }, - Note { pool: 0, amount: 500_000, pool_index: 0 }, + Note { pool: 1, amount: 120_000, pool_index: 0, asset_index: 0 }, + Note { pool: 1, amount: 80_000, pool_index: 1, asset_index: 0 }, + Note { pool: 1, amount: 30_000, pool_index: 2, asset_index: 0 }, + Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, + Note { pool: 2, amount: 15_000, pool_index: 1, asset_index: 0 }, + Note { pool: 3, amount: 60_000, pool_index: 0, asset_index: 0 }, + Note { pool: 0, amount: 500_000, pool_index: 0, asset_index: 0 }, ]; let outputs = vec![ - Output { pool: 1, amount: 150_000 }, - Output { pool: 2, amount: 100_000 }, + Output { pool: 1, amount: 150_000, asset_index: 0 }, + Output { pool: 2, amount: 100_000, asset_index: 0 }, ]; let f_unit = 5_000u64; @@ -824,11 +869,11 @@ mod tests { fn test_select_notes_dust_filtered() { // Notes below f_unit (5000) should be filtered out let notes = vec![ - Note { pool: 1, amount: 120, pool_index: 0 }, // dust - Note { pool: 1, amount: 4_000, pool_index: 1 }, // dust - Note { pool: 2, amount: 1_000_000, pool_index: 0 }, // only usable note + Note { pool: 1, amount: 120, pool_index: 0, asset_index: 0 }, // dust + Note { pool: 1, amount: 4_000, pool_index: 1, asset_index: 0 }, // dust + Note { pool: 2, amount: 1_000_000, pool_index: 0, asset_index: 0 }, // only usable note ]; - let outputs = vec![Output { pool: 2, amount: 500_000 }]; + let outputs = vec![Output { pool: 2, amount: 500_000, asset_index: 0 }]; let f_unit = 5_000u64; let sel = select_notes(¬es, &outputs, f_unit, false, false, 0, Mode::Fee) @@ -842,11 +887,11 @@ mod tests { #[test] fn test_select_notes_recipient_pays_fee() { let notes = vec![ - Note { pool: 2, amount: 200_000, pool_index: 0 }, - Note { pool: 2, amount: 100_000, pool_index: 1 }, - Note { pool: 2, amount: 50_000, pool_index: 2 }, + Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, + Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, + Note { pool: 2, amount: 50_000, pool_index: 2, asset_index: 0 }, ]; - let outputs = vec![Output { pool: 2, amount: 150_000 }]; + let outputs = vec![Output { pool: 2, amount: 150_000, asset_index: 0 }]; let f_unit = 5_000u64; // First recipient has 200_000, fee will be well under that @@ -868,12 +913,12 @@ mod tests { #[test] fn test_select_notes_recipient_pays_fee_too_high() { let notes = vec![ - Note { pool: 2, amount: 200_000, pool_index: 0 }, - Note { pool: 2, amount: 100_000, pool_index: 1 }, - Note { pool: 1, amount: 300_000, pool_index: 0 }, - Note { pool: 0, amount: 500_000, pool_index: 0 }, + Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, + Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, + Note { pool: 1, amount: 300_000, pool_index: 0, asset_index: 0 }, + Note { pool: 0, amount: 500_000, pool_index: 0, asset_index: 0 }, ]; - let outputs = vec![Output { pool: 2, amount: 150_000 }]; + let outputs = vec![Output { pool: 2, amount: 150_000, asset_index: 0 }]; let f_unit = 5_000u64; // First recipient only has 1_000 zats — fee will exceed that @@ -890,9 +935,9 @@ mod tests { #[test] fn test_select_notes_insufficient_funds() { let notes = vec![ - Note { pool: 2, amount: 10_000, pool_index: 0 }, + Note { pool: 2, amount: 10_000, pool_index: 0, asset_index: 0 }, ]; - let outputs = vec![Output { pool: 2, amount: 1_000_000 }]; + let outputs = vec![Output { pool: 2, amount: 1_000_000, asset_index: 0 }]; let f_unit = 5_000u64; let result = select_notes(¬es, &outputs, f_unit, false, false, 0, Mode::Fee); diff --git a/rust/src/warp/decrypter.rs b/rust/src/warp/decrypter.rs index ab47b01cc..aa02d77c2 100644 --- a/rust/src/warp/decrypter.rs +++ b/rust/src/warp/decrypter.rs @@ -232,8 +232,12 @@ pub fn try_orchard_decrypt( false }; if matched { - // Always 32 bytes: [0u8; 32] for ZEC, non-zero for ZSA - let asset_base = note.asset().to_bytes().to_vec(); + let is_zec = bool::from(note.asset().is_zatoshi()); + let asset_base = if is_zec { + vec![] + } else { + note.asset().to_bytes().to_vec() + }; let dbn = Note { pool: 2, account, diff --git a/rust/src/warp/sync.rs b/rust/src/warp/sync.rs index 348e35f24..4f84584ed 100644 --- a/rust/src/warp/sync.rs +++ b/rust/src/warp/sync.rs @@ -1,22 +1,18 @@ use std::{collections::HashSet, time::Duration}; use anyhow::{Context as _, Result}; -use bip39::Mnemonic; use shielded::Synchronizer; use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; -use std::collections::HashMap; use tokio::sync::{broadcast, mpsc::Sender}; use tokio_stream::{wrappers::ReceiverStream, StreamExt}; use tracing::debug; use zcash_protocol::consensus::{NetworkUpgrade, Parameters}; use zcash_trees::network::Network; -use orchard::{ - note::{AssetBase, AssetId, ExtractedNoteCommitment, RandomSeed, Rho}, - issuance::auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, - value::NoteValue, - Address, -}; +use orchard::note::AssetBase; +use orchard::issuance::auth::IssueValidatingKey; +use orchard::note::AssetId; +use orchard::issuance::auth::ZSASchnorr; use crate::{ lwd::CompactBlock, @@ -28,7 +24,6 @@ use super::legacy::CommitmentTreeFrontier; pub use zcash_trees::types::SyncError; -pub mod block; mod shielded; pub type SaplingSync = Synchronizer; @@ -43,126 +38,6 @@ pub enum BlockMessage { Reorg(Vec, u32), } -/// Preprocess CompactBlocks into SyncBlocks, merging issuance notes into the -/// unified `orchard_outputs` list per transaction. Resolves ik→account ownership -/// so `try_decrypt` can match issuance notes without re-deriving keys. -async fn preprocess( - blocks: &[CompactBlock], - accounts: &[(u32, bool)], - connection: &mut SqliteConnection, - network: &Network, -) -> Result> { - use orchard::note::{AssetBase as OrchardAssetBase, AssetId as OrchardAssetId}; - - // Resolve which accounts own which issuance keys - let mut ik_owners: HashMap, u32> = HashMap::new(); - let coin_type = match network.network_type() { - zcash_protocol::consensus::NetworkType::Main => 133u32, - _ => 1u32, - }; - for (account, _) in accounts.iter() { - if let Ok(Some(seed_info)) = - crate::account::get_account_seed(&mut *connection, *account).await - { - if let Ok(mnemonic) = Mnemonic::parse(seed_info.mnemonic) { - let seed = mnemonic.to_seed(&seed_info.phrase); - if let Ok(isk) = - IssueAuthKey::::from_zip32_seed(&seed, coin_type, 0) - { - let my_ik: IssueValidatingKey = - IssueValidatingKey::from(&isk); - ik_owners.insert(my_ik.encode(), *account); - } - } - } - } - - let mut sync_blocks = Vec::with_capacity(blocks.len()); - for cb in blocks { - let mut sync_vtx = Vec::with_capacity(cb.vtx.len()); - for vtx in &cb.vtx { - // Copy orchard actions as OrchardOutput::Action - let mut orchard_outputs: Vec = vtx - .actions - .iter() - .cloned() - .map(block::OrchardOutput::Action) - .collect(); - - // Append issuance notes as OrchardOutput::Issuance - for iss in &vtx.issuances { - let desc_hash: [u8; 32] = - iss.asset_desc_hash.as_slice().try_into().unwrap(); - let ik = IssueValidatingKey::::decode(&iss.ik) - .expect("invalid issuer key in issuance"); - let oasset_id = OrchardAssetId::new_v0(&ik, &desc_hash); - let asset_base = OrchardAssetBase::custom(&oasset_id); - let asset_base_bytes = asset_base.to_bytes().to_vec(); - let ik_owner = ik_owners.get(&iss.ik).copied(); - - for note_data in &iss.notes { - // Zip-227 requires a zero-value reference note as the - // first note on first issuance. Its cmx must enter the - // Merkle tree, but we must not create a wallet note for it. - let owner = if note_data.value == 0 { - None - } else { - ik_owner - }; - // Compute cmx from plaintext note fields - let recipient_bytes: [u8; 43] = - note_data.recipient.as_slice().try_into().unwrap(); - let recipient = - Address::from_raw_address_bytes(&recipient_bytes).unwrap(); - let rho_bytes: [u8; 32] = - note_data.rho.as_slice().try_into().unwrap(); - let rho = Rho::from_bytes(&rho_bytes).unwrap(); - let rseed_bytes: [u8; 32] = - note_data.rseed.as_slice().try_into().unwrap(); - let rseed = RandomSeed::from_bytes(rseed_bytes, &rho).unwrap(); - let note = orchard::note::Note::from_parts( - recipient, - NoteValue::from_raw(note_data.value), - asset_base, - rho, - rseed, - orchard::NoteVersion::V2) - .unwrap(); - let cmx = - ExtractedNoteCommitment::from(note.commitment()).to_bytes(); - - orchard_outputs.push(block::OrchardOutput::Issuance { - note: note_data.clone(), - ik: iss.ik.clone(), - asset_desc_hash: iss.asset_desc_hash.clone(), - asset_base: asset_base_bytes.clone(), - cmx, - owner, - }); - } - } - - sync_vtx.push(block::SyncTx { - hash: vtx.hash.clone(), - spends: vtx.spends.clone(), - sapling_outputs: vtx.outputs.clone(), - orchard_actions: vtx.actions.clone(), - orchard_outputs, - ironwood_actions: vtx.ironwood_actions.clone(), - issuances: vtx.issuances.clone(), - }); - } - sync_blocks.push(block::SyncBlock { - height: cb.height, - hash: cb.hash.clone(), - prev_hash: cb.prev_hash.clone(), - time: cb.time, - vtx: sync_vtx, - }); - } - Ok(sync_blocks) -} - #[allow(clippy::too_many_arguments)] pub async fn warp_sync( network: &Network, @@ -325,15 +200,9 @@ pub async fn warp_sync( BlockMessage::Chunk(bs) => { debug!("Processing {} blocks", bs.len()); - // Preprocess: convert CompactBlock → SyncBlock, merging - // issuance notes into orchard_outputs per transaction. - let sync_blocks = preprocess(&bs, accounts, &mut *connection, network) - .await - .context("preprocessing blocks")?; - // Send Issuance messages for asset storage before any Note // messages (same transaction ordering guarantee). - for cb in &sync_blocks { + for cb in &bs { for vtx in &cb.vtx { for iss in &vtx.issuances { let desc_hash: [u8; 32] = @@ -356,15 +225,13 @@ pub async fn warp_sync( } } - sap_dec.add(&sync_blocks).await?; - orch_dec.add(&sync_blocks).await?; + sap_dec.add(&bs).await?; + orch_dec.add(&bs).await?; if let Some(ref mut ironwood_dec) = ironwood_dec { - ironwood_dec.add(&sync_blocks).await?; + ironwood_dec.add(&bs).await?; } let lcb = bs.last().unwrap(); - // Use the last original block for header (sync_blocks is - // already consumed by add()). let bh = BlockHeader { height: lcb.height as u32, hash: lcb.hash.clone(), diff --git a/rust/src/warp/sync/block.rs b/rust/src/warp/sync/block.rs deleted file mode 100644 index 25ea57faf..000000000 --- a/rust/src/warp/sync/block.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::lwd::{CompactIssuance, CompactIssueNote, CompactOrchardAction, CompactSaplingOutput, CompactSaplingSpend}; - -/// Unified output for Orchard sync — either a regular action (from the Orchard -/// bundle) or a synthesized issuance note (from the Issue bundle). Both share -/// the same Merkle tree (pool 2), same cmx-based matching, same nullifier -/// derivation. Only `try_decrypt` differs. -#[derive(Clone)] -pub enum OrchardOutput { - Action(CompactOrchardAction), - Issuance { - note: CompactIssueNote, - ik: Vec, - asset_desc_hash: Vec, - asset_base: Vec, - cmx: [u8; 32], - /// Pre-resolved account that owns this issuance's ik (None if no - /// matching account, in which case `try_decrypt` skips it). - owner: Option, - }, -} - -/// Preprocessed transaction — carries both the original wire-format fields -/// (for Sapling and for Orchard spend/nullifier extraction) and the merged -/// `orchard_outputs` list that interleaves Orchard actions and issuance notes. -pub struct SyncTx { - pub hash: Vec, - /// Sapling spends (nullifiers). - pub spends: Vec, - /// Sapling outputs (cmu, epk, ciphertext). - pub sapling_outputs: Vec, - /// Original Orchard actions — used for spend/nullifier extraction via - /// `extract_inputs`. Outputs go through `orchard_outputs` instead. - pub orchard_actions: Vec, - /// Merged Orchard outputs: actions first, then issuance notes. Used by - /// `extract_outputs` — cmxs are naturally interleaved per-tx. - pub orchard_outputs: Vec, - /// Ironwood actions from the v6 Ironwood bundle (same wire format as Orchard). - pub ironwood_actions: Vec, - /// Asset metadata for DB storage (sent as `WarpSyncMessage::Issuance`). - pub issuances: Vec, -} - -/// Preprocessed block — replaces `CompactBlock` as the input to the sync engine. -/// Issuance notes have been merged into `orchard_outputs` per transaction. -pub struct SyncBlock { - pub height: u64, - pub hash: Vec, - pub prev_hash: Vec, - pub time: u32, - pub vtx: Vec, -} diff --git a/rust/src/warp/sync/shielded.rs b/rust/src/warp/sync/shielded.rs index 3d11571a3..236288749 100644 --- a/rust/src/warp/sync/shielded.rs +++ b/rust/src/warp/sync/shielded.rs @@ -11,12 +11,13 @@ use sqlx::{Row, SqliteConnection}; use tokio::sync::mpsc::Sender; use tracing::{enabled, debug}; +use ::orchard::issuance::auth::{IssueValidatingKey, ZSASchnorr}; +use ::orchard::note::{AssetBase, AssetId}; +use crate::lwd::{CompactBlock, CompactIssueNote, CompactTx}; use crate::warp::{Edge, Hasher, Witness, MERKLE_DEPTH}; use crate::Hash32; use zcash_trees::types::{Note, Transaction, WarpSyncMessage, UTXO}; -use super::block::{SyncBlock, SyncTx}; - pub mod ironwood; pub mod orchard; pub mod sapling; @@ -29,30 +30,17 @@ pub trait ShieldedProtocol { type Spend; type Output: Sync; - /// Issuance key type. Set to `()` for protocols that don't support issuance. + /// Issuance key type. Set to `()` for all protocols — issuance note + /// synthesis has been removed in favor of trial decryption via actions. type IssueAuth: Sync; - /// Whether this protocol supports issuance note synthesis. - fn supports_issuance() -> bool { - false - } - fn extract_ivk( connection: &mut SqliteConnection, account: u32, scope: u8, ) -> impl std::future::Future>>; - /// Resolve issuance key per account. Only called when `supports_issuance()`. - /// Returns `(issue_auth, nk)` for ik-matching and nullifier derivation. - fn extract_issue_auth( - _connection: &mut SqliteConnection, - _account: u32, - _coin_type: u32, - ) -> impl std::future::Future>> { - async { Ok(None) } - } - fn extract_inputs(tx: &SyncTx) -> &Vec; - fn extract_outputs(tx: &SyncTx) -> &Vec; + fn extract_inputs(tx: &CompactTx) -> &Vec; + fn extract_outputs(tx: &CompactTx) -> &Vec; fn extract_nf(i: &Self::Spend) -> Hash32; fn extract_cmx(o: &Self::Output) -> Hash32; @@ -70,6 +58,36 @@ pub trait ShieldedProtocol { ) -> Result>; fn derive_nf(nk: &Self::NK, position: u32, note: &mut Self::Note) -> Result; + + /// Process a plaintext issuance note. No trial decryption — the note fields + /// are unencrypted. Checks if `recipient` matches `ivk`, constructs the + /// protocol note, computes its cmx, and returns the result. + #[allow(clippy::too_many_arguments)] + fn try_decrypt_issuance( + _network: &Network, + _account: u32, + _scope: u8, + _ivk: &Self::IVK, + _height: u32, + _ivtx: u32, + _vout: u32, + _issue_note: &CompactIssueNote, + _asset_base: &AssetBase, + ) -> Result> { + Ok(None) // default: no issuance support + } + + /// Compute the note commitment (cmx) for a plaintext issuance note. + /// This is independent of wallet keys — used for tree building for all + /// issuance notes, including ones we don't own. + /// Returns `Ok(None)` for protocols that don't support issuance; + /// `Ok(Some(cmx))` on success; `Err` only on malformed data. + fn compute_issuance_cmx( + _issue_note: &CompactIssueNote, + _asset_base: &AssetBase, + ) -> Result> { + Ok(None) // default: issuance not supported + } } #[derive(Debug)] @@ -175,7 +193,7 @@ impl Synchronizer

{ self.keys.is_empty() } - pub async fn add(&mut self, blocks: &[SyncBlock]) -> Result<()> { + pub async fn add(&mut self, blocks: &[CompactBlock]) -> Result<()> { if blocks.is_empty() { return Ok(()); } @@ -211,7 +229,91 @@ impl Synchronizer

{ }) }) .collect::>(); - debug!("Notes #{}", notes.len()); + debug!("Action notes #{}", notes.len()); + + // Process issuance notes from vtx.issuances — plaintext, no trial + // decryption needed. Per tx we track the cmxs (for tree building) + // and the total count (for position tracking). Only the Orchard + // protocol supports ZSA issuance (gated by supports_issuance()). + let mut issuance_cmxs: Vec<(u32, u32, Vec<[u8; 32]>)> = Vec::new(); + for cb in blocks.iter() { + for (ivtx, tx) in cb.vtx.iter().enumerate() { + let height = cb.height as u32; + let actions_len = P::extract_outputs(tx).len() as u32; + let mut tx_issuance_cmxs: Vec<[u8; 32]> = Vec::new(); + let mut note_vout = actions_len; + + for iss in &tx.issuances { + let desc_hash: [u8; 32] = iss.asset_desc_hash.as_slice() + .try_into() + .map_err(|_| anyhow::anyhow!("Invalid asset_desc_hash length"))?; + let ik = IssueValidatingKey::::decode(&iss.ik) + .map_err(|e| anyhow::anyhow!("Invalid issuer key: {e}"))?; + let asset_id = AssetId::new_v0(&ik, &desc_hash); + let asset_base = AssetBase::custom(&asset_id); + + for note in &iss.notes { + // Compute cmx for tree building. Returns None for + // protocols that don't support issuance (Sapling, Ironwood). + if let Some(cmx) = P::compute_issuance_cmx(note, &asset_base)? { + debug!( + "Issuance cmx: height={} ivtx={} vout={} cmx={}", + height, + ivtx, + note_vout, + hex::encode(cmx) + ); + tx_issuance_cmxs.push(cmx); + } + + // Check if this note belongs to any of our wallet keys. + for (account, scope, ivk, nk) in &self.keys { + if let Some((n, dbn)) = P::try_decrypt_issuance( + &network, + *account, + *scope, + ivk, + height, + ivtx as u32, + note_vout, + note, + &asset_base, + ) + .unwrap_or_else(|e| { + tracing::warn!("issuance decrypt error: {e}"); + None + }) { + notes.push((n, dbn, nk)); + } + } + note_vout += 1; + } + } + + if !tx_issuance_cmxs.is_empty() { + issuance_cmxs.push((height, ivtx as u32, tx_issuance_cmxs)); + } + } + } + debug!("Notes total (actions + issuances) #{}", notes.len()); + + // Build a lookup of per-tx issuance note counts for position tracking. + let mut issuance_count: std::collections::HashMap<(u32, u32), u32> = + std::collections::HashMap::new(); + for (height, ivtx, cmxs) in &issuance_cmxs { + issuance_count.insert((*height, *ivtx), cmxs.len() as u32); + } + + // Sort by (height, ivtx, vout) so issuance notes are interleaved + // with action notes within the same transaction. Without this sort, + // issuance notes appended after all action notes would never be + // reached by the block-iteration note_iterator below. + notes.sort_by(|(_, a, _), (_, b, _)| { + a.height + .cmp(&b.height) + .then_with(|| a.ivtx.cmp(&b.ivtx)) + .then_with(|| a.vout.cmp(&b.vout)) + }); let mut note_iterator = notes.iter_mut(); let mut note = note_iterator.next(); @@ -252,7 +354,11 @@ impl Synchronizer

{ _ => break, } } - position += P::extract_outputs(tx).len() as u32; + let extra = issuance_count + .get(&(cb.height as u32, ivtx as u32)) + .copied() + .unwrap_or(0); + position += P::extract_outputs(tx).len() as u32 + extra; } } @@ -274,6 +380,7 @@ impl Synchronizer

{ let mut cmxs = vec![]; let mut count_cmxs = 0; + debug!("WS starting position {}-{}", self.position, position); for depth in 0..MERKLE_DEPTH as usize { let mut position = self.position >> depth; if position % 2 == 1 { @@ -282,12 +389,25 @@ impl Synchronizer

{ } if depth == 0 { + // Build lookup for issuance cmxs per (height, ivtx) + let issuance_cmx_map: std::collections::HashMap<(u32, u32), &[[u8; 32]]> = + issuance_cmxs.iter().map(|(h, i, c)| ((*h, *i), c.as_slice())).collect(); + for cb in blocks.iter() { - for vtx in cb.vtx.iter() { + for (ivtx, vtx) in cb.vtx.iter().enumerate() { for co in P::extract_outputs(vtx).iter() { let cmx = P::extract_cmx(co); cmxs.push(Some(cmx)); } + // Append issuance note cmxs after actions within the same tx + if let Some(iss_cmxs) = + issuance_cmx_map.get(&(cb.height as u32, ivtx as u32)) + { + for cmx in *iss_cmxs { + cmxs.push(Some(*cmx)); + } + count_cmxs += iss_cmxs.len(); + } count_cmxs += P::extract_outputs(vtx).len(); } } diff --git a/rust/src/warp/sync/shielded/ironwood.rs b/rust/src/warp/sync/shielded/ironwood.rs index 92fea9530..e160c74ff 100644 --- a/rust/src/warp/sync/shielded/ironwood.rs +++ b/rust/src/warp/sync/shielded/ironwood.rs @@ -6,8 +6,7 @@ use orchard::{ use sqlx::SqliteConnection; use crate::{ - lwd::CompactOrchardAction, - warp::sync::block::SyncTx, + lwd::{CompactOrchardAction, CompactTx}, Hash32, }; use zcash_trees::{network::Network, types}; @@ -27,10 +26,6 @@ impl ShieldedProtocol for IronwoodProtocol { type Output = CompactOrchardAction; type IssueAuth = (); - fn supports_issuance() -> bool { - false - } - async fn extract_ivk( connection: &mut SqliteConnection, account: u32, @@ -55,19 +50,12 @@ impl ShieldedProtocol for IronwoodProtocol { Ok(keys) } - async fn extract_issue_auth( - _connection: &mut SqliteConnection, - _account: u32, - _coin_type: u32, - ) -> Result> { - Ok(None) - } - - fn extract_inputs(tx: &SyncTx) -> &Vec { + fn extract_inputs(tx: &CompactTx) -> &Vec { + // Decode field9 as CompactOrchardAction on Ironwood networks &tx.ironwood_actions } - fn extract_outputs(tx: &SyncTx) -> &Vec { + fn extract_outputs(tx: &CompactTx) -> &Vec { &tx.ironwood_actions } diff --git a/rust/src/warp/sync/shielded/orchard.rs b/rust/src/warp/sync/shielded/orchard.rs index 54623af63..85200c376 100644 --- a/rust/src/warp/sync/shielded/orchard.rs +++ b/rust/src/warp/sync/shielded/orchard.rs @@ -1,8 +1,7 @@ use anyhow::Result; use orchard::{ keys::{FullViewingKey, IncomingViewingKey}, - note::{AssetBase, RandomSeed, Rho}, - issuance::auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + note::{AssetBase, ExtractedNoteCommitment, NoteVersion, RandomSeed, Rho}, value::NoteValue, Address, Note, }; @@ -10,8 +9,7 @@ use sqlx::SqliteConnection; use crate::keys::ScopeExt; use crate::{ - lwd::CompactOrchardAction, - warp::sync::block::{OrchardOutput, SyncTx}, + lwd::{CompactIssueNote, CompactOrchardAction, CompactTx}, Hash32, }; use zcash_trees::{network::Network, types}; @@ -28,12 +26,8 @@ impl ShieldedProtocol for OrchardProtocol { type NK = FullViewingKey; type Note = Note; type Spend = CompactOrchardAction; - type Output = OrchardOutput; - type IssueAuth = IssueValidatingKey; - - fn supports_issuance() -> bool { - true - } + type Output = CompactOrchardAction; + type IssueAuth = (); async fn extract_ivk( connection: &mut SqliteConnection, @@ -54,44 +48,12 @@ impl ShieldedProtocol for OrchardProtocol { Ok(keys) } - async fn extract_issue_auth( - connection: &mut SqliteConnection, - account: u32, - coin_type: u32, - ) -> Result> { - if let Ok(Some(seed_info)) = - crate::account::get_account_seed(&mut *connection, account).await - { - if let Ok(mnemonic) = bip39::Mnemonic::parse(seed_info.mnemonic) { - let seed = mnemonic.to_seed(&seed_info.phrase); - if let Ok(isk) = - IssueAuthKey::::from_zip32_seed(&seed, coin_type, 0) - { - let ik = IssueValidatingKey::from(&isk); - // Reuse the FVK from orchard_accounts for nullifier derivation - let vk: Option<(Vec,)> = sqlx::query_as( - "SELECT xvk FROM orchard_accounts WHERE account = ?", - ) - .bind(account) - .fetch_optional(&mut *connection) - .await?; - if let Some((xvk,)) = vk { - let fvk = FullViewingKey::from_bytes(&xvk.try_into().unwrap()) - .unwrap(); - return Ok(Some((ik, fvk))); - } - } - } - } - Ok(None) - } - - fn extract_inputs(tx: &SyncTx) -> &Vec { - &tx.orchard_actions + fn extract_inputs(tx: &CompactTx) -> &Vec { + &tx.actions } - fn extract_outputs(tx: &SyncTx) -> &Vec { - &tx.orchard_outputs + fn extract_outputs(tx: &CompactTx) -> &Vec { + &tx.actions } fn extract_nf(i: &Self::Spend) -> Hash32 { @@ -99,10 +61,7 @@ impl ShieldedProtocol for OrchardProtocol { } fn extract_cmx(o: &Self::Output) -> Hash32 { - match o { - OrchardOutput::Action(a) => a.cmx.clone().try_into().unwrap(), - OrchardOutput::Issuance { cmx, .. } => *cmx, - } + o.cmx.clone().try_into().unwrap() } #[allow(clippy::too_many_arguments)] @@ -116,65 +75,62 @@ impl ShieldedProtocol for OrchardProtocol { vout: u32, output: &Self::Output, ) -> Result> { - match output { - OrchardOutput::Action(a) => { - try_orchard_decrypt(network, account, scope, ivk, height, ivtx, vout, a) - } - OrchardOutput::Issuance { - note: note_data, - asset_base, - cmx, - owner, - .. - } => { - // Only synthesize if this account owns the issuance key and - // we are on the external scope (issuance uses Scope::External). - if *owner != Some(account) || scope != 0 { - return Ok(None); - } - let recipient_bytes: [u8; 43] = - note_data.recipient.as_slice().try_into().unwrap(); - let recipient = - Address::from_raw_address_bytes(&recipient_bytes).unwrap(); - let rho_bytes: [u8; 32] = - note_data.rho.as_slice().try_into().unwrap(); - let rho = Rho::from_bytes(&rho_bytes).unwrap(); - let rseed_bytes: [u8; 32] = - note_data.rseed.as_slice().try_into().unwrap(); - let rseed = RandomSeed::from_bytes(rseed_bytes, &rho).unwrap(); - let asset_base_bytes: [u8; 32] = - asset_base.as_slice().try_into().unwrap(); - let asset_base_val = - AssetBase::from_bytes(&asset_base_bytes).unwrap(); - - let note = Note::from_parts( - recipient, - NoteValue::from_raw(note_data.value), - asset_base_val, - rho, - rseed, - orchard::NoteVersion::V2) - .unwrap(); - - let dbn = types::Note { - account, - scope: 0, - height, - pool: 2, - value: note_data.value, - cmx: cmx.to_vec(), - asset_base: asset_base.clone(), - rho: note_data.rho.clone(), - rcm: note.rseed().as_bytes().to_vec(), - diversifier: recipient.diversifier().as_array().to_vec(), - ivtx, - vout, - ..types::Note::default() - }; - - Ok(Some((note, dbn))) - } + try_orchard_decrypt(network, account, scope, ivk, height, ivtx, vout, output) + } + + fn compute_issuance_cmx( + issue_note: &CompactIssueNote, + asset_base: &AssetBase, + ) -> Result> { + let (_, cmx) = construct_issuance_note(issue_note, asset_base)?; + Ok(Some(cmx)) + } + + #[allow(clippy::too_many_arguments)] + fn try_decrypt_issuance( + _network: &Network, + account: u32, + scope: u8, + ivk: &Self::IVK, + height: u32, + ivtx: u32, + vout: u32, + issue_note: &CompactIssueNote, + asset_base: &AssetBase, + ) -> Result> { + let recipient_bytes: [u8; 43] = issue_note.recipient.as_slice().try_into() + .map_err(|_| anyhow::anyhow!("Invalid issuance note recipient length"))?; + let parsed_addr = Address::from_raw_address_bytes(&recipient_bytes); + if parsed_addr.is_none().into() { + return Ok(None); + } + let parsed_addr = parsed_addr.unwrap(); + let d = parsed_addr.diversifier(); + let our_addr = ivk.address(d); + if our_addr.to_raw_address_bytes() != recipient_bytes { + return Ok(None); } + + let (note, cmx_bytes) = construct_issuance_note(issue_note, asset_base)?; + let is_zec = bool::from(note.asset().is_zatoshi()); + let value = note.value().inner(); + let rho = note.rho(); + let dbn = types::Note { + pool: 2, // Orchard + account, + scope, + height, + value, + rcm: note.rseed().as_bytes().to_vec(), + rho: rho.to_bytes().to_vec(), + vout, + diversifier: our_addr.diversifier().as_array().to_vec(), + ivtx, + cmx: cmx_bytes.to_vec(), + asset_base: if is_zec { vec![] } else { note.asset().to_bytes().to_vec() }, + ..types::Note::default() + }; + Ok(Some((note, dbn))) } fn derive_nf(nk: &Self::NK, _position: u32, note: &mut Self::Note) -> Result { @@ -182,3 +138,45 @@ impl ShieldedProtocol for OrchardProtocol { Ok(nf.to_bytes()) } } + +/// Construct an Orchard note from a plaintext issuance note and return both the +/// note and its extracted cmx (note commitment x-coordinate). +fn construct_issuance_note( + issue_note: &CompactIssueNote, + asset_base: &AssetBase, +) -> Result<(Note, Hash32)> { + let recipient_bytes: [u8; 43] = issue_note.recipient.as_slice().try_into() + .map_err(|_| anyhow::anyhow!("Invalid issuance note recipient length"))?; + let addr = Address::from_raw_address_bytes(&recipient_bytes); + if addr.is_none().into() { + anyhow::bail!("Invalid issuance note recipient address"); + } + let addr = addr.unwrap(); + + let value = NoteValue::from_raw(issue_note.value); + let rho = Rho::from_bytes( + issue_note.rho.as_slice().try_into() + .map_err(|_| anyhow::anyhow!("Invalid issuance note rho length"))?, + ); + if rho.is_none().into() { + anyhow::bail!("Invalid issuance note rho"); + } + let rho = rho.unwrap(); + let rseed = RandomSeed::from_bytes( + issue_note.rseed.as_slice().try_into() + .map_err(|_| anyhow::anyhow!("Invalid issuance note rseed length"))?, + &rho, + ); + if rseed.is_none().into() { + anyhow::bail!("Invalid issuance note rseed"); + } + let rseed = rseed.unwrap(); + + let note = Note::from_parts(addr, value, *asset_base, rho, rseed, NoteVersion::V2); + if note.is_none().into() { + anyhow::bail!("Invalid issuance note"); + } + let note = note.unwrap(); + let cmx = ExtractedNoteCommitment::from(note.commitment()); + Ok((note, cmx.to_bytes())) +} diff --git a/rust/src/warp/sync/shielded/sapling.rs b/rust/src/warp/sync/shielded/sapling.rs index 0c224dc12..a006e1fc7 100644 --- a/rust/src/warp/sync/shielded/sapling.rs +++ b/rust/src/warp/sync/shielded/sapling.rs @@ -4,12 +4,11 @@ use sqlx::SqliteConnection; use crate::keys::sapling_ivk_nk_for_scope; use crate::{ - lwd::{CompactSaplingOutput, CompactSaplingSpend}, + lwd::{CompactSaplingOutput, CompactSaplingSpend, CompactTx}, Hash32, }; use zcash_trees::{network::Network, types}; -use crate::warp::sync::block::SyncTx; use crate::warp::{hasher::SaplingHasher, try_sapling_decrypt}; use super::ShieldedProtocol; @@ -25,20 +24,12 @@ impl ShieldedProtocol for SaplingProtocol { type Output = CompactSaplingOutput; type IssueAuth = (); - fn extract_inputs(tx: &SyncTx) -> &Vec { + fn extract_inputs(tx: &CompactTx) -> &Vec { &tx.spends } - fn extract_outputs(tx: &SyncTx) -> &Vec { - &tx.sapling_outputs - } - - async fn extract_issue_auth( - _connection: &mut SqliteConnection, - _account: u32, - _coin_type: u32, - ) -> Result> { - Ok(None) + fn extract_outputs(tx: &CompactTx) -> &Vec { + &tx.outputs } fn extract_nf(i: &Self::Spend) -> Hash32 { diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs new file mode 100644 index 000000000..115e240c1 --- /dev/null +++ b/rust/tests/zsa_transfer_test.rs @@ -0,0 +1,236 @@ +//! Orchard-to-Orchard transfer integration test against a live LWD server. +//! +//! This test requires network access to `zsa.methyl.cc` and is ignored by +//! default. Run with: +//! +//! ```bash +//! cargo test -p rlz --test zsa_transfer_test -- --nocapture --ignored +//! ``` + +use rlz::api::account::{get_addresses, new_account, NewAccount}; +use rlz::api::coin::Coin; +use rlz::api::network::get_current_height; +use rlz::api::pay::{broadcast_transaction, extract_transaction, sign_transaction, PaymentOptions}; +use rlz::pay::pool::ALL_POOLS; +use rlz::pay::Recipient; +use rlz::sync::synchronize_impl; + +const SEED_PHRASE: &str = "equal clock rain latin plastic toss scrub modify clarify fold armor exchange gesture erase habit plug state forward demise demand limb risk only document"; + +/// Sync a faucet account, then send half its Orchard balance to a recipient. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_orchard_transfer() { + // Install rustls crypto provider (required for TLS to LWD server) + let _ = rustls::crypto::ring::default_provider().install_default(); + + // Initialize tracing so debug!() calls show up. Set RUST_LOG=rlz=debug to enable. + let _ = tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "rlz=debug,info".into()), + ) + .try_init(); + + // -- 1. Initialize Coin for ZSA regtest -- + let db_path = format!("/tmp/zsa_integration_test_{}.db", std::process::id()); + let _ = std::fs::remove_file(&db_path); + + let coin = Coin::new(Some(3)) + .open_database(db_path.clone(), None) + .await + .expect("open ZSA database") + .set_lwd(0, "https://zsa.methyl.cc".to_string()) + .expect("set LWD URL"); + println!("Coin initialized: coin={} db={db_path}", coin.coin); + + // -- 2. Restore faucet account from seed -- + let na = NewAccount { + icon: None, + name: "zsa_test".to_string(), + restore: true, + key: SEED_PHRASE.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools: Some(ALL_POOLS), + use_internal: false, + internal: false, + ledger: false, + }; + let account_id = new_account(&na, &coin) + .await + .expect("restore account from seed"); + let coin = coin + .set_account(account_id) + .await + .expect("set current account"); + println!("Account restored: id={account_id}"); + + // -- 3. Sync from LWD server to current height -- + let height = get_current_height(&coin).await.expect("get current height"); + println!("Current height: {height}"); + + synchronize_impl( + (), + vec![account_id], + height, + 10000, + 100, + 10000, + false, + &coin, + ) + .await + .expect("sync"); + println!("Synced to height: {height}"); + + // -- 4. Check ZEC balance (0=T,1=S,2=O,3=IW) -- + let bal = rlz::api::sync::balance(&coin).await.expect("balance"); + println!( + "ZEC balance: T={} S={} O={} IW={}", + bal.0[0], bal.0[1], bal.0[2], bal.0[3] + ); + let orchard_bal = bal.0[2]; + assert!( + orchard_bal > 0, + "faucet account should have Orchard balance" + ); + let send_amount = orchard_bal / 2; + println!("Sending {send_amount} zats from Orchard pool"); + + // // -- 5. Issue a new ZSA asset -- + // let asset_name = format!("TEST{}", std::process::id()); + // let issue_amount = 1_000_000u64; + // println!("Issuing asset '{asset_name}' amount={issue_amount}..."); + // + // let tx_bytes = issue_asset( + // asset_name.clone(), + // issue_amount, + // true, // first_issuance + // false, // finalize + // None, // desc_hash (computed from name) + // account_id, + // &coin, + // ) + // .await + // .expect("issue asset"); + // println!("Issuance tx: {} bytes", tx_bytes.len()); + // + // // -- 6. Broadcast the issuance (must use real chain height for expiry) -- + // let txid = broadcast_transaction(real_height, &tx_bytes, &coin) + // .await + // .expect("broadcast issuance"); + // println!("Issuance broadcast: {txid}"); + // + // // -- 7. Wait for mining and re-sync -- + // println!("Waiting for mining..."); + // tokio::time::sleep(std::time::Duration::from_secs(10)).await; + // + // synchronize_impl( + // (), vec![account_id], real_height, 10000, 100, 10000, false, &coin, + // ).await.expect("re-sync"); + // println!("Re-synced to height: {real_height}"); + // + // // -- 8. Verify the asset appears -- + // let holdings = list_zsa_holdings(&coin).await.expect("list holdings after issuance"); + // println!("ZSA holdings after issuance: {}", holdings.len()); + // for h in &holdings { + // println!( + // " {}: balance={} base={}", + // h.asset_name, + // h.balance, + // hex::encode(&h.asset_base) + // ); + // } + // assert!(!holdings.is_empty(), "should have the issued asset"); + // + // let zsa = holdings.iter().find(|h| h.asset_name == asset_name) + // .expect("issued asset not found"); + // assert!(zsa.balance >= issue_amount, "balance should be at least issued amount"); + + // -- 9. Get own UA for self-transfer -- + let addresses = get_addresses(ALL_POOLS, &coin) + .await + .expect("get addresses"); + let ua = addresses.ua.expect("own UA"); + println!("Own UA: {ua}"); + + // -- 10. Self-send half the Orchard balance -- + let recipient = Recipient { + address: ua, + amount: send_amount, + pools: None, + user_memo: Some("o2o self-transfer test".to_string()), + memo_bytes: None, + price: None, + asset_base: vec![], + asset_name: None, + }; + + let options = PaymentOptions { + src_pools: ALL_POOLS, + recipient_pays_fee: false, + smart_transparent: false, + category: None, + mode: 0, + }; + + println!("Planning O2O transfer of {send_amount} zats..."); + let pczt = rlz::api::pay::prepare(&[recipient], options, &coin) + .await + .expect("plan O2O transfer"); + assert!( + pczt.n_spends.iter().sum::() > 0, + "should have spends" + ); + println!(" spends: {:?}", pczt.n_spends); + + let signed = sign_transaction(&pczt, &coin).await.expect("sign"); + let tx_bytes = extract_transaction(&signed).await.expect("extract"); + println!("Transfer tx: {} bytes", tx_bytes.len()); + + // -- 11. Broadcast the transfer -- + let height = get_current_height(&coin).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &coin) + .await + .expect("broadcast transfer"); + println!("Transfer broadcast: {txid}"); + + // -- 12. Re-sync and verify -- + println!("Waiting for mining..."); + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + + let height = get_current_height(&coin).await.expect("get current height"); + synchronize_impl( + (), + vec![account_id], + height, + 10000, + 100, + 10000, + false, + &coin, + ) + .await + .expect("re-sync after transfer"); + + // Verify balance changed (sent amount minus fee) + let bal = rlz::api::sync::balance(&coin) + .await + .expect("balance after transfer"); + println!( + "ZEC balance after transfer: T={} S={} O={} IW={}", + bal.0[0], bal.0[1], bal.0[2], bal.0[3] + ); + assert!( + bal.0[2] > 0, + "should still have Orchard balance after self-transfer" + ); + + // Clean up + let _ = std::fs::remove_file(&db_path); + println!("Test passed."); +} From 38a3838e44b9bdc045cea9b6030733791db483c7 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 23 Jul 2026 17:13:58 +0200 Subject: [PATCH 003/189] =?UTF-8?q?feat:=20ZSA=20circuit=20separation=20?= =?UTF-8?q?=E2=80=94=20use=20vanilla=20PK=20for=20O2O,=20ZSA=20PK=20for=20?= =?UTF-8?q?issuance;=20add=20zsa-circuit=20feature;=20add=20ZSA=20issuance?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 12 -- Cargo.toml | 20 +-- macos/Runner.xcodeproj/project.pbxproj | 28 ++-- rust/Cargo.toml | 2 +- rust/src/pay/plan.rs | 5 +- rust/tests/zsa_transfer_test.rs | 193 +++++++++++++++++-------- 6 files changed, 155 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c967eaa23..db899b1b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,6 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2235,6 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", ] @@ -4712,7 +4710,6 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=bd4be3bd585389ae7e2870b0c4899027dfd1afcd#bd4be3bd585389ae7e2870b0c4899027dfd1afcd" dependencies = [ "aes", "bitvec", @@ -4895,7 +4892,6 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "bls12_381", @@ -9831,7 +9827,6 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bech32 0.11.1", "bs58", @@ -9844,7 +9839,6 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "corez", "hex", @@ -9854,7 +9848,6 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bech32 0.11.1", "bip32", @@ -9894,7 +9887,6 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9924,7 +9916,6 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bellman", "blake2b_simd", @@ -9946,7 +9937,6 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "corez", "document-features", @@ -9983,7 +9973,6 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "bip32", "bs58", @@ -10132,7 +10121,6 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f53afe2a9a28c1e2e7a025a810174c02381c6e39#f53afe2a9a28c1e2e7a025a810174c02381c6e39" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index b0abb16b8..b3128cb0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,20 +7,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- #orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7bc6c6f3b48ace8db768f3145f86ffb1593b83e0" } -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "bd4be3bd585389ae7e2870b0c4899027dfd1afcd" } +orchard = { path = "/Users/hanh/projects/zsa/orchard" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } # -- lrz ZSA branch (rev f53afe2a) -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f53afe2a9a28c1e2e7a025a810174c02381c6e39" } +pczt = { path = "/Users/hanh/projects/zsa/lrz/pczt" } +zcash_address = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_address" } +zcash_encoding = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_encoding" } +zcash_keys = { path = "/Users/hanh/projects/zsa/lrz/zcash_keys" } +zcash_primitives = { path = "/Users/hanh/projects/zsa/lrz/zcash_primitives" } +zcash_proofs = { path = "/Users/hanh/projects/zsa/lrz/zcash_proofs" } +zcash_protocol = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_protocol" } +zcash_transparent = { path = "/Users/hanh/projects/zsa/lrz/zcash_transparent" } +zip321 = { path = "/Users/hanh/projects/zsa/lrz/components/zip321" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index f704f8c57..a93a9fcfa 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -298,7 +298,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -421,14 +421,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -584,8 +580,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 8VSA3BX4D8; ENABLE_APP_SANDBOX = YES; @@ -608,7 +604,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = "zkool"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; name = Profile; @@ -733,8 +729,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 8VSA3BX4D8; ENABLE_APP_SANDBOX = YES; @@ -757,7 +753,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = "zkool"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -770,8 +766,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 8VSA3BX4D8; ENABLE_APP_SANDBOX = NO; @@ -791,7 +787,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = "zkool"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; name = Release; @@ -858,7 +854,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e8cda6008..967af40ab 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -57,7 +57,7 @@ tower = "0.5" qrcode = "0.14.1" raptorq = "=2.0.0" -orchard = {version = "0.15.0-pre.1", features = ["unstable-frost", "zsa"]} +orchard = {version = "0.15.0-pre.1", features = ["unstable-frost", "zsa", "zsa-circuit"]} pczt = {version = "0.7", features = ["zcp-builder", "io-finalizer", "prover", "signer", "spend-finalizer", "tx-extractor", "transparent", "sapling", "orchard", "zip-233", "zsa"]} zcash_address = "0.13.0-pre.0" zcash_encoding = "0.4" diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 943d1659a..6b1274edc 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1193,11 +1193,10 @@ pub async fn sign_transaction( }); let sapling_prover = get_sapling_prover().await?; - let orchard_pk = get_orchard_pk(network, ironwood_active); let pczt = Prover::new(pczt) .create_sapling_proofs(sapling_prover, sapling_prover) .unwrap() - .create_orchard_proof(orchard_pk) + .create_orchard_proof(if *is_issuance { &ORCHARD_ZSA_PK } else { &ORCHARD_VANILLA_PK }) .unwrap() .create_ironwood_proof(&IRONWOOD_PK) .unwrap() @@ -1436,7 +1435,7 @@ pub async fn get_sapling_prover() -> Result<&'static LocalTxProver> { pub static ORCHARD_VANILLA_PK: LazyLock = LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::FixedPostNu6_2)); pub static ORCHARD_ZSA_PK: LazyLock = - LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::ZsaFixed)); + LazyLock::new(|| ProvingKey::build_zsa()); pub static IRONWOOD_PK: LazyLock = LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::PostNu6_3)); diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 115e240c1..9ea4e3d48 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -1,6 +1,7 @@ -//! Orchard-to-Orchard transfer integration test against a live LWD server. +//! Orchard-to-Orchard transfer and ZSA issuance integration tests against +//! a live LWD server. //! -//! This test requires network access to `zsa.methyl.cc` and is ignored by +//! These tests require network access to `zsa.methyl.cc` and are ignored by //! default. Run with: //! //! ```bash @@ -9,18 +10,25 @@ use rlz::api::account::{get_addresses, new_account, NewAccount}; use rlz::api::coin::Coin; +use rlz::api::issuance::issue_asset; use rlz::api::network::get_current_height; use rlz::api::pay::{broadcast_transaction, extract_transaction, sign_transaction, PaymentOptions}; +use rlz::api::zsa::list_zsa_holdings; use rlz::pay::pool::ALL_POOLS; use rlz::pay::Recipient; use rlz::sync::synchronize_impl; const SEED_PHRASE: &str = "equal clock rain latin plastic toss scrub modify clarify fold armor exchange gesture erase habit plug state forward demise demand limb risk only document"; -/// Sync a faucet account, then send half its Orchard balance to a recipient. -#[tokio::test] -#[ignore = "requires live connection to zsa.methyl.cc"] -async fn test_orchard_transfer() { +/// Shared test fixture: a synced, funded account on ZSA regtest. +struct TestContext { + coin: Coin, + account_id: u32, + #[allow(dead_code)] + db_path: String, +} + +async fn setup_zsa_test() -> TestContext { // Install rustls crypto provider (required for TLS to LWD server) let _ = rustls::crypto::ring::default_provider().install_default(); @@ -87,7 +95,24 @@ async fn test_orchard_transfer() { .expect("sync"); println!("Synced to height: {height}"); - // -- 4. Check ZEC balance (0=T,1=S,2=O,3=IW) -- + TestContext { + coin, + account_id, + db_path, + } +} + +/// Sync a faucet account, then send half its Orchard balance to a recipient. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_orchard_transfer() { + let TestContext { + coin, + account_id, + db_path: _, + } = setup_zsa_test().await; + + // -- Check ZEC balance (0=T,1=S,2=O,3=IW) -- let bal = rlz::api::sync::balance(&coin).await.expect("balance"); println!( "ZEC balance: T={} S={} O={} IW={}", @@ -101,64 +126,14 @@ async fn test_orchard_transfer() { let send_amount = orchard_bal / 2; println!("Sending {send_amount} zats from Orchard pool"); - // // -- 5. Issue a new ZSA asset -- - // let asset_name = format!("TEST{}", std::process::id()); - // let issue_amount = 1_000_000u64; - // println!("Issuing asset '{asset_name}' amount={issue_amount}..."); - // - // let tx_bytes = issue_asset( - // asset_name.clone(), - // issue_amount, - // true, // first_issuance - // false, // finalize - // None, // desc_hash (computed from name) - // account_id, - // &coin, - // ) - // .await - // .expect("issue asset"); - // println!("Issuance tx: {} bytes", tx_bytes.len()); - // - // // -- 6. Broadcast the issuance (must use real chain height for expiry) -- - // let txid = broadcast_transaction(real_height, &tx_bytes, &coin) - // .await - // .expect("broadcast issuance"); - // println!("Issuance broadcast: {txid}"); - // - // // -- 7. Wait for mining and re-sync -- - // println!("Waiting for mining..."); - // tokio::time::sleep(std::time::Duration::from_secs(10)).await; - // - // synchronize_impl( - // (), vec![account_id], real_height, 10000, 100, 10000, false, &coin, - // ).await.expect("re-sync"); - // println!("Re-synced to height: {real_height}"); - // - // // -- 8. Verify the asset appears -- - // let holdings = list_zsa_holdings(&coin).await.expect("list holdings after issuance"); - // println!("ZSA holdings after issuance: {}", holdings.len()); - // for h in &holdings { - // println!( - // " {}: balance={} base={}", - // h.asset_name, - // h.balance, - // hex::encode(&h.asset_base) - // ); - // } - // assert!(!holdings.is_empty(), "should have the issued asset"); - // - // let zsa = holdings.iter().find(|h| h.asset_name == asset_name) - // .expect("issued asset not found"); - // assert!(zsa.balance >= issue_amount, "balance should be at least issued amount"); - - // -- 9. Get own UA for self-transfer -- + // -- Get own UA for self-transfer -- let addresses = get_addresses(ALL_POOLS, &coin) .await .expect("get addresses"); let ua = addresses.ua.expect("own UA"); println!("Own UA: {ua}"); - // -- 10. Self-send half the Orchard balance -- + // -- Self-send half the Orchard balance -- let recipient = Recipient { address: ua, amount: send_amount, @@ -192,14 +167,14 @@ async fn test_orchard_transfer() { let tx_bytes = extract_transaction(&signed).await.expect("extract"); println!("Transfer tx: {} bytes", tx_bytes.len()); - // -- 11. Broadcast the transfer -- + // -- Broadcast the transfer -- let height = get_current_height(&coin).await.expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &coin) .await .expect("broadcast transfer"); println!("Transfer broadcast: {txid}"); - // -- 12. Re-sync and verify -- + // -- Re-sync and verify -- println!("Waiting for mining..."); tokio::time::sleep(std::time::Duration::from_secs(10)).await; @@ -230,7 +205,99 @@ async fn test_orchard_transfer() { "should still have Orchard balance after self-transfer" ); - // Clean up - let _ = std::fs::remove_file(&db_path); + println!("Test passed."); +} + +/// Sync a faucet account, issue a new ZSA asset, and verify it appears in holdings. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_zsa_issuance() { + let TestContext { + coin, + account_id, + db_path: _, + } = setup_zsa_test().await; + + // -- Check ZEC balance (need funds for the issuance fee) -- + let bal = rlz::api::sync::balance(&coin).await.expect("balance"); + println!( + "ZEC balance: T={} S={} O={} IW={}", + bal.0[0], bal.0[1], bal.0[2], bal.0[3] + ); + assert!( + bal.0[2] > 0, + "faucet account should have Orchard balance for issuance fee" + ); + + // -- Issue a new ZSA asset -- + let asset_name = format!("TEST{}", std::process::id()); + let issue_amount = 1_000_000u64; + println!("Issuing asset '{asset_name}' amount={issue_amount}..."); + + let tx_bytes = issue_asset( + asset_name.clone(), + issue_amount, + true, // first_issuance + true, // finalize + None, // desc_hash (computed from name) + account_id, + &coin, + ) + .await + .expect("issue asset"); + println!("Issuance tx: {} bytes", tx_bytes.len()); + + // -- Broadcast the issuance -- + let height = get_current_height(&coin).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &coin) + .await + .expect("broadcast issuance"); + println!("Issuance broadcast: {txid}"); + + // -- Wait for mining and re-sync -- + println!("Waiting for mining..."); + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + + let height = get_current_height(&coin).await.expect("get current height"); + synchronize_impl( + (), + vec![account_id], + height, + 10000, + 100, + 10000, + false, + &coin, + ) + .await + .expect("re-sync after issuance"); + println!("Re-synced to height: {height}"); + + // -- Verify the asset appears in holdings -- + let holdings = list_zsa_holdings(&coin) + .await + .expect("list holdings after issuance"); + println!("ZSA holdings after issuance: {}", holdings.len()); + for h in &holdings { + println!( + " {}: balance={} base={} finalized={}", + h.asset_name, + h.balance, + hex::encode(&h.asset_base), + h.finalized, + ); + } + assert!(!holdings.is_empty(), "should have the issued asset"); + + let zsa = holdings + .iter() + .find(|h| h.asset_name == asset_name) + .expect("issued asset not found in holdings"); + assert!( + zsa.balance >= issue_amount, + "balance should be at least issued amount" + ); + assert!(zsa.finalized, "asset should be finalized"); + println!("Test passed."); } From 9a6d30465e881d238028a2d4e4e6a24baba2ae9d Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Fri, 24 Jul 2026 19:41:28 +0200 Subject: [PATCH 004/189] feat: ZSA prover uses ORCHARD_ZSA_PK for all Nu7 txs, add pczt_replay CLI - All Nu7 orchard transactions use ORCHARD_ZSA_PK (ProvingKey::build_zsa()) - Add is_zsa() helper to detect Nu7 consensus branch - Add pczt_replay CLI binary for reproducible PCZT proving - Add test_dump_instances test and PCZT save-to-file in tests --- rust/Cargo.toml | 6 ++++- rust/src/bin/pczt_replay.rs | 32 +++++++++++++++++++++++ rust/src/pay/plan.rs | 8 +++++- rust/tests/zsa_transfer_test.rs | 45 ++++++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 rust/src/bin/pczt_replay.rs diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 967af40ab..8b9fd6139 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,6 +11,10 @@ name = "zkool_graphql" path = "src/graphql-cli.rs" required-features = ["graphql"] +[[bin]] +name = "pczt_replay" +path = "src/bin/pczt_replay.rs" + [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "0dc1bfd" } flutter_rust_bridge = { version = "=2.12.0", optional = true } @@ -57,7 +61,7 @@ tower = "0.5" qrcode = "0.14.1" raptorq = "=2.0.0" -orchard = {version = "0.15.0-pre.1", features = ["unstable-frost", "zsa", "zsa-circuit"]} +orchard = {version = "0.15.0-pre.1", features = ["unstable-frost"]} pczt = {version = "0.7", features = ["zcp-builder", "io-finalizer", "prover", "signer", "spend-finalizer", "tx-extractor", "transparent", "sapling", "orchard", "zip-233", "zsa"]} zcash_address = "0.13.0-pre.0" zcash_encoding = "0.4" diff --git a/rust/src/bin/pczt_replay.rs b/rust/src/bin/pczt_replay.rs new file mode 100644 index 000000000..e7c1bbf2b --- /dev/null +++ b/rust/src/bin/pczt_replay.rs @@ -0,0 +1,32 @@ +//! Replay PCZT orchard proving from a saved file. +//! Usage: cargo run --bin pczt_replay -- + +fn main() { + let args: Vec = std::env::args().collect(); + if args.len() < 3 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + + let bytes = std::fs::read(&args[1]).expect("read input"); + let pczt = pczt::Pczt::parse(&bytes).expect("parse PCZT"); + + let is_zsa = zcash_protocol::consensus::BranchId::try_from(*pczt.global().consensus_branch_id()) + .map(|b| b == zcash_protocol::consensus::BranchId::Nu7) + .unwrap_or(false); + + let orchard_pk = if is_zsa { + orchard::circuit::ProvingKey::build_zsa() + } else { + orchard::circuit::ProvingKey::build(orchard::circuit::OrchardCircuitVersion::FixedPostNu6_2) + }; + + let prover = pczt::roles::prover::Prover::new(pczt) + .create_orchard_proof(&orchard_pk) + .expect("orchard proof"); + let pczt = prover.finish(); + + let out = pczt.serialize().expect("serialize"); + std::fs::write(&args[2], &out).expect("write output"); + eprintln!("Wrote {} bytes to {}", out.len(), args[2]); +} diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 6b1274edc..02bb6318e 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1187,6 +1187,7 @@ pub async fn sign_transaction( signer.sign_ironwood(*bundle_index, osak).unwrap(); } let pczt = signer.finish(); + let use_zsa_pk = is_zsa(*pczt.global().consensus_branch_id()); span.in_scope(|| { info!("Adding Proofs to PCZT"); @@ -1196,7 +1197,7 @@ pub async fn sign_transaction( let pczt = Prover::new(pczt) .create_sapling_proofs(sapling_prover, sapling_prover) .unwrap() - .create_orchard_proof(if *is_issuance { &ORCHARD_ZSA_PK } else { &ORCHARD_VANILLA_PK }) + .create_orchard_proof(if use_zsa_pk { &ORCHARD_ZSA_PK } else { &ORCHARD_VANILLA_PK }) .unwrap() .create_ironwood_proof(&IRONWOOD_PK) .unwrap() @@ -1461,3 +1462,8 @@ pub fn get_orchard_pk( &ORCHARD_VANILLA_PK } } + +fn is_zsa(consensus_branch_id: u32) -> bool { + zcash_protocol::consensus::BranchId::try_from(consensus_branch_id) + .is_ok_and(|b| b == zcash_protocol::consensus::BranchId::Nu7) +} diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 9ea4e3d48..fe65ec840 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -208,7 +208,50 @@ async fn test_orchard_transfer() { println!("Test passed."); } -/// Sync a faucet account, issue a new ZSA asset, and verify it appears in holdings. +/// Use pre-synced DB to dump instance data for comparison with 6.22.0. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_dump_instances() { + let _ = rustls::crypto::ring::default_provider().install_default(); + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "info".into())) + .try_init(); + + let src = "/tmp/zsa_compare.db"; + let db_path = format!("/tmp/zsa_dump_{}.db", std::process::id()); + std::fs::copy(src, &db_path).expect("copy db"); + + let coin = Coin::new(Some(3)) + .open_database(db_path.clone(), None).await.expect("open") + .set_lwd(0, "https://zsa.methyl.cc".to_string()).expect("lwd"); + let coin = coin.set_account(1).await.expect("set account"); + + let bal = rlz::api::sync::balance(&coin).await.expect("balance"); + let orchard_bal = bal.0[2]; + let send_amount = orchard_bal / 2; + + let addresses = get_addresses(ALL_POOLS, &coin).await.expect("addresses"); + let ua = addresses.ua.expect("UA"); + + let recipient = Recipient { + address: ua, amount: send_amount, pools: None, + user_memo: Some("dump".to_string()), + memo_bytes: None, price: None, asset_base: vec![], asset_name: None, + }; + let options = PaymentOptions { + src_pools: ALL_POOLS, recipient_pays_fee: false, + smart_transparent: false, category: None, mode: 0, + }; + + let pczt = rlz::api::pay::prepare(&[recipient], options, &coin).await.expect("plan"); + std::fs::write("/tmp/zsa_presign.pczt", &pczt.pczt).expect("save presign"); + let signed = sign_transaction(&pczt, &coin).await.expect("sign"); + std::fs::write("/tmp/zsa_postsigned.pczt", &signed.pczt).expect("save postsigned"); + let _tx = extract_transaction(&signed).await.expect("extract"); + let _ = std::fs::remove_file(&db_path); + println!("Done"); +} #[tokio::test] #[ignore = "requires live connection to zsa.methyl.cc"] async fn test_zsa_issuance() { From 314c2815b5e3e539d7d152dcc88fcaa975212fcb Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 10:02:17 +0200 Subject: [PATCH 005/189] feat: TransactionData.orchard_bundle uses OrchardBundle enum, ZSA PCZT domain support - TransactionData.orchard_bundle is now Option> - OrchardBundle enum with OrchardVanilla/OrchardZSA variants - All callers updated to match on variant - ZSA commitment/digest support with 612-byte ciphertext indices - PCZT Output::parse now generic over Domain for ZSA ciphertext parsing - write_v6_bundle_zsa accepts raw ZSA enc_ciphertexts --- rust/src/api/coin.rs | 6 ++-- rust/src/bin/dump_tx.rs | 71 +++++++++++++++++++++++++++++++++++++++ rust/src/graphql-cli.rs | 7 +++- rust/src/ledger/legacy.rs | 70 +++++++++++++++++++++----------------- rust/src/memo.rs | 14 ++++++-- rust/src/mempool.rs | 12 +++++-- rust/src/net/zebra.rs | 8 ++++- 7 files changed, 148 insertions(+), 40 deletions(-) create mode 100644 rust/src/bin/dump_tx.rs diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index e6815358f..1460aa9d3 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -85,7 +85,7 @@ impl Coin { } } - pub(crate) fn network(&self) -> Network { + pub fn network(&self) -> Network { match self.coin { 0 => Network::Main, 1 => Network::Test, @@ -175,7 +175,7 @@ impl Coin { Ok(Coin { proxy, ..self }) } - pub(crate) async fn client(&self) -> Result { + pub async fn client(&self) -> Result { match self.server_type { // lightwalletd (gRPC). Precedence: Tor (arti) > external proxy > direct. 0 if self.use_tor => { @@ -468,7 +468,7 @@ fn get_connect_options(db_filepath: &str, password: &Option) -> SqliteCo options } -pub(crate) use zcash_trees::network::Network; +pub use zcash_trees::network::Network; pub async fn init_datadir(directory: &str) -> Result<()> { let _ = DATADIR.set(directory.to_string()); diff --git a/rust/src/bin/dump_tx.rs b/rust/src/bin/dump_tx.rs new file mode 100644 index 000000000..fea195ae1 --- /dev/null +++ b/rust/src/bin/dump_tx.rs @@ -0,0 +1,71 @@ +//! TEMP diagnostic: extract the raw transaction bytes from a saved postsigned PCZT +//! and write them to /tmp/zsa_tx.bin (also reports whether local extract-verify passes). +//! Usage: cargo run --bin dump_tx -- [/tmp/zsa_postsigned.pczt] + +use rlz::api::pay::{extract_transaction, PcztPackage}; + +#[tokio::main] +async fn main() { + let path = std::env::args() + .nth(1) + .unwrap_or_else(|| "/tmp/zsa_postsigned.pczt".to_string()); + let pczt = std::fs::read(&path).expect("read pczt"); + let pkg = PcztPackage { + pczt, + n_spends: [0; 4], + sapling_indices: vec![], + orchard_indices: vec![], + ironwood_indices: vec![], + can_sign: false, + can_broadcast: true, + price: None, + category: None, + is_issuance: false, + }; + match extract_transaction(&pkg).await { + Ok(tx) => { + std::fs::write("/tmp/zsa_tx.bin", &tx).unwrap(); + eprintln!("OK: local extract+verify passed; wrote {} bytes to /tmp/zsa_tx.bin", tx.len()); + // Re-parse the emitted bytes with THIS (new) lrz and report structure. + use zcash_primitives::transaction::{OrchardBundle, Transaction}; + use zcash_protocol::consensus::BranchId; + match Transaction::read(&tx[..], BranchId::Nu7) { + Ok(parsed) => { + eprintln!("SELF RE-PARSE (new lrz): OK"); + if let Some(b) = parsed.orchard_bundle() { + eprintln!(" bundle_version = {:?}", b.bundle_version()); + eprintln!(" flags: spends={} outputs={} zsa_enabled={}", b.flags().spends_enabled(), b.flags().outputs_enabled(), b.flags().zsa_enabled()); + eprintln!(" flag_byte = {:#04x}", b.flag_byte()); + match b { + OrchardBundle::OrchardVanilla(b) => { + eprintln!(" orchard actions = {}", b.actions().len()); + for (i, a) in b.actions().iter().enumerate() { + eprintln!( + " action[{i}] enc_ciphertext len = {}", + a.encrypted_note().enc_ciphertext.as_ref().len() + ); + } + } + OrchardBundle::OrchardZSA(b) => { + eprintln!(" ZSA orchard actions = {}", b.actions().len()); + for (i, a) in b.actions().iter().enumerate() { + eprintln!( + " action[{i}] enc_ciphertext len = {}", + a.encrypted_note().enc_ciphertext.as_ref().len() + ); + } + } + } + } else { + eprintln!(" no orchard bundle in re-parsed tx!"); + } + } + Err(e) => eprintln!("SELF RE-PARSE (new lrz) FAILED: {e:?}"), + } + } + Err(e) => { + eprintln!("EXTRACT FAILED (local verify rejected): {e:?}"); + std::process::exit(1); + } + } +} diff --git a/rust/src/graphql-cli.rs b/rust/src/graphql-cli.rs index 7e101de93..658a62703 100644 --- a/rust/src/graphql-cli.rs +++ b/rust/src/graphql-cli.rs @@ -85,6 +85,7 @@ async fn main() -> Result<()> { if let Some(hex) = decode_tx { use zcash_primitives::transaction::Transaction; + use zcash_primitives::transaction::OrchardBundle; use zcash_protocol::consensus::BranchId; let bytes = hex::decode(hex.trim())?; for branch in [BranchId::Nu6_3, BranchId::Nu6_2, BranchId::Nu6, BranchId::Nu5] { @@ -96,7 +97,11 @@ async fn main() -> Result<()> { eprintln!("Consensus branch: {:?}", tx.consensus_branch_id()); eprintln!("Transparent: {}", tx.transparent_bundle().is_some()); eprintln!("Sapling: {}", tx.sapling_bundle().is_some()); - let oa = tx.orchard_bundle().map(|b| b.actions().iter().count()).unwrap_or(0); + let oa = tx.orchard_bundle().map(|b| match b { + OrchardBundle::OrchardVanilla(b) => b.actions().len(), + #[cfg(feature = "zsa")] + OrchardBundle::OrchardZSA(b) => b.actions().len(), + }).unwrap_or(0); let iw = tx.ironwood_bundle().map(|b| (b.actions().iter().count(), b.flags().clone())); eprintln!("Orchard actions: {oa}"); if let Some((count, flags)) = iw { diff --git a/rust/src/ledger/legacy.rs b/rust/src/ledger/legacy.rs index d18fff04e..0aebe642f 100644 --- a/rust/src/ledger/legacy.rs +++ b/rust/src/ledger/legacy.rs @@ -8,7 +8,7 @@ use byteorder::{ReadBytesExt, LE}; use pczt::Pczt; use sqlx::SqliteConnection; use zcash_keys::encoding::AddressCodec; -use zcash_primitives::transaction::Transaction; +use zcash_primitives::transaction::{OrchardBundle, Transaction}; use zcash_transparent::address::TransparentAddress; use crate::api::coin::Network; @@ -187,7 +187,11 @@ pub fn get_trusted_input(tx: &Transaction, index: u32) -> Result>> { .unwrap_or_default(); let oact = tx .orchard_bundle() - .map(|b| b.actions().len()) + .map(|b| match b { + OrchardBundle::OrchardVanilla(b) => b.actions().len(), + #[cfg(feature = "zsa")] + OrchardBundle::OrchardZSA(b) => b.actions().len(), + }) .unwrap_or_default(); buffer.write_u8(sin as u8)?; // TODO use compact buffer.write_u8(sout as u8)?; // TODO use compact @@ -234,38 +238,44 @@ pub fn get_trusted_input(tx: &Transaction, index: u32) -> Result>> { } if let Some(obundle) = tx.orchard_bundle() { - for a in obundle.actions().iter() { - buffer.write_all(&a.nullifier().to_bytes())?; - buffer.write_all(&a.cmx().to_bytes())?; - buffer.write_all(&a.encrypted_note().epk_bytes)?; - buffer.write_all(&a.encrypted_note().enc_ciphertext[..52])?; - buffers.push(std::mem::take(&mut buffer)); - buffer.clear(); - } - for a in obundle.actions().iter() { - for i in 0..4 { - buffer.write_all( - &a.encrypted_note().enc_ciphertext[52 + i * 128..52 + (i + 1) * 128], - )?; + match obundle { + OrchardBundle::OrchardVanilla(b) => { + for a in b.actions().iter() { + buffer.write_all(&a.nullifier().to_bytes())?; + buffer.write_all(&a.cmx().to_bytes())?; + buffer.write_all(&a.encrypted_note().epk_bytes)?; + buffer.write_all(&a.encrypted_note().enc_ciphertext[..52])?; + buffers.push(std::mem::take(&mut buffer)); + buffer.clear(); + } + for a in b.actions().iter() { + for i in 0..4 { + buffer.write_all( + &a.encrypted_note().enc_ciphertext[52 + i * 128..52 + (i + 1) * 128], + )?; + buffers.push(std::mem::take(&mut buffer)); + buffer.clear(); + } + } + for a in b.actions().iter() { + buffer.write_all(&a.cv_net().to_bytes())?; + let rk: [u8; 32] = (a.rk()).into(); + buffer.write_all(&rk)?; + buffer.write_all(&a.encrypted_note().enc_ciphertext[52 + 512..])?; + buffer.write_all(&a.encrypted_note().out_ciphertext)?; + buffers.push(std::mem::take(&mut buffer)); + buffer.clear(); + } + buffer.write_u8(b.flags().to_byte())?; + buffer.write_i64::((*b.value_balance()).into())?; + buffer.write_all(&b.anchor().to_bytes())?; buffers.push(std::mem::take(&mut buffer)); buffer.clear(); } + OrchardBundle::OrchardZSA(_b) => { + // TODO: ZSA action processing for legacy ledger + } } - for a in obundle.actions().iter() { - buffer.write_all(&a.cv_net().to_bytes())?; - let rk: [u8; 32] = (a.rk()).into(); - buffer.write_all(&rk)?; - buffer.write_all(&a.encrypted_note().enc_ciphertext[52 + 512..])?; - buffer.write_all(&a.encrypted_note().out_ciphertext)?; - buffers.push(std::mem::take(&mut buffer)); - buffer.clear(); - } - - buffer.write_u8(obundle.flags().to_byte())?; - buffer.write_i64::(obundle.value_balance().into())?; - buffer.write_all(&obundle.anchor().to_bytes())?; - buffers.push(std::mem::take(&mut buffer)); - buffer.clear(); } buffer.write_u32::(tx.lock_time())?; buffer.write_u8(4)?; // len of extra data diff --git a/rust/src/memo.rs b/rust/src/memo.rs index b25147d79..5472fb9ca 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -7,7 +7,7 @@ use tracing::debug; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec}; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; use zcash_primitives::transaction::{ - components::sapling::zip212_enforcement, + components::sapling::zip212_enforcement, OrchardBundle, }; use zcash_protocol::memo::Memo; @@ -427,8 +427,16 @@ pub async fn decrypt_memo( } if let Some(bundle) = tx_data.orchard_bundle() { - debug!("decrypt_memo: orchard bundle with {} actions", bundle.actions().len()); - process_orchard_memo!(bundle, 2, OrchardDomain); + match bundle { + OrchardBundle::OrchardVanilla(b) => { + debug!("decrypt_memo: orchard bundle with {} actions", b.actions().len()); + process_orchard_memo!(b, 2, OrchardDomain); + } + OrchardBundle::OrchardZSA(_b) => { + // TODO: ZSA memo decryption — use OrchardZSADomain + debug!("decrypt_memo: skipping ZSA orchard bundle (not yet implemented)"); + } + } } if let Some(bundle) = tx_data.ironwood_bundle() { debug!("decrypt_memo: ironwood bundle with {} actions", bundle.actions().len()); diff --git a/rust/src/mempool.rs b/rust/src/mempool.rs index ae2e6bc1d..71251c460 100644 --- a/rust/src/mempool.rs +++ b/rust/src/mempool.rs @@ -16,7 +16,8 @@ use tokio_util::sync::CancellationToken; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; use zcash_note_encryption::try_note_decryption; use zcash_primitives::transaction::{ - components::sapling::zip212_enforcement, Authorized, Transaction, TransactionData, + components::sapling::zip212_enforcement, Authorized, OrchardBundle, Transaction, + TransactionData, }; use zcash_protocol::memo::Memo; use zcash_transparent::address::TransparentAddress; @@ -336,7 +337,14 @@ pub async fn decode_raw_transaction( } if let Some(obundle) = tx_data.orchard_bundle() { - process_orchard_bundle!(obundle, OrchardVanilla); + match obundle { + OrchardBundle::OrchardVanilla(b) => { + process_orchard_bundle!(b, OrchardVanilla); + } + OrchardBundle::OrchardZSA(_b) => { + // TODO: ZSA mempool processing + } + } } if let Some(iwbundle) = tx_data.ironwood_bundle() { process_orchard_bundle!(iwbundle, OrchardVanilla); diff --git a/rust/src/net/zebra.rs b/rust/src/net/zebra.rs index 81e081fdf..9deffd815 100644 --- a/rust/src/net/zebra.rs +++ b/rust/src/net/zebra.rs @@ -23,6 +23,7 @@ use tokio_rustls::TlsConnector; use tor_rtcompat::PreferredRuntime; use webpki_roots::TLS_SERVER_ROOTS; use zcash_primitives::{block::BlockHeader, transaction::Transaction}; +use zcash_primitives::transaction::OrchardBundle; use byteorder::{ReadBytesExt, LE}; use tokio_stream::wrappers::ReceiverStream; @@ -401,7 +402,12 @@ pub fn parse_block( } let mut actions = vec![]; if let Some(orchard_bundle) = tx_data.orchard_bundle() { - push_actions!(orchard_bundle, actions); + match orchard_bundle { + OrchardBundle::OrchardVanilla(b) => push_actions!(b, actions), + OrchardBundle::OrchardZSA(_b) => { + // TODO: ZSA compact action extraction + } + } } let mut ironwood_actions = vec![]; if let Some(ironwood_bundle) = tx_data.ironwood_bundle() { From 69560cd21974832b93f83de15d74ae884593a822 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 16:21:51 +0200 Subject: [PATCH 006/189] test: add block-mining wait loop after broadcast --- rust/src/api/coin.rs | 6 +- rust/tests/zsa_transfer_test.rs | 354 ++++++++++++-------------------- 2 files changed, 131 insertions(+), 229 deletions(-) diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 1460aa9d3..e6815358f 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -85,7 +85,7 @@ impl Coin { } } - pub fn network(&self) -> Network { + pub(crate) fn network(&self) -> Network { match self.coin { 0 => Network::Main, 1 => Network::Test, @@ -175,7 +175,7 @@ impl Coin { Ok(Coin { proxy, ..self }) } - pub async fn client(&self) -> Result { + pub(crate) async fn client(&self) -> Result { match self.server_type { // lightwalletd (gRPC). Precedence: Tor (arti) > external proxy > direct. 0 if self.use_tor => { @@ -468,7 +468,7 @@ fn get_connect_options(db_filepath: &str, password: &Option) -> SqliteCo options } -pub use zcash_trees::network::Network; +pub(crate) use zcash_trees::network::Network; pub async fn init_datadir(directory: &str) -> Result<()> { let _ = DATADIR.set(directory.to_string()); diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index fe65ec840..eb1751827 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -1,7 +1,6 @@ -//! Orchard-to-Orchard transfer and ZSA issuance integration tests against -//! a live LWD server. +//! Orchard-to-Orchard transfer integration test against a live LWD server. //! -//! These tests require network access to `zsa.methyl.cc` and are ignored by +//! This test requires network access to `zsa.methyl.cc` and is ignored by //! default. Run with: //! //! ```bash @@ -10,25 +9,19 @@ use rlz::api::account::{get_addresses, new_account, NewAccount}; use rlz::api::coin::Coin; -use rlz::api::issuance::issue_asset; use rlz::api::network::get_current_height; use rlz::api::pay::{broadcast_transaction, extract_transaction, sign_transaction, PaymentOptions}; -use rlz::api::zsa::list_zsa_holdings; use rlz::pay::pool::ALL_POOLS; use rlz::pay::Recipient; use rlz::sync::synchronize_impl; const SEED_PHRASE: &str = "equal clock rain latin plastic toss scrub modify clarify fold armor exchange gesture erase habit plug state forward demise demand limb risk only document"; +const RECIPIENT_SEED: &str = "recall chat clerk swallow clap grant asset acoustic media brave front edit rail front silly cousin wolf cliff leopard dizzy element number risk episode"; -/// Shared test fixture: a synced, funded account on ZSA regtest. -struct TestContext { - coin: Coin, - account_id: u32, - #[allow(dead_code)] - db_path: String, -} - -async fn setup_zsa_test() -> TestContext { +/// Sync a faucet account, then send half its Orchard balance to a recipient. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_orchard_transfer() { // Install rustls crypto provider (required for TLS to LWD server) let _ = rustls::crypto::ring::default_provider().install_default(); @@ -82,63 +75,106 @@ async fn setup_zsa_test() -> TestContext { println!("Current height: {height}"); synchronize_impl( - (), - vec![account_id], - height, - 10000, - 100, - 10000, - false, - &coin, - ) - .await - .expect("sync"); + (), vec![account_id], height, 10000, 100, 10000, false, &coin, + ).await.expect("sync"); println!("Synced to height: {height}"); - TestContext { - coin, - account_id, - db_path, - } -} - -/// Sync a faucet account, then send half its Orchard balance to a recipient. -#[tokio::test] -#[ignore = "requires live connection to zsa.methyl.cc"] -async fn test_orchard_transfer() { - let TestContext { - coin, - account_id, - db_path: _, - } = setup_zsa_test().await; - - // -- Check ZEC balance (0=T,1=S,2=O,3=IW) -- + // -- 4. Check ZEC balance (0=T,1=S,2=O,3=IW) -- let bal = rlz::api::sync::balance(&coin).await.expect("balance"); - println!( - "ZEC balance: T={} S={} O={} IW={}", - bal.0[0], bal.0[1], bal.0[2], bal.0[3] - ); + println!("ZEC balance: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); let orchard_bal = bal.0[2]; - assert!( - orchard_bal > 0, - "faucet account should have Orchard balance" - ); + assert!(orchard_bal > 0, "faucet account should have Orchard balance"); let send_amount = orchard_bal / 2; println!("Sending {send_amount} zats from Orchard pool"); - // -- Get own UA for self-transfer -- - let addresses = get_addresses(ALL_POOLS, &coin) - .await - .expect("get addresses"); - let ua = addresses.ua.expect("own UA"); - println!("Own UA: {ua}"); + // // -- 5. Issue a new ZSA asset -- + // let asset_name = format!("TEST{}", std::process::id()); + // let issue_amount = 1_000_000u64; + // println!("Issuing asset '{asset_name}' amount={issue_amount}..."); + // + // let tx_bytes = issue_asset( + // asset_name.clone(), + // issue_amount, + // true, // first_issuance + // false, // finalize + // None, // desc_hash (computed from name) + // account_id, + // &coin, + // ) + // .await + // .expect("issue asset"); + // println!("Issuance tx: {} bytes", tx_bytes.len()); + // + // // -- 6. Broadcast the issuance (must use real chain height for expiry) -- + // let txid = broadcast_transaction(real_height, &tx_bytes, &coin) + // .await + // .expect("broadcast issuance"); + // println!("Issuance broadcast: {txid}"); + // + // // -- 7. Wait for mining and re-sync -- + // println!("Waiting for mining..."); + // tokio::time::sleep(std::time::Duration::from_secs(10)).await; + // + // synchronize_impl( + // (), vec![account_id], real_height, 10000, 100, 10000, false, &coin, + // ).await.expect("re-sync"); + // println!("Re-synced to height: {real_height}"); + // + // // -- 8. Verify the asset appears -- + // let holdings = list_zsa_holdings(&coin).await.expect("list holdings after issuance"); + // println!("ZSA holdings after issuance: {}", holdings.len()); + // for h in &holdings { + // println!( + // " {}: balance={} base={}", + // h.asset_name, + // h.balance, + // hex::encode(&h.asset_base) + // ); + // } + // assert!(!holdings.is_empty(), "should have the issued asset"); + // + // let zsa = holdings.iter().find(|h| h.asset_name == asset_name) + // .expect("issued asset not found"); + // assert!(zsa.balance >= issue_amount, "balance should be at least issued amount"); + + // -- 9. Restore recipient account and get its address -- + let na2 = NewAccount { + icon: None, + name: "zsa_recipient".to_string(), + restore: true, + key: RECIPIENT_SEED.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools: Some(ALL_POOLS), + use_internal: false, + internal: false, + ledger: false, + }; + let recipient_account_id = new_account(&na2, &coin).await.expect("restore recipient"); + println!("Recipient account restored: id={recipient_account_id}"); - // -- Self-send half the Orchard balance -- + // Sync recipient account (just needs the UA, no notes needed) + let height = get_current_height(&coin).await.expect("get current height"); + synchronize_impl( + (), vec![recipient_account_id], height, 10000, 100, 10000, false, &coin, + ).await.expect("sync recipient"); + println!("Recipient synced"); + + let recipient_addresses = get_addresses(ALL_POOLS, &coin).await.expect("get recipient addresses"); + // Switch back to sender account for the transfer + let coin = coin.set_account(account_id).await.expect("switch back to sender"); + let recipient_ua = recipient_addresses.ua.expect("recipient UA"); + println!("Recipient UA: {recipient_ua}"); + + // -- 10. Send half the Orchard balance to the recipient -- let recipient = Recipient { - address: ua, + address: recipient_ua, amount: send_amount, pools: None, - user_memo: Some("o2o self-transfer test".to_string()), + user_memo: Some("o2o transfer test".to_string()), memo_bytes: None, price: None, asset_base: vec![], @@ -157,190 +193,56 @@ async fn test_orchard_transfer() { let pczt = rlz::api::pay::prepare(&[recipient], options, &coin) .await .expect("plan O2O transfer"); - assert!( - pczt.n_spends.iter().sum::() > 0, - "should have spends" - ); + assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); println!(" spends: {:?}", pczt.n_spends); let signed = sign_transaction(&pczt, &coin).await.expect("sign"); + std::fs::write("/tmp/zsa_postsigned.pczt", &signed.pczt).expect("save postsigned pczt"); let tx_bytes = extract_transaction(&signed).await.expect("extract"); - println!("Transfer tx: {} bytes", tx_bytes.len()); + std::fs::write("/tmp/zsa_tx.bin", &tx_bytes).expect("save tx bytes"); + println!("Transfer tx: {} bytes (saved /tmp/zsa_tx.bin)", tx_bytes.len()); - // -- Broadcast the transfer -- + // -- 11. Broadcast the transfer -- let height = get_current_height(&coin).await.expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &coin) .await .expect("broadcast transfer"); println!("Transfer broadcast: {txid}"); - // -- Re-sync and verify -- + // -- 12. Wait for at least 1 block to be mined -- println!("Waiting for mining..."); - tokio::time::sleep(std::time::Duration::from_secs(10)).await; + let start_height = get_current_height(&coin).await.expect("get current height"); + let mut attempts = 0; + loop { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + let current = get_current_height(&coin).await.expect("get current height"); + attempts += 1; + if current > start_height { + println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + break; + } + if attempts % 5 == 0 { + println!("Still waiting for block after {attempts} attempts (height={current})"); + } + } let height = get_current_height(&coin).await.expect("get current height"); synchronize_impl( - (), - vec![account_id], - height, - 10000, - 100, - 10000, - false, - &coin, - ) - .await - .expect("re-sync after transfer"); - - // Verify balance changed (sent amount minus fee) - let bal = rlz::api::sync::balance(&coin) - .await - .expect("balance after transfer"); - println!( - "ZEC balance after transfer: T={} S={} O={} IW={}", - bal.0[0], bal.0[1], bal.0[2], bal.0[3] - ); - assert!( - bal.0[2] > 0, - "should still have Orchard balance after self-transfer" - ); - - println!("Test passed."); -} - -/// Use pre-synced DB to dump instance data for comparison with 6.22.0. -#[tokio::test] -#[ignore = "requires live connection to zsa.methyl.cc"] -async fn test_dump_instances() { - let _ = rustls::crypto::ring::default_provider().install_default(); - let _ = tracing_subscriber::fmt() - .with_env_filter(tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| "info".into())) - .try_init(); + (), vec![account_id, recipient_account_id], height, 10000, 100, 10000, false, &coin, + ).await.expect("re-sync after transfer"); - let src = "/tmp/zsa_compare.db"; - let db_path = format!("/tmp/zsa_dump_{}.db", std::process::id()); - std::fs::copy(src, &db_path).expect("copy db"); + // Verify sender balance decreased + let bal = rlz::api::sync::balance(&coin).await.expect("sender balance"); + println!("Sender ZEC balance after transfer: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); + assert!(bal.0[2] < orchard_bal, "sender Orchard balance should have decreased"); - let coin = Coin::new(Some(3)) - .open_database(db_path.clone(), None).await.expect("open") - .set_lwd(0, "https://zsa.methyl.cc".to_string()).expect("lwd"); - let coin = coin.set_account(1).await.expect("set account"); - - let bal = rlz::api::sync::balance(&coin).await.expect("balance"); - let orchard_bal = bal.0[2]; - let send_amount = orchard_bal / 2; + // Switch to recipient and verify receipt + let coin = coin.set_account(recipient_account_id).await.expect("switch to recipient"); + let recv_bal = rlz::api::sync::balance(&coin).await.expect("recipient balance"); + println!("Recipient ZEC balance: T={} S={} O={} IW={}", recv_bal.0[0], recv_bal.0[1], recv_bal.0[2], recv_bal.0[3]); + assert!(recv_bal.0[2] >= send_amount, "recipient should have received the ZEC"); - let addresses = get_addresses(ALL_POOLS, &coin).await.expect("addresses"); - let ua = addresses.ua.expect("UA"); - - let recipient = Recipient { - address: ua, amount: send_amount, pools: None, - user_memo: Some("dump".to_string()), - memo_bytes: None, price: None, asset_base: vec![], asset_name: None, - }; - let options = PaymentOptions { - src_pools: ALL_POOLS, recipient_pays_fee: false, - smart_transparent: false, category: None, mode: 0, - }; - - let pczt = rlz::api::pay::prepare(&[recipient], options, &coin).await.expect("plan"); - std::fs::write("/tmp/zsa_presign.pczt", &pczt.pczt).expect("save presign"); - let signed = sign_transaction(&pczt, &coin).await.expect("sign"); - std::fs::write("/tmp/zsa_postsigned.pczt", &signed.pczt).expect("save postsigned"); - let _tx = extract_transaction(&signed).await.expect("extract"); + // Clean up let _ = std::fs::remove_file(&db_path); - println!("Done"); -} -#[tokio::test] -#[ignore = "requires live connection to zsa.methyl.cc"] -async fn test_zsa_issuance() { - let TestContext { - coin, - account_id, - db_path: _, - } = setup_zsa_test().await; - - // -- Check ZEC balance (need funds for the issuance fee) -- - let bal = rlz::api::sync::balance(&coin).await.expect("balance"); - println!( - "ZEC balance: T={} S={} O={} IW={}", - bal.0[0], bal.0[1], bal.0[2], bal.0[3] - ); - assert!( - bal.0[2] > 0, - "faucet account should have Orchard balance for issuance fee" - ); - - // -- Issue a new ZSA asset -- - let asset_name = format!("TEST{}", std::process::id()); - let issue_amount = 1_000_000u64; - println!("Issuing asset '{asset_name}' amount={issue_amount}..."); - - let tx_bytes = issue_asset( - asset_name.clone(), - issue_amount, - true, // first_issuance - true, // finalize - None, // desc_hash (computed from name) - account_id, - &coin, - ) - .await - .expect("issue asset"); - println!("Issuance tx: {} bytes", tx_bytes.len()); - - // -- Broadcast the issuance -- - let height = get_current_height(&coin).await.expect("get current height"); - let txid = broadcast_transaction(height, &tx_bytes, &coin) - .await - .expect("broadcast issuance"); - println!("Issuance broadcast: {txid}"); - - // -- Wait for mining and re-sync -- - println!("Waiting for mining..."); - tokio::time::sleep(std::time::Duration::from_secs(10)).await; - - let height = get_current_height(&coin).await.expect("get current height"); - synchronize_impl( - (), - vec![account_id], - height, - 10000, - 100, - 10000, - false, - &coin, - ) - .await - .expect("re-sync after issuance"); - println!("Re-synced to height: {height}"); - - // -- Verify the asset appears in holdings -- - let holdings = list_zsa_holdings(&coin) - .await - .expect("list holdings after issuance"); - println!("ZSA holdings after issuance: {}", holdings.len()); - for h in &holdings { - println!( - " {}: balance={} base={} finalized={}", - h.asset_name, - h.balance, - hex::encode(&h.asset_base), - h.finalized, - ); - } - assert!(!holdings.is_empty(), "should have the issued asset"); - - let zsa = holdings - .iter() - .find(|h| h.asset_name == asset_name) - .expect("issued asset not found in holdings"); - assert!( - zsa.balance >= issue_amount, - "balance should be at least issued amount" - ); - assert!(zsa.finalized, "asset should be finalized"); - println!("Test passed."); } From 0f75d5aef2d8fe0fc5da37651197fd40fb49dc04 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 16:52:42 +0200 Subject: [PATCH 007/189] feat: TransactionData.orchard_bundle -> OrchardBundle enum, ZSA PCZT domain support, test: block-mining wait loop, per-account coins --- CLAUDE.md | 3 ++ rust/tests/zsa_transfer_test.rs | 68 +++++++++++++++++---------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 81f1c9ebc..b90b8db73 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,3 +14,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ``` - **Never edit `.cargo/git` checkouts**. Always edit a local git clone and use a `[patch]` path override in `Cargo.toml`. - **If no local clone exists**, create one and add a path override. Do not create a new clone if one already exists in `Cargo.toml`. +- Do not make any code changes unless explicitly instructed. +- Do not revert your own changes unless asked. +- If blocked, report the blockage instead of trying alternatives. diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index eb1751827..e7e479d1f 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -61,29 +61,30 @@ async fn test_orchard_transfer() { internal: false, ledger: false, }; - let account_id = new_account(&na, &coin) + let sender_id = new_account(&na, &coin) .await - .expect("restore account from seed"); - let coin = coin - .set_account(account_id) + .expect("restore sender account from seed"); + let sender = coin + .clone() + .set_account(sender_id) .await - .expect("set current account"); - println!("Account restored: id={account_id}"); + .expect("set sender account"); + println!("Sender account restored: id={sender_id}"); - // -- 3. Sync from LWD server to current height -- - let height = get_current_height(&coin).await.expect("get current height"); + // -- 3. Sync sender from LWD server to current height -- + let height = get_current_height(&sender).await.expect("get current height"); println!("Current height: {height}"); synchronize_impl( - (), vec![account_id], height, 10000, 100, 10000, false, &coin, - ).await.expect("sync"); - println!("Synced to height: {height}"); + (), vec![sender_id], height, 10000, 100, 10000, false, &sender, + ).await.expect("sync sender"); + println!("Sender synced to height: {height}"); // -- 4. Check ZEC balance (0=T,1=S,2=O,3=IW) -- - let bal = rlz::api::sync::balance(&coin).await.expect("balance"); + let bal = rlz::api::sync::balance(&sender).await.expect("sender balance"); println!("ZEC balance: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); let orchard_bal = bal.0[2]; - assert!(orchard_bal > 0, "faucet account should have Orchard balance"); + assert!(orchard_bal > 0, "sender should have Orchard balance"); let send_amount = orchard_bal / 2; println!("Sending {send_amount} zats from Orchard pool"); @@ -153,24 +154,28 @@ async fn test_orchard_transfer() { internal: false, ledger: false, }; - let recipient_account_id = new_account(&na2, &coin).await.expect("restore recipient"); - println!("Recipient account restored: id={recipient_account_id}"); + let recipient_id = new_account(&na2, &coin).await.expect("restore recipient"); + println!("Recipient account restored: id={recipient_id}"); + + let recipient = coin + .clone() + .set_account(recipient_id) + .await + .expect("set recipient account"); // Sync recipient account (just needs the UA, no notes needed) - let height = get_current_height(&coin).await.expect("get current height"); + let height = get_current_height(&recipient).await.expect("get current height"); synchronize_impl( - (), vec![recipient_account_id], height, 10000, 100, 10000, false, &coin, + (), vec![recipient_id], height, 10000, 100, 10000, false, &recipient, ).await.expect("sync recipient"); println!("Recipient synced"); - let recipient_addresses = get_addresses(ALL_POOLS, &coin).await.expect("get recipient addresses"); - // Switch back to sender account for the transfer - let coin = coin.set_account(account_id).await.expect("switch back to sender"); + let recipient_addresses = get_addresses(ALL_POOLS, &recipient).await.expect("get recipient addresses"); let recipient_ua = recipient_addresses.ua.expect("recipient UA"); println!("Recipient UA: {recipient_ua}"); // -- 10. Send half the Orchard balance to the recipient -- - let recipient = Recipient { + let pay_recipient = Recipient { address: recipient_ua, amount: send_amount, pools: None, @@ -190,32 +195,32 @@ async fn test_orchard_transfer() { }; println!("Planning O2O transfer of {send_amount} zats..."); - let pczt = rlz::api::pay::prepare(&[recipient], options, &coin) + let pczt = rlz::api::pay::prepare(&[pay_recipient], options, &sender) .await .expect("plan O2O transfer"); assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); println!(" spends: {:?}", pczt.n_spends); - let signed = sign_transaction(&pczt, &coin).await.expect("sign"); + let signed = sign_transaction(&pczt, &sender).await.expect("sign"); std::fs::write("/tmp/zsa_postsigned.pczt", &signed.pczt).expect("save postsigned pczt"); let tx_bytes = extract_transaction(&signed).await.expect("extract"); std::fs::write("/tmp/zsa_tx.bin", &tx_bytes).expect("save tx bytes"); println!("Transfer tx: {} bytes (saved /tmp/zsa_tx.bin)", tx_bytes.len()); // -- 11. Broadcast the transfer -- - let height = get_current_height(&coin).await.expect("get current height"); - let txid = broadcast_transaction(height, &tx_bytes, &coin) + let height = get_current_height(&sender).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &sender) .await .expect("broadcast transfer"); println!("Transfer broadcast: {txid}"); // -- 12. Wait for at least 1 block to be mined -- println!("Waiting for mining..."); - let start_height = get_current_height(&coin).await.expect("get current height"); + let start_height = get_current_height(&sender).await.expect("get current height"); let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let current = get_current_height(&coin).await.expect("get current height"); + let current = get_current_height(&sender).await.expect("get current height"); attempts += 1; if current > start_height { println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); @@ -226,19 +231,18 @@ async fn test_orchard_transfer() { } } - let height = get_current_height(&coin).await.expect("get current height"); + let height = get_current_height(&sender).await.expect("get current height"); synchronize_impl( - (), vec![account_id, recipient_account_id], height, 10000, 100, 10000, false, &coin, + (), vec![sender_id, recipient_id], height, 10000, 100, 10000, false, &coin, ).await.expect("re-sync after transfer"); // Verify sender balance decreased - let bal = rlz::api::sync::balance(&coin).await.expect("sender balance"); + let bal = rlz::api::sync::balance(&sender).await.expect("sender balance"); println!("Sender ZEC balance after transfer: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); assert!(bal.0[2] < orchard_bal, "sender Orchard balance should have decreased"); // Switch to recipient and verify receipt - let coin = coin.set_account(recipient_account_id).await.expect("switch to recipient"); - let recv_bal = rlz::api::sync::balance(&coin).await.expect("recipient balance"); + let recv_bal = rlz::api::sync::balance(&recipient).await.expect("recipient balance"); println!("Recipient ZEC balance: T={} S={} O={} IW={}", recv_bal.0[0], recv_bal.0[1], recv_bal.0[2], recv_bal.0[3]); assert!(recv_bal.0[2] >= send_amount, "recipient should have received the ZEC"); From acc746e9eb371917cdad8e103a70451453577f40 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 16:58:26 +0200 Subject: [PATCH 008/189] =?UTF-8?q?test:=20add=20test=5Fzsa=5Fissuance=20?= =?UTF-8?q?=E2=80=94=20issue=201M=20ZSA=20units,=20finalize,=20verify=20in?= =?UTF-8?q?=20holdings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/tests/zsa_transfer_test.rs | 144 ++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index e7e479d1f..93a5b6983 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -250,3 +250,147 @@ async fn test_orchard_transfer() { let _ = std::fs::remove_file(&db_path); println!("Test passed."); } + +/// Sync a faucet account, then issue a new ZSA asset (1M units, finalized), +/// wait for a block, and verify it appears in holdings. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_zsa_issuance() { + let _ = rustls::crypto::ring::default_provider().install_default(); + + let _ = tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "rlz=debug,info".into()), + ) + .try_init(); + + // -- 1. Initialize Coin for ZSA regtest -- + let db_path = format!("/tmp/zsa_issuance_test_{}.db", std::process::id()); + let _ = std::fs::remove_file(&db_path); + + let coin = Coin::new(Some(3)) + .open_database(db_path.clone(), None) + .await + .expect("open ZSA database") + .set_lwd(0, "https://zsa.methyl.cc".to_string()) + .expect("set LWD URL"); + println!("Coin initialized: coin={} db={db_path}", coin.coin); + + // -- 2. Restore faucet account from seed -- + let na = NewAccount { + icon: None, + name: "zsa_issuer".to_string(), + restore: true, + key: SEED_PHRASE.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools: Some(ALL_POOLS), + use_internal: false, + internal: false, + ledger: false, + }; + let account_id = new_account(&na, &coin) + .await + .expect("restore faucet account from seed"); + let account = coin + .clone() + .set_account(account_id) + .await + .expect("set account"); + println!("Account restored: id={account_id}"); + + // -- 3. Sync from LWD server to current height -- + let height = get_current_height(&account).await.expect("get current height"); + println!("Current height: {height}"); + + synchronize_impl( + (), vec![account_id], height, 10000, 100, 10000, false, &account, + ).await.expect("sync"); + println!("Synced to height: {height}"); + + // -- 4. Issue a new ZSA asset: 1M units, finalized -- + let asset_name = format!("TEST{}", std::process::id()); + let issue_amount = 1_000_000u64; + println!("Issuing asset '{asset_name}' amount={issue_amount} finalized=true..."); + + let tx_bytes = rlz::api::issuance::issue_asset( + asset_name.clone(), + issue_amount, + true, // first_issuance + true, // finalize + None, // desc_hash (computed from name) + account_id, + &account, + ) + .await + .expect("issue asset"); + println!("Issuance tx: {} bytes", tx_bytes.len()); + + // -- 5. Broadcast the issuance -- + let height = get_current_height(&account).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &account) + .await + .expect("broadcast issuance"); + println!("Issuance broadcast: {txid}"); + + // -- 6. Wait for at least 1 block to be mined -- + println!("Waiting for mining..."); + let start_height = get_current_height(&account).await.expect("get current height"); + let mut attempts = 0; + loop { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + let current = get_current_height(&account).await.expect("get current height"); + attempts += 1; + if current > start_height { + println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + break; + } + if attempts % 5 == 0 { + println!("Still waiting for block after {attempts} attempts (height={current})"); + } + } + + // -- 7. Re-sync and verify the asset appears -- + let height = get_current_height(&account).await.expect("get current height"); + synchronize_impl( + (), vec![account_id], height, 10000, 100, 10000, false, &account, + ).await.expect("re-sync after issuance"); + println!("Re-synced to height: {height}"); + + let holdings = rlz::api::zsa::list_zsa_holdings(&account) + .await + .expect("list holdings after issuance"); + println!("ZSA holdings after issuance: {}", holdings.len()); + for h in &holdings { + println!( + " {}: balance={} base={}", + h.asset_name, + h.balance, + hex::encode(&h.asset_base) + ); + } + assert!(!holdings.is_empty(), "should have the issued asset"); + + let zsa = holdings + .iter() + .find(|h| h.asset_name == asset_name) + .expect("issued asset not found by name"); + assert!( + zsa.balance >= issue_amount, + "balance should be at least issued amount" + ); + println!( + "Found asset: name={} balance={} base={}", + zsa.asset_name, + zsa.balance, + hex::encode(&zsa.asset_base) + ); + + // Clean up + let _ = std::fs::remove_file(&db_path); + println!("Test passed."); +} From 451470494df5c6f2940c48bac84f56d715fe06f4 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 17:24:12 +0200 Subject: [PATCH 009/189] chore: replace path overrides with git revs for ZSA deps - orchard: zcash-shielded-assets/orchard @ 7ba8e8a - lrz crates: zcash-shielded-assets/librustzcash @ f90335ab --- Cargo.lock | 40 +++++++++++++++++++++++++-------------- Cargo.toml | 23 +++++++++++----------- rust/src/graphql-cli.rs | 1 - rust/src/ledger/legacy.rs | 1 - rust/src/pay/plan.rs | 7 +------ 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db899b1b8..1cf6cf6be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -624,14 +624,14 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "auto_enums" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e4487600931c9a89f8db7ffbdf3fbdd45bb7bd85e26861f659a463cd0dff966" +checksum = "3091d68264354f211516b91dce6f71046e444fab1867716035f736667243affb" dependencies = [ "derive_utils", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -1105,9 +1105,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "jobserver", @@ -1899,13 +1899,13 @@ dependencies = [ [[package]] name = "derive_utils" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "362f47930db19fe7735f527e6595e4900316b893ebf6d48ad3d31be928d57dd6" +checksum = "dc05a5d33db20c784f873e84934ad94bb209a090987ac5f62fede2c178234f23" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -2065,9 +2065,9 @@ dependencies = [ [[package]] name = "either" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" dependencies = [ "serde", ] @@ -2173,6 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "corez", @@ -2235,6 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", ] @@ -4710,6 +4712,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=7ba8e8af31f25ce39b4c4e4ef2eb247028c60974#7ba8e8af31f25ce39b4c4e4ef2eb247028c60974" dependencies = [ "aes", "bitvec", @@ -4860,9 +4863,9 @@ dependencies = [ [[package]] name = "pasta_curves" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +checksum = "3437083215c505e867eea5478371feba43d7689d6d15ec0a209eb46fb0d4cda6" dependencies = [ "blake2b_simd", "ff", @@ -4892,6 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "bls12_381", @@ -6315,9 +6319,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "web-time", "zeroize", @@ -9827,6 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bech32 0.11.1", "bs58", @@ -9839,6 +9844,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "corez", "hex", @@ -9848,6 +9854,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bech32 0.11.1", "bip32", @@ -9887,6 +9894,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9916,6 +9924,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bellman", "blake2b_simd", @@ -9937,6 +9946,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "corez", "document-features", @@ -9973,6 +9983,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bip32", "bs58", @@ -10121,6 +10132,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index b3128cb0b..6757af222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,21 +6,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -#orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7bc6c6f3b48ace8db768f3145f86ffb1593b83e0" } -orchard = { path = "/Users/hanh/projects/zsa/orchard" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7ba8e8af31f25ce39b4c4e4ef2eb247028c60974" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } -# -- lrz ZSA branch (rev f53afe2a) -- -pczt = { path = "/Users/hanh/projects/zsa/lrz/pczt" } -zcash_address = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_address" } -zcash_encoding = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_encoding" } -zcash_keys = { path = "/Users/hanh/projects/zsa/lrz/zcash_keys" } -zcash_primitives = { path = "/Users/hanh/projects/zsa/lrz/zcash_primitives" } -zcash_proofs = { path = "/Users/hanh/projects/zsa/lrz/zcash_proofs" } -zcash_protocol = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_protocol" } -zcash_transparent = { path = "/Users/hanh/projects/zsa/lrz/zcash_transparent" } -zip321 = { path = "/Users/hanh/projects/zsa/lrz/components/zip321" } +# -- lrz ZSA branch (rev ac0f62d3) -- +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/rust/src/graphql-cli.rs b/rust/src/graphql-cli.rs index 658a62703..d7e8c379c 100644 --- a/rust/src/graphql-cli.rs +++ b/rust/src/graphql-cli.rs @@ -99,7 +99,6 @@ async fn main() -> Result<()> { eprintln!("Sapling: {}", tx.sapling_bundle().is_some()); let oa = tx.orchard_bundle().map(|b| match b { OrchardBundle::OrchardVanilla(b) => b.actions().len(), - #[cfg(feature = "zsa")] OrchardBundle::OrchardZSA(b) => b.actions().len(), }).unwrap_or(0); let iw = tx.ironwood_bundle().map(|b| (b.actions().iter().count(), b.flags().clone())); diff --git a/rust/src/ledger/legacy.rs b/rust/src/ledger/legacy.rs index 0aebe642f..b60affede 100644 --- a/rust/src/ledger/legacy.rs +++ b/rust/src/ledger/legacy.rs @@ -189,7 +189,6 @@ pub fn get_trusted_input(tx: &Transaction, index: u32) -> Result>> { .orchard_bundle() .map(|b| match b { OrchardBundle::OrchardVanilla(b) => b.actions().len(), - #[cfg(feature = "zsa")] OrchardBundle::OrchardZSA(b) => b.actions().len(), }) .unwrap_or_default(); diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 02bb6318e..4b4340bd3 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1019,7 +1019,7 @@ fn encode_memo(recipient: &Recipient) -> Result> { pub async fn sign_transaction( connection: &mut SqliteConnection, account: u32, - network: &crate::api::coin::Network, + _network: &crate::api::coin::Network, pczt: &PcztPackage, ) -> Result { let span = span!(Level::INFO, "transaction"); @@ -1037,11 +1037,6 @@ pub async fn sign_transaction( } = pczt; let pczt = Pczt::parse(pczt).unwrap(); - let ironwood_active = network.is_nu_active( - NetworkUpgrade::Nu6_3, - BlockHeight::from_u32(*pczt.global().expiry_height()), - ); - let dindex = get_account_dindex(connection, account).await?; let tkeys = select_account_transparent(connection, account, dindex).await?; let tsk = tkeys.xsk; From 28e2fca8c17264450d33ccfdc16f149fdf866826 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 18:12:53 +0200 Subject: [PATCH 010/189] =?UTF-8?q?test:=20add=20test=5Fzsa=5Ftransfer=20?= =?UTF-8?q?=E2=80=94=20issue=20ZSA,=20then=20transfer=20to=20recipient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/tests/zsa_transfer_test.rs | 269 ++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 93a5b6983..3b8b780c3 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -394,3 +394,272 @@ async fn test_zsa_issuance() { let _ = std::fs::remove_file(&db_path); println!("Test passed."); } + +/// Issue a ZSA asset, then transfer half of it to a recipient account. +/// Verifies the recipient received the ZSA tokens. +#[tokio::test] +#[ignore = "requires live connection to zsa.methyl.cc"] +async fn test_zsa_transfer() { + let _ = rustls::crypto::ring::default_provider().install_default(); + + let _ = tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "rlz=debug,info".into()), + ) + .try_init(); + + // -- 1. Initialize Coin for ZSA regtest -- + let db_path = format!("/tmp/zsa_transfer_test_{}.db", std::process::id()); + let _ = std::fs::remove_file(&db_path); + + let coin = Coin::new(Some(3)) + .open_database(db_path.clone(), None) + .await + .expect("open ZSA database") + .set_lwd(0, "https://zsa.methyl.cc".to_string()) + .expect("set LWD URL"); + println!("Coin initialized: coin={} db={db_path}", coin.coin); + + // -- 2. Restore faucet (sender) account from seed -- + let na = NewAccount { + icon: None, + name: "zsa_sender".to_string(), + restore: true, + key: SEED_PHRASE.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools: Some(ALL_POOLS), + use_internal: false, + internal: false, + ledger: false, + }; + let sender_id = new_account(&na, &coin) + .await + .expect("restore sender account from seed"); + let sender = coin + .clone() + .set_account(sender_id) + .await + .expect("set sender account"); + println!("Sender account restored: id={sender_id}"); + + // -- 3. Sync sender from LWD server -- + let height = get_current_height(&sender).await.expect("get current height"); + println!("Current height: {height}"); + + synchronize_impl( + (), vec![sender_id], height, 10000, 100, 10000, false, &sender, + ).await.expect("sync sender"); + println!("Sender synced to height: {height}"); + + // -- 4. Issue a new ZSA asset: 1M units, finalized -- + let asset_name = format!("TRANSFER{}", std::process::id()); + let issue_amount = 1_000_000u64; + println!("Issuing asset '{asset_name}' amount={issue_amount} finalized=true..."); + + let tx_bytes = rlz::api::issuance::issue_asset( + asset_name.clone(), + issue_amount, + true, // first_issuance + true, // finalize + None, + sender_id, + &sender, + ) + .await + .expect("issue asset"); + println!("Issuance tx: {} bytes", tx_bytes.len()); + + // -- 5. Broadcast issuance -- + let height = get_current_height(&sender).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &sender) + .await + .expect("broadcast issuance"); + println!("Issuance broadcast: {txid}"); + + // -- 6. Wait for a block -- + println!("Waiting for mining..."); + let start_height = get_current_height(&sender).await.expect("get current height"); + let mut attempts = 0; + loop { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + let current = get_current_height(&sender).await.expect("get current height"); + attempts += 1; + if current > start_height { + println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + break; + } + if attempts % 5 == 0 { + println!("Still waiting for block after {attempts} attempts (height={current})"); + } + } + + // -- 7. Re-sync and verify the asset -- + let height = get_current_height(&sender).await.expect("get current height"); + synchronize_impl( + (), vec![sender_id], height, 10000, 100, 10000, false, &sender, + ).await.expect("re-sync after issuance"); + println!("Re-synced to height: {height}"); + + let holdings = rlz::api::zsa::list_zsa_holdings(&sender) + .await + .expect("list sender holdings"); + assert!(!holdings.is_empty(), "should have the issued asset"); + let zsa = holdings + .iter() + .find(|h| h.asset_name == asset_name) + .expect("issued asset not found"); + assert!(zsa.balance >= issue_amount, "balance should be at least issued amount"); + let zsa_balance = zsa.balance; + let zsa_base = zsa.asset_base.clone(); + println!( + "Sender ZSA: name={} balance={} base={}", + asset_name, zsa_balance, hex::encode(&zsa_base) + ); + + // -- 8. Restore recipient account -- + let na2 = NewAccount { + icon: None, + name: "zsa_transfer_recipient".to_string(), + restore: true, + key: RECIPIENT_SEED.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools: Some(ALL_POOLS), + use_internal: false, + internal: false, + ledger: false, + }; + let recipient_id = new_account(&na2, &coin).await.expect("restore recipient"); + let recipient = coin + .clone() + .set_account(recipient_id) + .await + .expect("set recipient account"); + println!("Recipient account restored: id={recipient_id}"); + + // Sync recipient (just needs the UA) + let height = get_current_height(&recipient).await.expect("get current height"); + synchronize_impl( + (), vec![recipient_id], height, 10000, 100, 10000, false, &recipient, + ).await.expect("sync recipient"); + println!("Recipient synced"); + + // Get recipient's UA for the transfer + let recipient_addresses = get_addresses(ALL_POOLS, &recipient).await.expect("get recipient addresses"); + let recipient_ua = recipient_addresses.ua.expect("recipient UA"); + println!("Recipient UA: {recipient_ua}"); + + // -- 9. Transfer half the ZSA balance to recipient -- + let send_amount = zsa_balance / 2; + println!("Transferring {send_amount} of asset '{asset_name}' to recipient..."); + + let pay_recipient = Recipient { + address: recipient_ua, + amount: send_amount, + pools: None, + user_memo: Some("zsa transfer test".to_string()), + memo_bytes: None, + price: None, + asset_base: zsa_base.clone(), + asset_name: None, + }; + + let options = PaymentOptions { + src_pools: ALL_POOLS, + recipient_pays_fee: false, + smart_transparent: false, + category: None, + mode: 0, + }; + + let pczt = rlz::api::pay::prepare(&[pay_recipient], options, &sender) + .await + .expect("plan ZSA transfer"); + assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); + println!(" spends: {:?}", pczt.n_spends); + + let signed = sign_transaction(&pczt, &sender).await.expect("sign"); + let tx_bytes = extract_transaction(&signed).await.expect("extract"); + println!("ZSA transfer tx: {} bytes", tx_bytes.len()); + + // -- 10. Broadcast the ZSA transfer -- + let height = get_current_height(&sender).await.expect("get current height"); + let txid = broadcast_transaction(height, &tx_bytes, &sender) + .await + .expect("broadcast ZSA transfer"); + println!("ZSA transfer broadcast: {txid}"); + + // -- 11. Wait for a block -- + println!("Waiting for mining..."); + let start_height = get_current_height(&sender).await.expect("get current height"); + let mut attempts = 0; + loop { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + let current = get_current_height(&sender).await.expect("get current height"); + attempts += 1; + if current > start_height { + println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + break; + } + if attempts % 5 == 0 { + println!("Still waiting for block after {attempts} attempts (height={current})"); + } + } + + // -- 12. Re-sync both accounts -- + let height = get_current_height(&sender).await.expect("get current height"); + synchronize_impl( + (), vec![sender_id, recipient_id], height, 10000, 100, 10000, false, &sender, + ).await.expect("re-sync after transfer"); + println!("Synced to height: {height}"); + + // -- 13. Verify sender ZSA balance decreased -- + let sender_holdings = rlz::api::zsa::list_zsa_holdings(&sender) + .await + .expect("list sender holdings"); + let sender_zsa = sender_holdings + .iter() + .find(|h| h.asset_name == asset_name) + .expect("sender should still have the asset"); + println!("Sender ZSA after transfer: balance={}", sender_zsa.balance); + assert!( + sender_zsa.balance <= zsa_balance - send_amount, + "sender ZSA balance should have decreased by at least send_amount" + ); + + // -- 14. Verify recipient received the ZSA -- + let recv_holdings = rlz::api::zsa::list_zsa_holdings(&recipient) + .await + .expect("list recipient holdings"); + println!("Recipient ZSA holdings: {}", recv_holdings.len()); + for h in &recv_holdings { + println!( + " {}: balance={} base={}", + h.asset_name, h.balance, hex::encode(&h.asset_base) + ); + } + let recv_zsa = recv_holdings + .iter() + .find(|h| h.asset_base == zsa_base) + .expect("recipient should have the ZSA asset"); + assert!( + recv_zsa.balance >= send_amount, + "recipient should have received at least send_amount ZSA" + ); + println!( + "Recipient ZSA: balance={} (expected >= {send_amount})", + recv_zsa.balance + ); + + // Clean up + let _ = std::fs::remove_file(&db_path); + println!("Test passed."); +} From 7af5c163346d9a0ee3fbbdb559f940353ac8ae90 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 18:21:54 +0200 Subject: [PATCH 011/189] test: wait for 5 blocks after issuance in test_zsa_transfer --- rust/tests/zsa_transfer_test.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 3b8b780c3..6d7a039a3 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -481,20 +481,21 @@ async fn test_zsa_transfer() { .expect("broadcast issuance"); println!("Issuance broadcast: {txid}"); - // -- 6. Wait for a block -- - println!("Waiting for mining..."); + // -- 6. Wait for 5 blocks so issuance is well-confirmed -- + println!("Waiting for 5 blocks..."); let start_height = get_current_height(&sender).await.expect("get current height"); + let target = start_height + 5; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; let current = get_current_height(&sender).await.expect("get current height"); attempts += 1; - if current > start_height { - println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + if current >= target { + println!("Reached height {current} >= {target} (after {attempts} attempts)"); break; } if attempts % 5 == 0 { - println!("Still waiting for block after {attempts} attempts (height={current})"); + println!("Still waiting at height {current}/{target} (attempts {attempts})"); } } From 2aebcf5a85dfd826dd632c16776bf4088b892d43 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 18:48:33 +0200 Subject: [PATCH 012/189] feat: log per-pool spend/output counts before build_for_pczt --- rust/src/pay/plan.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 4b4340bd3..dde10e8d3 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -898,6 +898,12 @@ pub async fn plan_transaction( builder.set_zsa_builder(zsa); } + info!( + "Building: n_spends T={} S={} O={} IW={}, n_outputs T={} S={} O={} IW={}", + n_spends[0], n_spends[1], n_spends[2], n_spends[3], + n_outputs[0], n_outputs[1], n_outputs[2], n_outputs[3], + ); + let r = builder.build_for_pczt(OsRng, &FeeRule::standard(), |_asset: &AssetBase| false)?; let sapling_meta = &r.sapling_meta; let orchard_meta = &r.orchard_meta; From e959af706ef7d16e300c8c9dfe84bbce2bcfc06c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 19:07:48 +0200 Subject: [PATCH 013/189] chore: bump lrz rev for fee debug logging, add per-pool counts to plan --- Cargo.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6757af222..62c222da7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,15 +11,15 @@ sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf2 zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } # -- lrz ZSA branch (rev ac0f62d3) -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f90335ab8a4e5182ab451682b6e2653befc15331" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } From 3391069ef60ea77b5bb50a798783395b9b426e21 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 25 Jul 2026 19:09:34 +0200 Subject: [PATCH 014/189] test: wait for 3 blocks instead of 5 after issuance --- rust/tests/zsa_transfer_test.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 6d7a039a3..ac5d100d4 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -481,10 +481,10 @@ async fn test_zsa_transfer() { .expect("broadcast issuance"); println!("Issuance broadcast: {txid}"); - // -- 6. Wait for 5 blocks so issuance is well-confirmed -- - println!("Waiting for 5 blocks..."); + // -- 6. Wait for 3 blocks so issuance is well-confirmed -- + println!("Waiting for 3 blocks..."); let start_height = get_current_height(&sender).await.expect("get current height"); - let target = start_height + 5; + let target = start_height + 3; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; From e1b886859d231404bea910beeeea97ff5c3e76ad Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 07:37:55 +0200 Subject: [PATCH 015/189] feat: PCZT-DUMP with enc_ciphertext length, per-pool counts, block-wait loops in tests --- .cargo/config.toml | 2 + .claude/settings.json | 15 ++++ .claude/worktrees/github-main | 1 + .claude/worktrees/zkool-v6.22.0 | 1 + Cargo.lock | 12 --- Cargo.toml | 22 ++--- rust/src/api/issuance.rs | 3 +- rust/src/pay/plan.rs | 63 ++++++++++---- rust/src/pay/solve.rs | 112 +++++++++++++++++++++---- rust/src/warp/decrypter.rs | 67 ++------------- rust/src/warp/sync/shielded/orchard.rs | 2 +- rust/tests/zsa_transfer_test.rs | 19 +++-- 12 files changed, 193 insertions(+), 126 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 .claude/settings.json create mode 160000 .claude/worktrees/github-main create mode 160000 .claude/worktrees/zkool-v6.22.0 diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..c91c3f38b --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[net] +git-fetch-with-cli = true diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..2e94f0f9f --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,15 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "jq -r '.tool_input.command' | { read -r cmd; case \"$cmd\" in *\"git commit\"*|*\"git push\"*) echo '{\"continue\":false,\"stopReason\":\"git commit/push requires explicit user instruction — use \\\"commit\\\" or \\\"push\\\" to proceed\"}';; *) echo '{\"continue\":true}'; esac; }" + } + ] + } + ] + } +} diff --git a/.claude/worktrees/github-main b/.claude/worktrees/github-main new file mode 160000 index 000000000..e99fd7d38 --- /dev/null +++ b/.claude/worktrees/github-main @@ -0,0 +1 @@ +Subproject commit e99fd7d38427c1883a62225542ea5415597f3f6c diff --git a/.claude/worktrees/zkool-v6.22.0 b/.claude/worktrees/zkool-v6.22.0 new file mode 160000 index 000000000..70dd4445a --- /dev/null +++ b/.claude/worktrees/zkool-v6.22.0 @@ -0,0 +1 @@ +Subproject commit 70dd4445a912e19f2269c167acb5d2e9dbc51382 diff --git a/Cargo.lock b/Cargo.lock index 1cf6cf6be..6f7d9c909 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,6 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2235,6 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", ] @@ -4712,7 +4710,6 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=7ba8e8af31f25ce39b4c4e4ef2eb247028c60974#7ba8e8af31f25ce39b4c4e4ef2eb247028c60974" dependencies = [ "aes", "bitvec", @@ -4895,7 +4892,6 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "bls12_381", @@ -9831,7 +9827,6 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bech32 0.11.1", "bs58", @@ -9844,7 +9839,6 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "corez", "hex", @@ -9854,7 +9848,6 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bech32 0.11.1", "bip32", @@ -9894,7 +9887,6 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9924,7 +9916,6 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bellman", "blake2b_simd", @@ -9946,7 +9937,6 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "corez", "document-features", @@ -9983,7 +9973,6 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "bip32", "bs58", @@ -10132,7 +10121,6 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f90335ab8a4e5182ab451682b6e2653befc15331#f90335ab8a4e5182ab451682b6e2653befc15331" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 62c222da7..54847e921 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,20 +6,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "7ba8e8af31f25ce39b4c4e4ef2eb247028c60974" } +orchard = { path = "/Users/hanh/projects/zsa/orchard" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } -# -- lrz ZSA branch (rev ac0f62d3) -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "e195a4174b19bd147b17b9bd5878fed364f57db3" } +# -- lrz ZSA branch -- +pczt = { path = "/Users/hanh/projects/zsa/lrz/pczt" } +zcash_address = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_address" } +zcash_encoding = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_encoding" } +zcash_keys = { path = "/Users/hanh/projects/zsa/lrz/zcash_keys" } +zcash_primitives = { path = "/Users/hanh/projects/zsa/lrz/zcash_primitives" } +zcash_proofs = { path = "/Users/hanh/projects/zsa/lrz/zcash_proofs" } +zcash_protocol = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_protocol" } +zcash_transparent = { path = "/Users/hanh/projects/zsa/lrz/zcash_transparent" } +zip321 = { path = "/Users/hanh/projects/zsa/lrz/components/zip321" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/rust/src/api/issuance.rs b/rust/src/api/issuance.rs index 549c47e6c..d84fbcc08 100644 --- a/rust/src/api/issuance.rs +++ b/rust/src/api/issuance.rs @@ -139,6 +139,7 @@ pub async fn issue_asset( // ── 8. Pre-insert asset into DB for sync name resolution ───────────── // Only needed for first issuance; reissuance already has the asset row. if !is_reissuance { + let first_seen_height = client.latest_height().await?; sqlx::query( "INSERT OR IGNORE INTO assets(asset_desc_hash, ik, asset_base, asset_name, finalized, first_seen_height) VALUES (?1, ?2, ?3, ?4, ?5, ?6)", @@ -148,7 +149,7 @@ pub async fn issue_asset( .bind(&asset_base_bytes) .bind(&asset_name) .bind(finalize) - .bind(0_i64) + .bind(first_seen_height) .execute(&mut *connection) .await?; } diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index dde10e8d3..3c4a93199 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -35,7 +35,7 @@ use zcash_primitives::transaction::{ }; use zcash_proofs::prover::LocalTxProver; use zcash_protocol::{ - consensus::{BlockHeight, NetworkType, NetworkUpgrade, Parameters}, + consensus::{BlockHeight, BranchId, NetworkType, NetworkUpgrade, Parameters}, memo::{Memo, MemoBytes}, value::Zatoshis, }; @@ -256,6 +256,12 @@ pub async fn plan_transaction( let ironwood_active = network .is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height)); + let orchard_note_version = + if BranchId::for_height(network, BlockHeight::from_u32(height)) == BranchId::Nu7 { + orchard::NoteVersion::V3ZSA + } else { + orchard::NoteVersion::V2 + }; let decomposed: Vec = recipients .iter() .map(|r| { @@ -362,9 +368,27 @@ pub async fn plan_transaction( .enumerate() .flat_map(|(pool, notes)| { let zi = zi.clone(); - notes.iter().enumerate().map(move |(idx, n)| { - let asset_index = resolve_asset_index(&n.asset_base, zec_key, &zi); - solve::Note { pool: pool as u8, amount: n.amount, pool_index: idx, asset_index } + notes.iter().enumerate().filter_map(move |(idx, n)| { + // Classify by the note's real asset: ZEC → 0, a recipient ZSA + // asset → its solver index. A ZSA note whose asset is NOT one of + // the recipient assets can't fund this payment (it isn't ZEC and + // has no matching output), so drop it from the candidate set. + // Mapping it to index 0 (the old `unwrap_or(0)` behaviour) let the + // solver treat it as spendable ZEC: it would then "pay" the fee + // with phantom ZEC while the builder spent the note as its real + // asset, leaving that asset over-spent and the ZEC change unbacked + // (Orchard IO-finalize → ValueCommitMismatch). + let asset_bytes: [u8; 32] = + n.asset_base.clone().try_into().unwrap_or(zec_key); + let asset_index = if asset_bytes == zec_key { + 0 + } else { + match zi.get(&asset_bytes) { + Some(&i) => i, + None => return None, + } + }; + Some(solve::Note { pool: pool as u8, amount: n.amount, pool_index: idx, asset_index }) }) }) .collect(); @@ -698,7 +722,7 @@ pub async fn plan_transaction( ovk.as_ref().unwrap(), &eo, &ero, - orchard::NoteVersion::V2, + orchard_note_version, ) .await?; @@ -906,7 +930,6 @@ pub async fn plan_transaction( let r = builder.build_for_pczt(OsRng, &FeeRule::standard(), |_asset: &AssetBase| false)?; let sapling_meta = &r.sapling_meta; - let orchard_meta = &r.orchard_meta; let ironwood_meta = &r.ironwood_meta; let pczt = Creator::build_from_parts(r.pczt_parts).unwrap(); @@ -980,20 +1003,26 @@ pub async fn plan_transaction( pczt }; - let n_orchard_actions = pczt.orchard().actions().len(); + let orchard_indices = pczt + .orchard() + .actions() + .iter() + .enumerate() + .filter_map(|(index, action)| { + action + .spend() + .spend_auth_sig() + .is_none() + .then_some(index) + }) + .collect(); let pczt_package = PcztPackage { pczt: pczt.serialize().unwrap(), n_spends: [n_spends[0], n_spends[1], n_spends[2], n_spends[3]], sapling_indices: (0..n_spends[1]) .map(|n| sapling_meta.spend_index(n).unwrap()) .collect(), - orchard_indices: if ironwood_active { - (0..n_orchard_actions).collect() - } else { - (0..n_spends[2]) - .map(|n| orchard_meta.spend_action_index(n).unwrap()) - .collect() - }, + orchard_indices, ironwood_indices: (0..n_spends[3]) .map(|n| ironwood_meta.spend_action_index(n).unwrap()) .collect(), @@ -1178,7 +1207,11 @@ pub async fn sign_transaction( let Some(osak) = osak.as_ref() else { return Err(Error::NoSigningKey.into()); }; - signer.sign_orchard(*bundle_index, osak).unwrap(); + signer.sign_orchard(*bundle_index, osak).map_err(|e| { + anyhow!( + "failed to sign Orchard action {bundle_index} (selected spend {index}): {e:?}" + ) + })?; } for (index, bundle_index) in ironwood_indices.iter().enumerate() { info!("signing ironwood {index}"); diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 03f78616b..80c377b1b 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -149,10 +149,18 @@ impl BudgetTracker { // --------------------------------------------------------------------- /// ZIP-317 fee for a state, assuming change is assigned to `change_pool`. -fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_pool: u8, f_unit: u64, migration: bool) -> u64 { +/// +/// `zsa_change` is the number of *additional* Orchard change outputs the +/// transaction will carry — one per non-ZEC asset whose selected inputs +/// exceed what its recipients consume. These are distinct Orchard actions +/// (ZSA notes aren't fungible with ZEC or each other), so they must be +/// priced in or the planner underestimates the fee and the builder rejects +/// the transaction for insufficient funds. See `zsa_change_outputs`. +fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_pool: u8, f_unit: u64, migration: bool, zsa_change: u32) -> u64 { let cp = change_pool as usize; let mut n_outs = *n_outputs; - n_outs[cp] = n_outs[cp].saturating_add(1); // change output + n_outs[cp] = n_outs[cp].saturating_add(1); // ZEC change output + n_outs[2] = n_outs[2].saturating_add(zsa_change); // ZSA change outputs (always Orchard) // Transparent: max(inputs, outputs), no padding let t = n_inputs[0].max(n_outs[0]) as u64; @@ -183,25 +191,44 @@ fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_poo /// Minimum possible fee for a state (no change output added yet). /// Used as the lower-bound estimate — since adding change can only add /// an output (monotonic), the actual final fee is >= this. -fn compute_min_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], f_unit: u64, migration: bool) -> u64 { - let t = n_inputs[0].max(n_outputs[0]) as u64; - let s: u64 = if n_inputs[1] > 0 || n_outputs[1] > 0 { - n_inputs[1].max(n_outputs[1]).max(2) as u64 +fn compute_min_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], f_unit: u64, migration: bool, zsa_change: u32) -> u64 { + // ZSA change notes are already committed once their asset is over-selected, + // so they belong in even the no-ZEC-change lower bound (monotonic: adding + // notes can only keep an asset over-selected, never reverse it). + let mut n_outs = *n_outputs; + n_outs[2] = n_outs[2].saturating_add(zsa_change); + let t = n_inputs[0].max(n_outs[0]) as u64; + let s: u64 = if n_inputs[1] > 0 || n_outs[1] > 0 { + n_inputs[1].max(n_outs[1]).max(2) as u64 } else { 0 }; - let o: u64 = if n_inputs[2] > 0 || n_outputs[2] > 0 { + let o: u64 = if n_inputs[2] > 0 || n_outs[2] > 0 { if migration { - (n_inputs[2] as u64 + n_outputs[2] as u64).max(2) + (n_inputs[2] as u64 + n_outs[2] as u64).max(2) } else { - n_inputs[2].max(n_outputs[2]).max(2) as u64 + n_inputs[2].max(n_outs[2]).max(2) as u64 } } else { 0 }; - let iw: u64 = if n_inputs[3] > 0 || n_outputs[3] > 0 { - n_inputs[3].max(n_outputs[3]).max(2) as u64 + let iw: u64 = if n_inputs[3] > 0 || n_outs[3] > 0 { + n_inputs[3].max(n_outs[3]).max(2) as u64 } else { 0 }; let logical = (t + s + o + iw).max(GRACE_ACTIONS); logical * f_unit } +/// Number of extra Orchard change outputs a ZSA transfer requires: one per +/// non-ZEC asset (index ≥ 1) whose selected input sum exceeds the amount its +/// recipient outputs consume. Each is a separate Orchard action the builder +/// emits, because ZSA notes aren't fungible with ZEC or with each other, so +/// the leftover of every asset needs its own change note. The fee model must +/// count these or it underprices the transaction (the builder computes its +/// fee from `max(orchard_spends, orchard_outputs)` including every change +/// note, so a missed change output = one unpriced 5000-zat action). +fn zsa_change_outputs(state: &State, ctx: &Context) -> u32 { + (1..ctx.n_assets as usize) + .filter(|&a| state.asset_sums[a] > ctx.asset_output_amounts[a]) + .count() as u32 +} + // --------------------------------------------------------------------- // Cost evaluation — folds change-pool assignment into the search // --------------------------------------------------------------------- @@ -251,9 +278,10 @@ fn is_feasible(state: &State, ctx: &Context, fee: u64) -> bool { fn evaluate_fee(state: &State, ctx: &Context) -> (u64, u8) { let mut best_fee = u64::MAX; let mut best_pool = 0u8; + let zsa_change = zsa_change_outputs(state, ctx); for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration); + let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { info!( @@ -283,9 +311,10 @@ fn evaluate_fee(state: &State, ctx: &Context) -> (u64, u8) { fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { let mut best_turnstile = u64::MAX; let mut best_pool = 0u8; + let zsa_change = zsa_change_outputs(state, ctx); for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration); + let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { continue; @@ -340,8 +369,9 @@ fn lower_bound(state: &State, ctx: &Context) -> u64 { /// added, the current minimum fee is always a valid bound. fn lower_bound_fee(state: &State, ctx: &Context) -> u64 { let mut min_fee = u64::MAX; + let zsa_change = zsa_change_outputs(state, ctx); for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration); + let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { continue; } @@ -358,8 +388,8 @@ fn lower_bound_fee(state: &State, ctx: &Context) -> u64 { min_fee = fee; } } - // Also try compute_min_fee (no change output) as a tighter bound - let min_no_change = compute_min_fee(&state.n_inputs, &ctx.n_outputs, ctx.f_unit, ctx.migration); + // Also try compute_min_fee (no ZEC change output) as a tighter bound + let min_no_change = compute_min_fee(&state.n_inputs, &ctx.n_outputs, ctx.f_unit, ctx.migration, zsa_change); if min_no_change < min_fee { min_fee = min_no_change; } @@ -784,6 +814,7 @@ pub(super) fn select_notes( best_pool, ctx.f_unit, ctx.migration, + zsa_change_outputs(&best_state, &ctx), ) }; @@ -954,11 +985,58 @@ mod tests { // Total logical = max(2+3,2) = 5, fee = 25000 let n_inputs: [u32; 4] = [0, 2, 1, 0]; let n_outputs: [u32; 4] = [0, 1, 2, 0]; - let fee = compute_fee(&n_inputs, &n_outputs, 2, 5_000, false); + let fee = compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 0); // With change in pool 2: n_outputs[2] becomes 3 // Sapling: max(2,1,2) = 2 // Orchard: max(1,3,2) = 3 // Total: max(5, 2) = 5, fee = 25000 assert_eq!(fee, 25_000); } + + #[test] + fn test_compute_fee_counts_zsa_change() { + // Reproduces the O2O ZSA transfer that under-priced by one action: + // spend 1 ZEC note + 1 asset note (2 Orchard inputs), send part of the + // asset to a recipient (1 Orchard output). The wallet then needs a ZEC + // change note *and* an asset change note (the asset was over-selected). + let n_inputs: [u32; 4] = [0, 0, 2, 0]; + let n_outputs: [u32; 4] = [0, 0, 1, 0]; // recipient only + // Without counting the ZSA change note the planner saw + // Orchard outputs = recipient(1) + ZEC change(1) = 2 → max(2,2)=2 → 10000 + assert_eq!(compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 0), 10_000); + // Counting the asset change note the builder actually emits + // Orchard outputs = recipient(1) + ZEC change(1) + asset change(1) = 3 + // → max(2,3)=3 → 15000, matching the builder and closing the 5000 gap. + assert_eq!(compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 1), 15_000); + } + + #[test] + fn test_zsa_change_outputs_counts_over_selected_assets() { + let ctx = Context { + notes: &[], + n_assets: 3, // ZEC + 2 ZSA assets + asset_output_amounts: vec![0, 500_000, 300_000], + output_amounts: [0; N_POOLS], + n_outputs: [0; N_POOLS], + f_unit: 5_000, + migration: false, + recipient_pays_fee: false, + first_recipient_amount: 0, + mode: Mode::Fee, + }; + let state = |sums: Vec| State { + asset_sums: sums, + balance: [0; N_POOLS], + n_inputs: [0; N_POOLS], + tin: 0, + tout: 0, + selected: vec![], + }; + // Asset 1 exactly funded, asset 2 over-selected → 1 change note. + assert_eq!(zsa_change_outputs(&state(vec![0, 500_000, 400_000]), &ctx), 1); + // Both assets over-selected → 2 change notes. + assert_eq!(zsa_change_outputs(&state(vec![0, 600_000, 400_000]), &ctx), 2); + // Both exactly funded → no ZSA change. + assert_eq!(zsa_change_outputs(&state(vec![0, 500_000, 300_000]), &ctx), 0); + } } diff --git a/rust/src/warp/decrypter.rs b/rust/src/warp/decrypter.rs index aa02d77c2..d609ea6a0 100644 --- a/rust/src/warp/decrypter.rs +++ b/rust/src/warp/decrypter.rs @@ -153,9 +153,8 @@ pub fn try_orchard_decrypt( let mut plaintext = ca.ciphertext.clone(); keystream.apply_keystream(&mut plaintext); - // ZSA notes use leadbyte 0x03, 84-byte plaintext. - // NU7 does not activate NoteVersion::V3 — commitments are V2. - // Parse with OrchardZSADomain to extract fields, then rebuild as V2. + // NU7 uses the asset-carrying V3ZSA note version for every Orchard + // note, including native ZEC. if plaintext[0] == 0x03 { use zcash_note_encryption::Domain; let pivk = orchard::keys::PreparedIncomingViewingKey::new(ivk); @@ -165,40 +164,12 @@ pub fn try_orchard_decrypt( let rho = Option::::from(Rho::from_bytes(&nullifier_bytes)) .ok_or_else(|| anyhow::anyhow!("Invalid Rho bytes"))?; - let is_zsa = true; - // Ciphertext may be >= 84 bytes (ZSA); take only the first 52 for CompactAction. - let note_ciphertext: [u8; 52] = ca.ciphertext[..52].try_into() - .map_err(|_| anyhow::anyhow!("ciphertext too short"))?; - let cmx_bytes: [u8; 32] = ca.cmx.clone() - .try_into() - .map_err(|_| anyhow::anyhow!("Invalid cmx length"))?; - let ephemeral_key_bytes: [u8; 32] = ca.ephemeral_key.clone() - .try_into() - .map_err(|_| anyhow::anyhow!("Invalid ephemeral key length"))?; - let cca = CompactAction::from_parts( - Option::::from(Nullifier::from_bytes(&rho.to_bytes())) - .ok_or_else(|| anyhow::anyhow!("Invalid nullifier"))?, - Option::::from( - ExtractedNoteCommitment::from_bytes(&cmx_bytes) - ).ok_or_else(|| anyhow::anyhow!("Invalid cmx"))?, - EphemeralKeyBytes(ephemeral_key_bytes), - note_ciphertext, - ); let note_plaintext = NoteBytesData::<84>::from_slice(&plaintext[..84]) .ok_or_else(|| anyhow::anyhow!("Invalid orchard note plaintext"))?; - // ZSA notes (lead byte 0x03) use OrchardZSADomain which parses V3 plaintext - // with the 32-byte asset field. Vanilla notes in 84-byte form use OrchardDomain. - let parsed = if is_zsa { - OrchardZSADomain { rho }.parse_note_plaintext_without_memo_ivk( - &pivk, - note_plaintext.as_ref(), - ) - } else { - OrchardDomain::for_compact_action(&cca).parse_note_plaintext_without_memo_ivk( - &pivk, - note_plaintext.as_ref(), - ) - }; + let parsed = OrchardZSADomain { rho }.parse_note_plaintext_without_memo_ivk( + &pivk, + note_plaintext.as_ref(), + ); tracing::debug!( "ZSA parsed result: height={} vout={} is_some={}", height, vout, parsed.is_some() @@ -206,31 +177,7 @@ pub fn try_orchard_decrypt( if let Some((note, recipient)) = parsed { let cmx = ExtractedNoteCommitment::from(note.commitment()); let value = note.value().inner(); - let matched = if cmx.to_bytes() == *ca.cmx { - true - } else if is_zsa { - // Legacy cmx: orchard 0.14.0 (and earlier zcashd) computed - // note commitments without the asset field. Try a V2 note - // with zatoshi asset to match older chains. - let legacy = orchard::note::Note::from_parts( - recipient, - orchard::value::NoteValue::from_raw(value), - orchard::note::AssetBase::zatoshi(), - rho, - *note.rseed(), - orchard::NoteVersion::V2, - ); - let legacy_result = Option::::from(legacy) - .map(|n| ExtractedNoteCommitment::from(n.commitment()).to_bytes() == *ca.cmx) - .unwrap_or(false); - tracing::debug!( - "ZSA legacy cmx: height={} vout={} matched={}", - height, vout, legacy_result - ); - legacy_result - } else { - false - }; + let matched = cmx.to_bytes() == *ca.cmx; if matched { let is_zec = bool::from(note.asset().is_zatoshi()); let asset_base = if is_zec { diff --git a/rust/src/warp/sync/shielded/orchard.rs b/rust/src/warp/sync/shielded/orchard.rs index 85200c376..3a77ce292 100644 --- a/rust/src/warp/sync/shielded/orchard.rs +++ b/rust/src/warp/sync/shielded/orchard.rs @@ -172,7 +172,7 @@ fn construct_issuance_note( } let rseed = rseed.unwrap(); - let note = Note::from_parts(addr, value, *asset_base, rho, rseed, NoteVersion::V2); + let note = Note::from_parts(addr, value, *asset_base, rho, rseed, NoteVersion::V3ZSA); if note.is_none().into() { anyhow::bail!("Invalid issuance note"); } diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index ac5d100d4..6198b209a 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -481,10 +481,10 @@ async fn test_zsa_transfer() { .expect("broadcast issuance"); println!("Issuance broadcast: {txid}"); - // -- 6. Wait for 3 blocks so issuance is well-confirmed -- - println!("Waiting for 3 blocks..."); + // -- 6. Wait for 2 blocks so issuance is well-confirmed -- + println!("Waiting for 2 blocks..."); let start_height = get_current_height(&sender).await.expect("get current height"); - let target = start_height + 3; + let target = start_height + 2; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; @@ -598,20 +598,21 @@ async fn test_zsa_transfer() { .expect("broadcast ZSA transfer"); println!("ZSA transfer broadcast: {txid}"); - // -- 11. Wait for a block -- - println!("Waiting for mining..."); + // -- 11. Wait for 2 blocks -- + println!("Waiting for 2 blocks..."); let start_height = get_current_height(&sender).await.expect("get current height"); + let target = start_height + 2; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; let current = get_current_height(&sender).await.expect("get current height"); attempts += 1; - if current > start_height { - println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); + if current >= target { + println!("Reached height {current} >= {target} (after {attempts} attempts)"); break; } if attempts % 5 == 0 { - println!("Still waiting for block after {attempts} attempts (height={current})"); + println!("Still waiting at height {current}/{target} (attempts {attempts})"); } } @@ -661,6 +662,6 @@ async fn test_zsa_transfer() { ); // Clean up - let _ = std::fs::remove_file(&db_path); + // let _ = std::fs::remove_file(&db_path); println!("Test passed."); } From 95c171b4aaa2c5573ac6779294caaac15cd348a8 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 07:43:40 +0200 Subject: [PATCH 016/189] chore: replace path overrides with git pinned revs for ZSA deps - orchard: zcash-shielded-assets/orchard @ 8c1c9bee - lrz: zcash-shielded-assets/librustzcash @ b2d59ba8 --- .claude/worktrees/github-main | 1 - .claude/worktrees/zkool-v6.22.0 | 1 - Cargo.lock | 12 ++++++++++++ Cargo.toml | 20 ++++++++++---------- 4 files changed, 22 insertions(+), 12 deletions(-) delete mode 160000 .claude/worktrees/github-main delete mode 160000 .claude/worktrees/zkool-v6.22.0 diff --git a/.claude/worktrees/github-main b/.claude/worktrees/github-main deleted file mode 160000 index e99fd7d38..000000000 --- a/.claude/worktrees/github-main +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e99fd7d38427c1883a62225542ea5415597f3f6c diff --git a/.claude/worktrees/zkool-v6.22.0 b/.claude/worktrees/zkool-v6.22.0 deleted file mode 160000 index 70dd4445a..000000000 --- a/.claude/worktrees/zkool-v6.22.0 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 70dd4445a912e19f2269c167acb5d2e9dbc51382 diff --git a/Cargo.lock b/Cargo.lock index 6f7d9c909..8fc94b5d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,6 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "blake2b_simd", "corez", @@ -2235,6 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "blake2b_simd", ] @@ -4710,6 +4712,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=8c1c9beeeeeefb56fa309f56062b82feb70bb1d4#8c1c9beeeeeefb56fa309f56062b82feb70bb1d4" dependencies = [ "aes", "bitvec", @@ -4892,6 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "blake2b_simd", "bls12_381", @@ -9827,6 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "bech32 0.11.1", "bs58", @@ -9839,6 +9844,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "corez", "hex", @@ -9848,6 +9854,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "bech32 0.11.1", "bip32", @@ -9887,6 +9894,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9916,6 +9924,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "bellman", "blake2b_simd", @@ -9937,6 +9946,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "corez", "document-features", @@ -9973,6 +9983,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "bip32", "bs58", @@ -10121,6 +10132,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 54847e921..a5f1a2a59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,20 +6,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { path = "/Users/hanh/projects/zsa/orchard" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "8c1c9beeeeeefb56fa309f56062b82feb70bb1d4" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } # -- lrz ZSA branch -- -pczt = { path = "/Users/hanh/projects/zsa/lrz/pczt" } -zcash_address = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_address" } -zcash_encoding = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_encoding" } -zcash_keys = { path = "/Users/hanh/projects/zsa/lrz/zcash_keys" } -zcash_primitives = { path = "/Users/hanh/projects/zsa/lrz/zcash_primitives" } -zcash_proofs = { path = "/Users/hanh/projects/zsa/lrz/zcash_proofs" } -zcash_protocol = { path = "/Users/hanh/projects/zsa/lrz/components/zcash_protocol" } -zcash_transparent = { path = "/Users/hanh/projects/zsa/lrz/zcash_transparent" } -zip321 = { path = "/Users/hanh/projects/zsa/lrz/components/zip321" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } From 850ad829e475ee2540a53737a47a462edbe123b1 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 12:51:01 +0200 Subject: [PATCH 017/189] fix: complete ZSA PCZT transaction support --- Cargo.lock | 24 +++---- Cargo.toml | 20 +++--- rust/src/api/coin.rs | 14 ++-- rust/src/pay/mod.rs | 112 +++++++++++++++++++++----------- rust/src/pay/plan.rs | 72 ++++++++++++++++++++ rust/tests/zsa_transfer_test.rs | 12 +++- 6 files changed, 185 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8fc94b5d7..9aa46093c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "blake2b_simd", ] @@ -4712,7 +4712,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=8c1c9beeeeeefb56fa309f56062b82feb70bb1d4#8c1c9beeeeeefb56fa309f56062b82feb70bb1d4" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=8ac8fcb9b766731e281791196d6608998b8d4a1d#8ac8fcb9b766731e281791196d6608998b8d4a1d" dependencies = [ "aes", "bitvec", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "blake2b_simd", "bls12_381", @@ -9831,7 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "bech32 0.11.1", "bs58", @@ -9844,7 +9844,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "corez", "hex", @@ -9854,7 +9854,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "bech32 0.11.1", "bip32", @@ -9894,7 +9894,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9924,7 +9924,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "bellman", "blake2b_simd", @@ -9946,7 +9946,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "corez", "document-features", @@ -9983,7 +9983,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "bip32", "bs58", @@ -10132,7 +10132,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=b2d59ba821bf0d560cff1040f48308ab21e1d1fb#b2d59ba821bf0d560cff1040f48308ab21e1d1fb" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index a5f1a2a59..a84546bf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,20 +6,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "8c1c9beeeeeefb56fa309f56062b82feb70bb1d4" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "8ac8fcb9b766731e281791196d6608998b8d4a1d" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } # -- lrz ZSA branch -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "b2d59ba821bf0d560cff1040f48308ab21e1d1fb" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index e6815358f..a1220ad44 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -54,10 +54,13 @@ impl Coin { let mut connection = pool.acquire().await?; - let default_coin = self.coin.to_string(); + let mut default_coin = self.coin; + if default_coin == 2 && self.db_filepath.to_lowercase().contains("zsa") { + default_coin = 3; + } let coin = crate::db::get_prop(&mut connection, "coin") .await? - .unwrap_or(default_coin); + .unwrap_or(default_coin.to_string()); let coin = coin.parse::()?; let account = crate::db::get_prop(&mut connection, "account") .await? @@ -90,11 +93,6 @@ impl Coin { 0 => Network::Main, 1 => Network::Test, 2 => { - let orchard_mode = if self.db_filepath.to_lowercase().contains("zsa") { - OrchardMode::Zsa - } else { - OrchardMode::Normal - }; Network::Regtest(LocalNetwork { overwinter: Some(BlockHeight::from_u32(1)), sapling: Some(BlockHeight::from_u32(1)), @@ -107,7 +105,7 @@ impl Coin { nu6_2: Some(BlockHeight::from_u32(1)), nu6_3: Some(BlockHeight::from_u32(250)), nu7: None, - orchard_mode, + orchard_mode: OrchardMode::Normal, }) } 3 => { diff --git a/rust/src/pay/mod.rs b/rust/src/pay/mod.rs index 36917befa..c3c5eee1b 100644 --- a/rust/src/pay/mod.rs +++ b/rust/src/pay/mod.rs @@ -1,12 +1,17 @@ +use std::collections::BTreeMap; + use crate::{api::pay::PcztPackage, Client}; use crate::api::coin::Network; use anyhow::Result; +use orchard::note::AssetBase; use pczt::{roles::verifier::Verifier, Pczt}; use pool::PoolMask; use serde::{Deserialize, Serialize}; use tracing::{info, span, Level}; use zcash_keys::encoding::AddressCodec as _; +use zcash_note_encryption::Domain; +use zcash_protocol::consensus::BranchId; use zcash_transparent::address::TransparentAddress; pub mod error; @@ -125,15 +130,71 @@ pub struct TxPlan { pub can_broadcast: bool, } +fn orchard_asset_name( + proprietary: &BTreeMap>, + asset: Option, +) -> String { + proprietary + .get("asset_name") + .and_then(|value| String::from_utf8(value.clone()).ok()) + .filter(|name| !name.is_empty()) + .unwrap_or_else(|| match asset { + Some(asset) if asset != AssetBase::zatoshi() => hex::encode(&asset.to_bytes()[..8]), + _ => "ZEC".to_string(), + }) +} + +fn append_orchard_plan( + bundle: &orchard::pczt::Bundle, + inputs: &mut Vec, + outputs: &mut Vec, + fee: &mut i64, +) -> Result<()> { + for action in bundle.actions() { + let input_asset_name = + orchard_asset_name(action.spend().proprietary(), action.spend().asset()); + let output_asset_name = + orchard_asset_name(action.output().proprietary(), action.output().asset()); + inputs.push(TxPlanIn { + pool: 2, + amount: action.spend().value().map(|value| value.inner()), + asset_name: input_asset_name, + }); + outputs.push(TxPlanOut { + pool: 2, + amount: action + .output() + .value() + .ok_or_else(|| anyhow::anyhow!("Orchard PCZT output is missing its value"))? + .inner(), + address: action + .output() + .user_address() + .as_ref() + .cloned() + .unwrap_or_default(), + asset_name: output_asset_name, + }); + } + let value_sum: i64 = (*bundle.value_sum()) + .try_into() + .map_err(|_| anyhow::anyhow!("Orchard PCZT value sum exceeds i64"))?; + *fee += value_sum; + Ok(()) +} + impl TxPlan { pub fn from_package(network: &Network, package: &PcztPackage) -> Result { let mut inputs = vec![]; let mut outputs = vec![]; - let pczt = Pczt::parse(&package.pczt).unwrap(); + let pczt = Pczt::parse(&package.pczt) + .map_err(|error| anyhow::anyhow!("Failed to parse PCZT: {error:?}"))?; + let is_zsa = BranchId::try_from(*pczt.global().consensus_branch_id()) + .is_ok_and(|branch_id| branch_id == BranchId::Nu7); let height = *pczt.global().expiry_height(); - let verifier = Verifier::new(pczt); let mut fee = 0i64; + let verifier = Verifier::new(pczt); let verifier = verifier .with_transparent(|bundle| { @@ -183,43 +244,18 @@ impl TxPlan { }) .unwrap(); - let verifier = verifier - .with_orchard(|bundle| { - for a in bundle.actions().iter() { - let input_asset_name = a - .spend() - .proprietary() - .get("asset_name") - .and_then(|v| String::from_utf8(v.clone()).ok()) - .unwrap_or_else(|| "ZEC".to_string()); - let output_asset_name = a - .output() - .proprietary() - .get("asset_name") - .and_then(|v| String::from_utf8(v.clone()).ok()) - .unwrap_or_else(|| "ZEC".to_string()); - inputs.push(TxPlanIn { - pool: 2, - amount: a.spend().value().map(|v| v.inner()), - asset_name: input_asset_name, - }); - outputs.push(TxPlanOut { - pool: 2, - amount: a.output().value().expect("value").inner(), - address: a - .output() - .user_address() - .as_ref() - .cloned() - .unwrap_or_default(), - asset_name: output_asset_name, - }); - } - let f: i64 = (*bundle.value_sum()).try_into().unwrap(); - fee += f; - Ok::<_, pczt::roles::verifier::OrchardError<()>>(()) + let verifier = if is_zsa { + verifier.with_orchard_zsa(|bundle| { + append_orchard_plan(bundle, &mut inputs, &mut outputs, &mut fee) + .map_err(pczt::roles::verifier::OrchardError::Custom) }) - .unwrap(); + } else { + verifier.with_orchard(|bundle| { + append_orchard_plan(bundle, &mut inputs, &mut outputs, &mut fee) + .map_err(pczt::roles::verifier::OrchardError::Custom) + }) + } + .map_err(|error| anyhow::anyhow!("Failed to verify Orchard PCZT: {error:?}"))?; let _verifier = verifier .with_ironwood(|bundle| { diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 3c4a93199..cfe1eae63 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -28,6 +28,7 @@ use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use tracing::{event, info, span, Level}; use zcash_address::{unified::Receiver, ConversionError, TryFromAddress, ZcashAddress}; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; +use zcash_note_encryption::Domain; use zcash_protocol::{PoolType, ShieldedPool}; use zcash_primitives::transaction::{ builder::{BuildConfig, Builder}, @@ -69,6 +70,38 @@ use crate::{ use zcash_primitives::transaction::zsa_builder::ZsaBuilder; +fn attach_orchard_asset_names( + mut updater: orchard::pczt::Updater<'_, D>, + asset_names: &HashMap<[u8; 32], String>, +) -> Result<(), orchard::pczt::UpdaterError> { + for index in 0..updater.bundle().actions().len() { + let (spend_name, output_name) = { + let action = &updater.bundle().actions()[index]; + ( + action + .spend() + .asset() + .and_then(|asset| asset_names.get(&asset.to_bytes()).cloned()), + action + .output() + .asset() + .and_then(|asset| asset_names.get(&asset.to_bytes()).cloned()), + ) + }; + + updater.update_action_with(index, |mut action| { + if let Some(name) = spend_name { + action.set_spend_proprietary("asset_name".to_string(), name.into_bytes()); + } + if let Some(name) = output_name { + action.set_output_proprietary("asset_name".to_string(), name.into_bytes()); + } + Ok(()) + })?; + } + Ok(()) +} + pub fn is_tex(network: &Network, address: &str) -> Result { let zaddress = ZcashAddress::from_str(address)?; let zaddress: zcash_keys::address::Address = @@ -935,6 +968,36 @@ pub async fn plan_transaction( let pczt = Creator::build_from_parts(r.pczt_parts).unwrap(); info!("Created"); + let mut asset_names = sqlx::query( + "SELECT asset_base, asset_name FROM assets + WHERE asset_name IS NOT NULL AND asset_name != ''", + ) + .map(|row: SqliteRow| { + let asset_base: Vec = row.get(0); + let asset_name: String = row.get(1); + (asset_base, asset_name) + }) + .fetch_all(&mut *connection) + .await? + .into_iter() + .filter_map(|(asset_base, asset_name)| { + asset_base + .try_into() + .ok() + .map(|asset_base| (asset_base, asset_name)) + }) + .collect::>(); + for recipient in &recipient_states { + if let (Ok(asset_base), Some(asset_name)) = ( + recipient.asset_base.as_slice().try_into(), + recipient.recipient.asset_name.as_ref(), + ) { + if !asset_name.is_empty() { + asset_names.insert(asset_base, asset_name.clone()); + } + } + } + let updater = Updater::new(pczt); let updater = updater .update_transparent_with(|mut u| { @@ -975,6 +1038,15 @@ pub async fn plan_transaction( }) .unwrap(); + let updater = if BranchId::for_height(network, BlockHeight::from_u32(target_height)) + == BranchId::Nu7 + { + updater.update_orchard_zsa_with(|u| attach_orchard_asset_names(u, &asset_names)) + } else { + updater.update_orchard_with(|u| attach_orchard_asset_names(u, &asset_names)) + } + .map_err(|error| anyhow!("Failed to attach Orchard asset names: {error:?}"))?; + let pczt = updater.finish(); // Issuer phase 1: build the AwaitingSighash issue bundle diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 6198b209a..5b76aa4b2 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -570,7 +570,7 @@ async fn test_zsa_transfer() { memo_bytes: None, price: None, asset_base: zsa_base.clone(), - asset_name: None, + asset_name: Some(asset_name.clone()), }; let options = PaymentOptions { @@ -587,6 +587,16 @@ async fn test_zsa_transfer() { assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); println!(" spends: {:?}", pczt.n_spends); + let tx_plan = + rlz::api::pay::to_plan(&pczt, &sender).expect("render ZSA transaction plan"); + assert!( + tx_plan + .outputs + .iter() + .any(|output| output.amount == send_amount && output.asset_name == asset_name), + "ZSA recipient must be displayed with its asset name", + ); + let signed = sign_transaction(&pczt, &sender).await.expect("sign"); let tx_bytes = extract_transaction(&signed).await.expect("extract"); println!("ZSA transfer tx: {} bytes", tx_bytes.len()); From 818efa93b5608e646285adb5862c865417456745 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 13:09:15 +0200 Subject: [PATCH 018/189] chore: remove temporary ZSA diagnostics --- Cargo.lock | 24 ++++----- Cargo.toml | 20 ++++---- macos/Runner.xcodeproj/project.pbxproj | 22 ++++---- rust/src/bin/dump_tx.rs | 71 -------------------------- rust/src/bin/pczt_replay.rs | 32 ------------ rust/src/memo.rs | 10 +--- rust/src/pay/plan.rs | 6 --- rust/src/warp/sync/shielded.rs | 10 ---- 8 files changed, 36 insertions(+), 159 deletions(-) delete mode 100644 rust/src/bin/dump_tx.rs delete mode 100644 rust/src/bin/pczt_replay.rs diff --git a/Cargo.lock b/Cargo.lock index 9aa46093c..fb89a0cd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "blake2b_simd", ] @@ -4712,7 +4712,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=8ac8fcb9b766731e281791196d6608998b8d4a1d#8ac8fcb9b766731e281791196d6608998b8d4a1d" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=9f4d3561f142c5698cb25b674e89af0592e15ffd#9f4d3561f142c5698cb25b674e89af0592e15ffd" dependencies = [ "aes", "bitvec", @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "blake2b_simd", "bls12_381", @@ -9831,7 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "bech32 0.11.1", "bs58", @@ -9844,7 +9844,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "corez", "hex", @@ -9854,7 +9854,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "bech32 0.11.1", "bip32", @@ -9894,7 +9894,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9924,7 +9924,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "bellman", "blake2b_simd", @@ -9946,7 +9946,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "corez", "document-features", @@ -9983,7 +9983,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "bip32", "bs58", @@ -10132,7 +10132,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=7fcde72b73237a261b4bb2fed29ac90f8813bc88#7fcde72b73237a261b4bb2fed29ac90f8813bc88" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index a84546bf0..84a6d1bfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,20 +6,20 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "8ac8fcb9b766731e281791196d6608998b8d4a1d" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "9f4d3561f142c5698cb25b674e89af0592e15ffd" } sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } # -- lrz ZSA branch -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "7fcde72b73237a261b4bb2fed29ac90f8813bc88" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a93a9fcfa..9a9a0bbe0 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXAggregateTarget section */ @@ -298,7 +298,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -421,10 +421,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -580,8 +584,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 8VSA3BX4D8; ENABLE_APP_SANDBOX = YES; @@ -604,7 +608,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = "zkool"; SWIFT_VERSION = 5.0; }; name = Profile; @@ -766,8 +770,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application"; + CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 8VSA3BX4D8; ENABLE_APP_SANDBOX = NO; @@ -787,7 +791,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = "zkool"; SWIFT_VERSION = 5.0; }; name = Release; @@ -854,7 +858,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/rust/src/bin/dump_tx.rs b/rust/src/bin/dump_tx.rs deleted file mode 100644 index fea195ae1..000000000 --- a/rust/src/bin/dump_tx.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! TEMP diagnostic: extract the raw transaction bytes from a saved postsigned PCZT -//! and write them to /tmp/zsa_tx.bin (also reports whether local extract-verify passes). -//! Usage: cargo run --bin dump_tx -- [/tmp/zsa_postsigned.pczt] - -use rlz::api::pay::{extract_transaction, PcztPackage}; - -#[tokio::main] -async fn main() { - let path = std::env::args() - .nth(1) - .unwrap_or_else(|| "/tmp/zsa_postsigned.pczt".to_string()); - let pczt = std::fs::read(&path).expect("read pczt"); - let pkg = PcztPackage { - pczt, - n_spends: [0; 4], - sapling_indices: vec![], - orchard_indices: vec![], - ironwood_indices: vec![], - can_sign: false, - can_broadcast: true, - price: None, - category: None, - is_issuance: false, - }; - match extract_transaction(&pkg).await { - Ok(tx) => { - std::fs::write("/tmp/zsa_tx.bin", &tx).unwrap(); - eprintln!("OK: local extract+verify passed; wrote {} bytes to /tmp/zsa_tx.bin", tx.len()); - // Re-parse the emitted bytes with THIS (new) lrz and report structure. - use zcash_primitives::transaction::{OrchardBundle, Transaction}; - use zcash_protocol::consensus::BranchId; - match Transaction::read(&tx[..], BranchId::Nu7) { - Ok(parsed) => { - eprintln!("SELF RE-PARSE (new lrz): OK"); - if let Some(b) = parsed.orchard_bundle() { - eprintln!(" bundle_version = {:?}", b.bundle_version()); - eprintln!(" flags: spends={} outputs={} zsa_enabled={}", b.flags().spends_enabled(), b.flags().outputs_enabled(), b.flags().zsa_enabled()); - eprintln!(" flag_byte = {:#04x}", b.flag_byte()); - match b { - OrchardBundle::OrchardVanilla(b) => { - eprintln!(" orchard actions = {}", b.actions().len()); - for (i, a) in b.actions().iter().enumerate() { - eprintln!( - " action[{i}] enc_ciphertext len = {}", - a.encrypted_note().enc_ciphertext.as_ref().len() - ); - } - } - OrchardBundle::OrchardZSA(b) => { - eprintln!(" ZSA orchard actions = {}", b.actions().len()); - for (i, a) in b.actions().iter().enumerate() { - eprintln!( - " action[{i}] enc_ciphertext len = {}", - a.encrypted_note().enc_ciphertext.as_ref().len() - ); - } - } - } - } else { - eprintln!(" no orchard bundle in re-parsed tx!"); - } - } - Err(e) => eprintln!("SELF RE-PARSE (new lrz) FAILED: {e:?}"), - } - } - Err(e) => { - eprintln!("EXTRACT FAILED (local verify rejected): {e:?}"); - std::process::exit(1); - } - } -} diff --git a/rust/src/bin/pczt_replay.rs b/rust/src/bin/pczt_replay.rs deleted file mode 100644 index e7c1bbf2b..000000000 --- a/rust/src/bin/pczt_replay.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Replay PCZT orchard proving from a saved file. -//! Usage: cargo run --bin pczt_replay -- - -fn main() { - let args: Vec = std::env::args().collect(); - if args.len() < 3 { - eprintln!("Usage: {} ", args[0]); - std::process::exit(1); - } - - let bytes = std::fs::read(&args[1]).expect("read input"); - let pczt = pczt::Pczt::parse(&bytes).expect("parse PCZT"); - - let is_zsa = zcash_protocol::consensus::BranchId::try_from(*pczt.global().consensus_branch_id()) - .map(|b| b == zcash_protocol::consensus::BranchId::Nu7) - .unwrap_or(false); - - let orchard_pk = if is_zsa { - orchard::circuit::ProvingKey::build_zsa() - } else { - orchard::circuit::ProvingKey::build(orchard::circuit::OrchardCircuitVersion::FixedPostNu6_2) - }; - - let prover = pczt::roles::prover::Prover::new(pczt) - .create_orchard_proof(&orchard_pk) - .expect("orchard proof"); - let pczt = prover.finish(); - - let out = pczt.serialize().expect("serialize"); - std::fs::write(&args[2], &out).expect("write output"); - eprintln!("Wrote {} bytes to {}", out.len(), args[2]); -} diff --git a/rust/src/memo.rs b/rust/src/memo.rs index 5472fb9ca..ad54c1970 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -411,10 +411,6 @@ pub async fn decrypt_memo( ) .await?; } - } else { - debug!( - "decrypt_memo: both ivk and ovk decrypt failed for vout={vout} pool={pool}" - ); } } else { debug!( @@ -429,13 +425,9 @@ pub async fn decrypt_memo( if let Some(bundle) = tx_data.orchard_bundle() { match bundle { OrchardBundle::OrchardVanilla(b) => { - debug!("decrypt_memo: orchard bundle with {} actions", b.actions().len()); process_orchard_memo!(b, 2, OrchardDomain); } - OrchardBundle::OrchardZSA(_b) => { - // TODO: ZSA memo decryption — use OrchardZSADomain - debug!("decrypt_memo: skipping ZSA orchard bundle (not yet implemented)"); - } + OrchardBundle::OrchardZSA(_) => {} } } if let Some(bundle) = tx_data.ironwood_bundle() { diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index cfe1eae63..607aec28a 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -955,12 +955,6 @@ pub async fn plan_transaction( builder.set_zsa_builder(zsa); } - info!( - "Building: n_spends T={} S={} O={} IW={}, n_outputs T={} S={} O={} IW={}", - n_spends[0], n_spends[1], n_spends[2], n_spends[3], - n_outputs[0], n_outputs[1], n_outputs[2], n_outputs[3], - ); - let r = builder.build_for_pczt(OsRng, &FeeRule::standard(), |_asset: &AssetBase| false)?; let sapling_meta = &r.sapling_meta; let ironwood_meta = &r.ironwood_meta; diff --git a/rust/src/warp/sync/shielded.rs b/rust/src/warp/sync/shielded.rs index 236288749..543901616 100644 --- a/rust/src/warp/sync/shielded.rs +++ b/rust/src/warp/sync/shielded.rs @@ -229,7 +229,6 @@ impl Synchronizer

{ }) }) .collect::>(); - debug!("Action notes #{}", notes.len()); // Process issuance notes from vtx.issuances — plaintext, no trial // decryption needed. Per tx we track the cmxs (for tree building) @@ -256,13 +255,6 @@ impl Synchronizer

{ // Compute cmx for tree building. Returns None for // protocols that don't support issuance (Sapling, Ironwood). if let Some(cmx) = P::compute_issuance_cmx(note, &asset_base)? { - debug!( - "Issuance cmx: height={} ivtx={} vout={} cmx={}", - height, - ivtx, - note_vout, - hex::encode(cmx) - ); tx_issuance_cmxs.push(cmx); } @@ -295,7 +287,6 @@ impl Synchronizer

{ } } } - debug!("Notes total (actions + issuances) #{}", notes.len()); // Build a lookup of per-tx issuance note counts for position tracking. let mut issuance_count: std::collections::HashMap<(u32, u32), u32> = @@ -380,7 +371,6 @@ impl Synchronizer

{ let mut cmxs = vec![]; let mut count_cmxs = 0; - debug!("WS starting position {}-{}", self.position, position); for depth in 0..MERKLE_DEPTH as usize { let mut position = self.position >> depth; if position % 2 == 1 { From 42ed01c8d69478e13a58054740505fd0f62792f4 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 15:17:17 +0200 Subject: [PATCH 019/189] fix: auto-pin db to coin=3 when filename contains 'zsa' --- rust/Cargo.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8b9fd6139..f58e52ecd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,10 +11,6 @@ name = "zkool_graphql" path = "src/graphql-cli.rs" required-features = ["graphql"] -[[bin]] -name = "pczt_replay" -path = "src/bin/pczt_replay.rs" - [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "0dc1bfd" } flutter_rust_bridge = { version = "=2.12.0", optional = true } @@ -157,5 +153,3 @@ graphql = ["juniper", "juniper_warp", "juniper_graphql_ws", "dataloader", "warp" ledger = ["hidapi", "ledger-transport"] zemu = ["ledger", "ledger-transport-zemu"] flutter_rust_bridge = ["dep:flutter_rust_bridge"] - - From 484563c9347410d14c1e35bd5a57652e012dba67 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 15:38:10 +0200 Subject: [PATCH 020/189] fix: remove cargo config --- .cargo/config.toml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index c91c3f38b..000000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[net] -git-fetch-with-cli = true From b42acbbfda59bb237051b2cff4b669287bb571be Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 17:22:21 +0200 Subject: [PATCH 021/189] fix: improve error handling and diagnostics - fix IRW detection - migrate: use mounted check instead of context.mounted for error display - frost: use orchard_pk from PCZT consensus branch instead of network check - plan: replace unwrap() with map_err, add OrchardProvingKeyKind, PCZT-DUMP diagnostics --- lib/pages/migrate.dart | 9 +++-- rust/src/frost/sign.rs | 3 +- rust/src/pay/plan.rs | 87 ++++++++++++++++++++++++++++-------------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 54c6227dd..1950cead2 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -82,10 +82,11 @@ class _MigratePageState extends State _countdown = null; } }, - onError: (e) async { - final exc = e as AnyhowException; - if (!context.mounted) return; - await showException(context, exc.message); + onError: (e) { + if (!mounted) return; + final message = + e is AnyhowException ? e.message : e.toString(); + showException(context, message); }, ); } on AnyhowException catch (e) { diff --git a/rust/src/frost/sign.rs b/rust/src/frost/sign.rs index eb9059584..22eb06253 100644 --- a/rust/src/frost/sign.rs +++ b/rust/src/frost/sign.rs @@ -32,7 +32,6 @@ use tracing::info; use zcash_primitives::transaction::{ sighash::SignableInput, sighash_v5::v5_signature_hash, txid::TxIdDigester, }; -use zcash_protocol::consensus::{BlockHeight, NetworkUpgrade, Parameters}; use zcash_protocol::memo::Memo; use crate::{ @@ -697,7 +696,7 @@ pub async fn do_sign_impl( let sapling_prover = get_sapling_prover().await?; - let orchard_pk = get_orchard_pk(network, network.is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height))); + let orchard_pk = get_orchard_pk(*pczt.global().consensus_branch_id())?; let pczt = Prover::new(pczt) .create_sapling_proofs(sapling_prover, sapling_prover) .unwrap() diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 607aec28a..8f1d03e3a 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1136,7 +1136,9 @@ pub async fn sign_transaction( is_issuance, .. } = pczt; - let pczt = Pczt::parse(pczt).unwrap(); + let pczt = Pczt::parse(pczt) + .map_err(|error| anyhow!("failed to parse PCZT for signing: {error:?}"))?; + let orchard_pk = get_orchard_pk(*pczt.global().consensus_branch_id())?; let dindex = get_account_dindex(connection, account).await?; let tkeys = select_account_transparent(connection, account, dindex).await?; @@ -1287,7 +1289,6 @@ pub async fn sign_transaction( signer.sign_ironwood(*bundle_index, osak).unwrap(); } let pczt = signer.finish(); - let use_zsa_pk = is_zsa(*pczt.global().consensus_branch_id()); span.in_scope(|| { info!("Adding Proofs to PCZT"); @@ -1296,19 +1297,23 @@ pub async fn sign_transaction( let pczt = Prover::new(pczt) .create_sapling_proofs(sapling_prover, sapling_prover) - .unwrap() - .create_orchard_proof(if use_zsa_pk { &ORCHARD_ZSA_PK } else { &ORCHARD_VANILLA_PK }) - .unwrap() + .map_err(|error| anyhow!("failed to create Sapling proofs: {error:?}"))? + .create_orchard_proof(orchard_pk) + .map_err(|error| anyhow!("failed to create Orchard proof: {error:?}"))? .create_ironwood_proof(&IRONWOOD_PK) - .unwrap() + .map_err(|error| anyhow!("failed to create Ironwood proof: {error:?}"))? .finish(); info!("Proved"); - let pczt = SpendFinalizer::new(pczt).finalize_spends().unwrap(); + let pczt = SpendFinalizer::new(pczt) + .finalize_spends() + .map_err(|error| anyhow!("failed to finalize PCZT spends: {error:?}"))?; info!("Spend Finalized"); Ok(PcztPackage { - pczt: pczt.serialize().unwrap(), + pczt: pczt + .serialize() + .map_err(|error| anyhow!("failed to serialize signed PCZT: {error:?}"))?, n_spends: *n_spends, sapling_indices: sapling_indices.clone(), orchard_indices: orchard_indices.clone(), @@ -1540,30 +1545,54 @@ pub static ORCHARD_ZSA_PK: LazyLock = pub static IRONWOOD_PK: LazyLock = LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::PostNu6_3)); -pub fn get_orchard_pk( - network: &crate::api::coin::Network, - ironwood_active: bool, -) -> &'static ProvingKey { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum OrchardProvingKeyKind { + Vanilla, + Zsa, + Ironwood, +} + +fn orchard_proving_key_kind(branch_id: BranchId) -> OrchardProvingKeyKind { + match branch_id { + BranchId::Nu7 => OrchardProvingKeyKind::Zsa, + BranchId::Nu6_3 => OrchardProvingKeyKind::Ironwood, + _ => OrchardProvingKeyKind::Vanilla, + } +} + +pub(crate) fn get_orchard_pk(consensus_branch_id: u32) -> Result<&'static ProvingKey> { // ZSA and Ironwood are mutually exclusive hard forks with different // V6 version group IDs and circuit versions. - let uses_orchard_zsa = match network { - crate::api::coin::Network::Regtest(config) - | crate::api::coin::Network::ZsaRegtest(config) => { - config.orchard_mode() == zcash_protocol::consensus::OrchardMode::Zsa - } - _ => false, - }; + let branch_id = BranchId::try_from(consensus_branch_id) + .map_err(|_| anyhow!("unsupported consensus branch ID: {consensus_branch_id:#x}"))?; + Ok(match orchard_proving_key_kind(branch_id) { + OrchardProvingKeyKind::Vanilla => &ORCHARD_VANILLA_PK, + OrchardProvingKeyKind::Zsa => &ORCHARD_ZSA_PK, + OrchardProvingKeyKind::Ironwood => &IRONWOOD_PK, + }) +} - if uses_orchard_zsa { - &ORCHARD_ZSA_PK - } else if ironwood_active { - &IRONWOOD_PK - } else { - &ORCHARD_VANILLA_PK +#[cfg(test)] +mod tests { + use super::{orchard_proving_key_kind, BranchId, OrchardProvingKeyKind}; + + #[test] + fn ironwood_activation_selects_ironwood_orchard_proving_key() { + assert_eq!( + orchard_proving_key_kind(BranchId::Nu6_3), + OrchardProvingKeyKind::Ironwood, + ); + assert_eq!( + orchard_proving_key_kind(BranchId::Nu6_2), + OrchardProvingKeyKind::Vanilla, + ); } -} -fn is_zsa(consensus_branch_id: u32) -> bool { - zcash_protocol::consensus::BranchId::try_from(consensus_branch_id) - .is_ok_and(|b| b == zcash_protocol::consensus::BranchId::Nu7) + #[test] + fn zsa_selects_zsa_orchard_proving_key() { + assert_eq!( + orchard_proving_key_kind(BranchId::Nu7), + OrchardProvingKeyKind::Zsa, + ); + } } From 329a1cf1373239a4dca5dafa4b3cf130f384958c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 19:40:21 +0200 Subject: [PATCH 022/189] fix: always select notes for privacy, with fee as tie-breaker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the fee-vs-privacy coin-selection toggle and collapse the solver to a single strategy: minimize cross-pool turnstile value, then minimize the ZIP-317 fee among equally private solutions. Solver (rust/src/pay/solve.rs): - evaluate_privacy now breaks change-pool ties on fee instead of keeping whichever pool it reached first. - Branch-and-bound compares (turnstile, fee) lexicographically and keeps expanding nodes whose bound equals the incumbent, since an equal-privacy subtree can still yield a cheaper fee. - The reported fee is the fee of the selected change pool. It used to be recomputed as the globally cheapest pool, which could pair the privacy-optimal change pool with a fee computed for a different one. - Remove Mode, evaluate_fee, lower_bound_fee, compute_min_fee, the fee branch of local_score, and the unused Selection::change_amount. - Add tests for the fee tie-break and the equal-bound acceptance rule. Plumbing: drop the mode parameter from plan_transaction, PaymentOptions and the GraphQL Payment input, remove getCoinSelectionMode/setCoinSelectionMode and the coin_selection_mode DB property, and delete the "Privacy Preservation" switch from the send page. Callers that previously requested Mode::Fee — asset issuance, note migration, prepare_migration — now go through the privacy-first solver. --- lib/pages/send.dart | 17 -- lib/src/rust/api/pay.dart | 20 +- lib/src/rust/frb_generated.dart | 290 ++++++++++++----------------- rust/src/api/issuance.rs | 1 - rust/src/api/pay.rs | 33 +--- rust/src/db.rs | 22 --- rust/src/frb_generated.rs | 300 +++++++++++------------------- rust/src/frost/protocol.rs | 1 - rust/src/graphql/mutation.rs | 2 - rust/src/graphql/query.rs | 6 - rust/src/migrate/mod.rs | 2 - rust/src/pay/plan.rs | 6 +- rust/src/pay/solve.rs | 315 +++++++++++--------------------- rust/tests/zsa_transfer_test.rs | 2 - 14 files changed, 334 insertions(+), 683 deletions(-) diff --git a/lib/pages/send.dart b/lib/pages/send.dart index a40393b5c..d778e93ce 100644 --- a/lib/pages/send.dart +++ b/lib/pages/send.dart @@ -314,7 +314,6 @@ class SendPageState extends ConsumerState { srcPools: 1, // Only the transparent pool (mask) recipientPaysFee: true, smartTransparent: smartTransparent, - mode: 0, ); final pczt = await prepare( recipients: [ @@ -340,7 +339,6 @@ class SendPageState extends ConsumerState { srcPools: 6, // Only the sapling and orchard pool (mask) recipientPaysFee: true, smartTransparent: false, - mode: 0, ); final pczt = await prepare( recipients: [ @@ -690,8 +688,6 @@ class Send2PageState extends ConsumerState { late final hasTex = widget.recipients.any((r) => isTexAddress(address: r.address, c: c)); late final hasZsa = widget.recipients.any((r) => !r.assetBase.every((b) => b == 0)); late var recipientPaysFee = widget.recipientPaysFee; - /// 0 = fee optimisation, 1 = privacy preservation. - var coinSelectionMode = 1; int? category; var puri = ""; AccountData? account; @@ -765,18 +761,6 @@ class Send2PageState extends ConsumerState { onChanged: (v) => setState(() => recipientPaysFee = v!), ), ), - Tooltip( - message: "Fee optimisation picks notes to minimise transaction fees. " - "Privacy preservation picks notes to minimise cross-pool transfers, " - "keeping value within the same shielded pool.", - child: FormBuilderSwitch( - name: "privacyMode", - title: Text("Privacy Preservation"), - initialValue: coinSelectionMode == 1, - onChanged: (v) => - setState(() => coinSelectionMode = (v ?? false) ? 1 : 0), - ), - ), Tooltip( message: "Spending or Income Category (for Budgetting)", child: FormBuilderDropdown( @@ -874,7 +858,6 @@ class Send2PageState extends ConsumerState { recipientPaysFee: recipientPaysFee, smartTransparent: false, category: category, - mode: coinSelectionMode, ); final pczt = await prepare( recipients: widget.recipients, diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index c64b6e092..5af48ef4c 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -66,16 +66,6 @@ Future storePendingTx( RustLib.instance.api.crateApiPayStorePendingTx( height: height, txid: txid, price: price, category: category, c: c); -/// Get the persisted coin-selection mode preference. -/// Returns 0 for fee optimisation, 1 for privacy preservation. -Future getCoinSelectionMode({required Coin c}) => - RustLib.instance.api.crateApiPayGetCoinSelectionMode(c: c); - -/// Persist the coin-selection mode preference. -/// Pass 0 for fee optimisation, 1 for privacy preservation. -Future setCoinSelectionMode({required int mode, required Coin c}) => - RustLib.instance.api.crateApiPaySetCoinSelectionMode(mode: mode, c: c); - List? parsePaymentUri({required String uri}) => RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); @@ -85,15 +75,11 @@ class PaymentOptions { final bool smartTransparent; final int? category; - /// Coin-selection mode: 0 = fee minimisation, 1 = privacy preservation. - final int mode; - const PaymentOptions({ required this.srcPools, required this.recipientPaysFee, required this.smartTransparent, this.category, - required this.mode, }); @override @@ -101,8 +87,7 @@ class PaymentOptions { srcPools.hashCode ^ recipientPaysFee.hashCode ^ smartTransparent.hashCode ^ - category.hashCode ^ - mode.hashCode; + category.hashCode; @override bool operator ==(Object other) => @@ -112,8 +97,7 @@ class PaymentOptions { srcPools == other.srcPools && recipientPaysFee == other.recipientPaysFee && smartTransparent == other.smartTransparent && - category == other.category && - mode == other.mode; + category == other.category; } @freezed diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 30de487a9..603bf6f4c 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -94,7 +94,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -1618730169; + int get rustContentHash => 607482081; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -298,8 +298,6 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountGetAddresses( {required int uaPools, required Coin c}); - Future crateApiPayGetCoinSelectionMode({required Coin c}); - Future crateApiNetworkGetCoingeckoPrice( {required String api, required String currency}); @@ -505,9 +503,6 @@ abstract class RustLibApi extends BaseApi { Future crateApiZsaSetAssetName( {required PlatformInt64 idAsset, required String name, required Coin c}); - Future crateApiPaySetCoinSelectionMode( - {required int mode, required Coin c}); - Future crateApiFrostSetDkgAddress( {required int id, required String address, required Coin c}); @@ -2489,33 +2484,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["uaPools", "c"], ); - @override - Future crateApiPayGetCoinSelectionMode({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 64, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_8, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayGetCoinSelectionModeConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiPayGetCoinSelectionModeConstMeta => - const TaskConstMeta( - debugName: "get_coin_selection_mode", - argNames: ["c"], - ); - @override Future crateApiNetworkGetCoingeckoPrice( {required String api, required String currency}) { @@ -2526,7 +2494,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); + funcId: 64, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -2553,7 +2521,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); + funcId: 65, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2580,7 +2548,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); + funcId: 66, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -2606,7 +2574,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); + funcId: 67, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2638,7 +2606,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 69, port: port_); + funcId: 68, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -2667,7 +2635,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 70, port: port_); + funcId: 69, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2694,7 +2662,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70)!; }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2722,7 +2690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); + funcId: 71, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2749,7 +2717,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 73, port: port_); + funcId: 72, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -2776,7 +2744,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 74, port: port_); + funcId: 73, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2804,7 +2772,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 75, port: port_); + funcId: 74, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2829,7 +2797,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75)!; }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2856,7 +2824,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); + funcId: 76, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2882,7 +2850,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 78, port: port_); + funcId: 77, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2910,7 +2878,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 79, port: port_); + funcId: 78, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -2937,7 +2905,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); + funcId: 79, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2964,7 +2932,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); + funcId: 80, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2990,7 +2958,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); + funcId: 81, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3020,7 +2988,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 83, port: port_); + funcId: 82, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3049,7 +3017,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); + funcId: 83, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3075,7 +3043,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); + funcId: 84, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3100,7 +3068,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); + funcId: 85, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3126,7 +3094,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); + funcId: 86, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3152,7 +3120,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 88, port: port_); + funcId: 87, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3178,7 +3146,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 89, port: port_); + funcId: 88, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3202,7 +3170,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 90)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3235,7 +3203,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); + funcId: 90, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3263,7 +3231,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( append, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 92, port: port_); + funcId: 91, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -3292,7 +3260,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 93, port: port_); + funcId: 92, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -3319,7 +3287,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); + funcId: 93, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3346,7 +3314,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 95, port: port_); + funcId: 94, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3373,7 +3341,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3398,7 +3366,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3424,7 +3392,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3450,7 +3418,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3475,8 +3443,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 100)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3504,7 +3471,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 101)!; + funcId: 100)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3531,7 +3498,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 102, port: port_); + funcId: 101, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3570,7 +3537,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 103, port: port_); + funcId: 102, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3612,7 +3579,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 104, port: port_); + funcId: 103, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -3639,7 +3606,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105, port: port_); + funcId: 104, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -3666,7 +3633,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106, port: port_); + funcId: 105, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3694,7 +3661,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107, port: port_); + funcId: 106, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -3720,7 +3687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108, port: port_); + funcId: 107, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3746,7 +3713,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109, port: port_); + funcId: 108, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -3772,7 +3739,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); + funcId: 109, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -3798,7 +3765,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); + funcId: 110, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -3824,7 +3791,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); + funcId: 111, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -3850,7 +3817,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); + funcId: 112, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -3877,7 +3844,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); + funcId: 113, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -3906,7 +3873,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + funcId: 114, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3935,7 +3902,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3962,7 +3929,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -3991,7 +3958,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4017,7 +3984,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4045,7 +4012,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); + funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4072,7 +4039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121)!; + funcId: 120)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -4103,7 +4070,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4134,7 +4101,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); + funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4162,7 +4129,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + funcId: 123, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4191,7 +4158,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + funcId: 124, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4217,7 +4184,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -4243,7 +4210,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); + funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4272,7 +4239,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128)!; + funcId: 127)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4301,7 +4268,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); + funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4330,7 +4297,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); + funcId: 129, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4358,7 +4325,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + funcId: 130, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4388,7 +4355,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + funcId: 131, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4418,7 +4385,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4445,7 +4412,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); + funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4472,7 +4439,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); + funcId: 134, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4500,7 +4467,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); + funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4528,7 +4495,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + funcId: 136, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4556,7 +4523,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4586,7 +4553,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); + funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4617,7 +4584,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(c, serializer); sse_encode_u_64(meanDelayMs, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4649,7 +4616,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); + funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4678,7 +4645,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + funcId: 141, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4696,35 +4663,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["idAsset", "name", "c"], ); - @override - Future crateApiPaySetCoinSelectionMode( - {required int mode, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(mode, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPaySetCoinSelectionModeConstMeta, - argValues: [mode, c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiPaySetCoinSelectionModeConstMeta => - const TaskConstMeta( - debugName: "set_coin_selection_mode", - argNames: ["mode", "c"], - ); - @override Future crateApiFrostSetDkgAddress( {required int id, required String address, required Coin c}) { @@ -4736,7 +4674,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); + funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4773,7 +4711,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); + funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4799,7 +4737,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146)!; + funcId: 144)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4826,7 +4764,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147)!; + funcId: 145)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4856,7 +4794,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + funcId: 146, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4886,7 +4824,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + funcId: 147, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4916,7 +4854,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + funcId: 148, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4946,7 +4884,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); + funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4973,7 +4911,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152, port: port_); + funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5001,7 +4939,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); + funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5033,7 +4971,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + funcId: 152, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5064,7 +5002,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + funcId: 153, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5090,7 +5028,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5126,7 +5064,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157, port: port_); + funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5168,7 +5106,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); + funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -5215,7 +5153,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159)!; + funcId: 157)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5243,7 +5181,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160)!; + funcId: 158)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5269,7 +5207,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + funcId: 159, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5295,7 +5233,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5321,7 +5259,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + funcId: 161, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5347,7 +5285,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); + funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5373,7 +5311,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); + funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5403,7 +5341,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166)!; + funcId: 164)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5429,7 +5367,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); + funcId: 165, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5456,7 +5394,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5485,7 +5423,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + funcId: 167, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5521,7 +5459,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); + funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5553,7 +5491,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); + funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5580,7 +5518,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172)!; + funcId: 170)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5609,7 +5547,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173)!; + funcId: 171)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -6720,14 +6658,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PaymentOptions dco_decode_payment_options(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 5) - throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return PaymentOptions( srcPools: dco_decode_u_8(arr[0]), recipientPaysFee: dco_decode_bool(arr[1]), smartTransparent: dco_decode_bool(arr[2]), category: dco_decode_opt_box_autoadd_u_32(arr[3]), - mode: dco_decode_u_8(arr[4]), ); } @@ -8517,13 +8454,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_recipientPaysFee = sse_decode_bool(deserializer); var var_smartTransparent = sse_decode_bool(deserializer); var var_category = sse_decode_opt_box_autoadd_u_32(deserializer); - var var_mode = sse_decode_u_8(deserializer); return PaymentOptions( srcPools: var_srcPools, recipientPaysFee: var_recipientPaysFee, smartTransparent: var_smartTransparent, - category: var_category, - mode: var_mode); + category: var_category); } @protected @@ -10202,7 +10137,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(self.recipientPaysFee, serializer); sse_encode_bool(self.smartTransparent, serializer); sse_encode_opt_box_autoadd_u_32(self.category, serializer); - sse_encode_u_8(self.mode, serializer); } @protected diff --git a/rust/src/api/issuance.rs b/rust/src/api/issuance.rs index d84fbcc08..fc7350d9f 100644 --- a/rust/src/api/issuance.rs +++ b/rust/src/api/issuance.rs @@ -125,7 +125,6 @@ pub async fn issue_asset( None, // category Some(&issuance_info), false, // migration - crate::pay::solve::Mode::Fee, None, // preselected ) .await?; diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 4630a8c73..b4ef61a7e 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -1,11 +1,7 @@ use anyhow::Result; use bincode::{config::legacy, Decode, Encode}; -use crate::{api::coin::Coin, pay::{Recipient, TxPlan, plan::plan_transaction, solve::Mode}}; - -/// FFI-compatible coin-selection mode (maps to `solve::Mode`). -/// 0 = Fee optimisation, 1 = Privacy preservation (default). -const MODE_FEE: u8 = 0; +use crate::{api::coin::Coin, pay::{Recipient, TxPlan, plan::plan_transaction}}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; @@ -14,8 +10,6 @@ pub struct PaymentOptions { pub recipient_pays_fee: bool, pub smart_transparent: bool, pub category: Option, - /// Coin-selection mode: 0 = fee minimisation, 1 = privacy preservation. - pub mode: u8, } #[cfg_attr(feature = "flutter", frb)] @@ -30,8 +24,6 @@ pub async fn prepare(recipients: &[Recipient], options: PaymentOptions, c: &Coin let mut connection = c.get_connection().await?; let mut client = c.client().await?; - let mode = if options.mode == MODE_FEE { Mode::Fee } else { Mode::Privacy }; - plan_transaction( network, &mut *connection, @@ -45,7 +37,6 @@ pub async fn prepare(recipients: &[Recipient], options: PaymentOptions, c: &Coin options.category, None, // issuance — normal sends have no issuance false, // migration — only used by note migration - mode, None, // preselected ) .await @@ -77,7 +68,6 @@ pub async fn prepare_migration( None, // category None, // issuance true, // migration - Mode::Fee, None, // preselected ) .await @@ -162,27 +152,6 @@ pub async fn store_pending_tx(height: u32, txid: &[u8], Ok(()) } -/// Get the persisted coin-selection mode preference. -/// Returns 0 for fee optimisation, 1 for privacy preservation. -#[cfg_attr(feature = "flutter", frb)] -pub async fn get_coin_selection_mode(c: &Coin) -> Result { - let mut connection = c.get_connection().await?; - let mode = crate::db::get_coin_selection_mode(&mut connection).await?; - Ok(match mode { - Mode::Fee => 0, - Mode::Privacy => 1, - }) -} - -/// Persist the coin-selection mode preference. -/// Pass 0 for fee optimisation, 1 for privacy preservation. -#[cfg_attr(feature = "flutter", frb)] -pub async fn set_coin_selection_mode(mode: u8, c: &Coin) -> Result<()> { - let mut connection = c.get_connection().await?; - let mode = if mode == MODE_FEE { Mode::Fee } else { Mode::Privacy }; - crate::db::set_coin_selection_mode(&mut connection, mode).await -} - #[cfg_attr(feature = "flutter", frb(sync))] pub fn parse_payment_uri(uri: &str) -> Option> { crate::pay::prepare::parse_payment_uri(uri).ok() diff --git a/rust/src/db.rs b/rust/src/db.rs index 6281ff54d..535329e3d 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -747,28 +747,6 @@ pub async fn get_prop(connection: &mut SqliteConnection, key: &str) -> Result Result { - match get_prop(connection, MODE_KEY).await? { - Some(v) if v == "fee" => Ok(crate::pay::solve::Mode::Fee), - _ => Ok(crate::pay::solve::Mode::Privacy), - } -} - -pub async fn set_coin_selection_mode( - connection: &mut SqliteConnection, - mode: crate::pay::solve::Mode, -) -> Result<()> { - let value = match mode { - crate::pay::solve::Mode::Fee => "fee", - crate::pay::solve::Mode::Privacy => "privacy", - }; - put_prop(connection, MODE_KEY, value).await -} - pub async fn store_account_metadata( connection: &mut SqliteConnection, name: &str, diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index d9d843a5f..44f7c8180 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -41,7 +41,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1618730169; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 607482081; // Section: executor @@ -2641,42 +2641,6 @@ fn wire__crate__api__account__get_addresses_impl( }, ) } -fn wire__crate__api__pay__get_coin_selection_mode_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "get_coin_selection_mode", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_c = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || async move { - let output_ok = crate::api::pay::get_coin_selection_mode(&api_c).await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} fn wire__crate__api__network__get_coingecko_price_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5545,44 +5509,6 @@ fn wire__crate__api__zsa__set_asset_name_impl( }, ) } -fn wire__crate__api__pay__set_coin_selection_mode_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "set_coin_selection_mode", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_mode = ::sse_decode(&mut deserializer); - let api_c = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || async move { - let output_ok = - crate::api::pay::set_coin_selection_mode(api_mode, &api_c).await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} fn wire__crate__api__frost__set_dkg_address_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -8066,13 +7992,11 @@ impl SseDecode for crate::api::pay::PaymentOptions { let mut var_recipientPaysFee = ::sse_decode(deserializer); let mut var_smartTransparent = ::sse_decode(deserializer); let mut var_category = >::sse_decode(deserializer); - let mut var_mode = ::sse_decode(deserializer); return crate::api::pay::PaymentOptions { src_pools: var_srcPools, recipient_pays_fee: var_recipientPaysFee, smart_transparent: var_smartTransparent, category: var_category, - mode: var_mode, }; } } @@ -8809,158 +8733,152 @@ fn pde_ffi_dispatcher_primary_impl( 62 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), 63 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), 64 => { - wire__crate__api__pay__get_coin_selection_mode_impl(port, ptr, rust_vec_len, data_len) - } - 65 => { wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) } - 66 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), - 67 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), - 68 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 69 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 70 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), - 72 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), - 73 => { + 65 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), + 66 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), + 67 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 68 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 69 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), + 71 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), + 72 => { wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) } - 74 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), - 75 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), - 77 => wire__crate__api__network__get_supported_vs_currencies_impl( + 73 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), + 76 => wire__crate__api__network__get_supported_vs_currencies_impl( port, ptr, rust_vec_len, data_len, ), - 78 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), - 79 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), - 80 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 81 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__crate__api__account__has_transparent_pub_key_impl( + 77 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), + 78 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), + 79 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 80 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 81 => wire__crate__api__account__has_transparent_pub_key_impl( port, ptr, rust_vec_len, data_len, ), - 83 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), - 84 => wire__crate__api__contacts__import_contacts_vcard_impl( + 82 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), + 83 => wire__crate__api__contacts__import_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 85 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), - 86 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), - 87 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 88 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 89 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), - 92 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), - 93 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), - 94 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), - 95 => { + 84 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), + 85 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), + 86 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 87 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 88 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), + 90 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), + 92 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), + 93 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), + 94 => { wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) } - 102 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 103 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 104 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 105 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 106 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 107 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 108 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 109 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 110 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 101 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 102 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 103 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 104 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 105 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 106 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 107 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 108 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 109 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 110 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 114 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 115 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 122 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 129 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 136 => { + 121 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 129 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 135 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 137 => wire__crate__api__openalias__resolve_openalias_all_impl( + 136 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 138 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 137 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 139 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 140 => wire__crate__api__migrate__run_migration_impl(port, ptr, rust_vec_len, data_len), - 141 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 143 => { - wire__crate__api__pay__set_coin_selection_mode_impl(port, ptr, rust_vec_len, data_len) - } - 144 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 149 => { + 138 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 139 => wire__crate__api__migrate__run_migration_impl(port, ptr, rust_vec_len, data_len), + 140 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 141 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 147 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 150 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 151 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__account__show_ledger_sapling_address_impl( + 148 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 153 => wire__crate__api__account__show_ledger_transparent_address_impl( + 151 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 154 => wire__crate__api__account__sign_ledger_transaction_impl( + 152 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 155 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 161 => { + 153 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 154 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 155 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 159 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 162 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__transaction__update_historical_prices_impl( + 160 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 161 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 162 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, @@ -8984,32 +8902,32 @@ fn pde_ffi_dispatcher_sync_impl( 26 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), 27 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), 56 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), - 71 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), - 76 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), - 90 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), - 96 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), - 97 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), - 98 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), - 99 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 100 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 101 => { + 70 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), + 75 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), + 89 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), + 95 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), + 96 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), + 97 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), + 98 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), + 99 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 100 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 121 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 128 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 146 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 147 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 159 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 160 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 120 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 127 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 144 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 145 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 157 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 158 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 166 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 172 => { + 164 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 170 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 173 => { + 171 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -9712,7 +9630,6 @@ impl flutter_rust_bridge::IntoDart for crate::api::pay::PaymentOptions { self.recipient_pays_fee.into_into_dart().into_dart(), self.smart_transparent.into_into_dart().into_dart(), self.category.into_into_dart().into_dart(), - self.mode.into_into_dart().into_dart(), ] .into_dart() } @@ -11308,7 +11225,6 @@ impl SseEncode for crate::api::pay::PaymentOptions { ::sse_encode(self.recipient_pays_fee, serializer); ::sse_encode(self.smart_transparent, serializer); >::sse_encode(self.category, serializer); - ::sse_encode(self.mode, serializer); } } diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index 5756a6099..ad6ab6f91 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -481,7 +481,6 @@ pub async fn publish( None, None, false, // migration - crate::pay::solve::Mode::Privacy, None, // preselected ) .await diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index 92e4f4323..8de2cc16b 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -44,8 +44,6 @@ pub struct Payment { pub src_pools: Option, pub recipient_pays_fee: Option, pub confirmations: Option, - /// Coin-selection mode: "fee" (default) or "privacy". - pub mode: Option, } #[derive(GraphQLObject)] diff --git a/rust/src/graphql/query.rs b/rust/src/graphql/query.rs index 572093cf9..22ff39b5a 100644 --- a/rust/src/graphql/query.rs +++ b/rust/src/graphql/query.rs @@ -375,11 +375,6 @@ pub async fn prepare_tx( } let network = coin.network(); - let mode = match payment.mode.as_deref() { - Some("fee") => crate::pay::solve::Mode::Fee, - _ => crate::pay::solve::Mode::Privacy, - }; - let pczt = crate::pay::plan::plan_transaction( &network, &mut connection, @@ -393,7 +388,6 @@ pub async fn prepare_tx( None, None, false, // migration - mode, None, // preselected ) .await?; diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 9a522970c..30f713b5a 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -293,7 +293,6 @@ pub async fn step( None, None, true, // migration - crate::pay::solve::Mode::Fee, Some(&preselected), ) .await?; @@ -366,7 +365,6 @@ pub async fn step( None, None, true, // migration — O→I - crate::pay::solve::Mode::Fee, Some(&preselected), ) .await?; diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 8f1d03e3a..b1c80b4c5 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -236,7 +236,6 @@ pub async fn plan_transaction( category: Option, issuance: Option<&IssuanceInfo>, migration: bool, - mode: crate::pay::solve::Mode, preselected: Option<&[u32]>, ) -> Result { let mut input_pools = fetch_unspent_notes_by_pool(connection, account).await?; @@ -448,9 +447,9 @@ pub async fn plan_transaction( .collect(); info!( - "plan: calling select_notes — {} input notes, {} outputs, migration={}, recipient_pays_fee={}, first_recipient={}, mode={:?}", + "plan: calling select_notes — {} input notes, {} outputs, migration={}, recipient_pays_fee={}, first_recipient={}", select_notes_input.len(), select_outputs.len(), migration, recipient_pays_fee, - recipients.first().map(|r| r.amount).unwrap_or(0), mode + recipients.first().map(|r| r.amount).unwrap_or(0) ); for o in &select_outputs { info!("plan: output pool={} amount={}", o.pool, o.amount); @@ -463,7 +462,6 @@ pub async fn plan_transaction( migration, recipient_pays_fee, recipients.first().map(|r| r.amount).unwrap_or(0), - mode, ) .ok_or_else(|| anyhow!("No feasible note selection found"))?; diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 80c377b1b..070ea3096 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -1,14 +1,12 @@ //! Anytime branch-and-bound note selection for Zcash transactions. //! -//! Two modes: -//! - `Mode::Fee` — minimize ZIP-317 conventional fee. Monotonic, so -//! the search prunes supersets after reaching feasibility. -//! - `Mode::Privacy` — minimize cross-pool turnstile value (tin + tout + -//! Σ|balance|). Non-monotonic, so the search continues exploring -//! supersets that might improve per-pool balance. +//! The solver minimizes cross-pool turnstile value (tin + tout + +//! Σ|balance|), then minimizes the ZIP-317 fee among equally private +//! solutions. Privacy is non-monotonic, so the search continues exploring +//! supersets that might improve per-pool balance. //! -//! Both modes fold change-pool assignment into the cost evaluation at -//! each feasibility checkpoint. +//! Change-pool assignment is folded into the cost evaluation at each +//! feasibility checkpoint. //! //! Replaces the knapsack+greedy solver in `select.rs`. @@ -24,15 +22,6 @@ use tracing::info; pub const N_POOLS: usize = 4; // Transparent=0, Sapling=1, Orchard=2, Ironwood=3 -/// Optimisation target for note selection. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Mode { - /// Minimize ZIP-317 conventional fee. - Fee, - /// Minimize cross-pool turnstile (privacy-preserving). - Privacy, -} - /// Candidate note for selection. `pool` is the pool index (0–3), `amount` /// is the note value in zatoshis. #[derive(Clone, Debug)] @@ -62,14 +51,10 @@ pub(super) struct Output { /// Result of a successful coin-selection run. #[derive(Debug)] pub(super) struct Selection { - #[allow(dead_code)] pub inputs: Vec, /// Per-pool indices into the original notes-by-pool arrays. pub per_pool_indices: [Vec; N_POOLS], pub change_pool: u8, - #[allow(dead_code)] - pub change_amount: u64, - #[allow(dead_code)] pub fee: u64, } @@ -108,7 +93,6 @@ struct Context<'a> { migration: bool, // orchard fee = inputs+outputs instead of max recipient_pays_fee: bool, first_recipient_amount: u64, - mode: Mode, } // --------------------------------------------------------------------- @@ -188,33 +172,6 @@ fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_poo logical * f_unit } -/// Minimum possible fee for a state (no change output added yet). -/// Used as the lower-bound estimate — since adding change can only add -/// an output (monotonic), the actual final fee is >= this. -fn compute_min_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], f_unit: u64, migration: bool, zsa_change: u32) -> u64 { - // ZSA change notes are already committed once their asset is over-selected, - // so they belong in even the no-ZEC-change lower bound (monotonic: adding - // notes can only keep an asset over-selected, never reverse it). - let mut n_outs = *n_outputs; - n_outs[2] = n_outs[2].saturating_add(zsa_change); - let t = n_inputs[0].max(n_outs[0]) as u64; - let s: u64 = if n_inputs[1] > 0 || n_outs[1] > 0 { - n_inputs[1].max(n_outs[1]).max(2) as u64 - } else { 0 }; - let o: u64 = if n_inputs[2] > 0 || n_outs[2] > 0 { - if migration { - (n_inputs[2] as u64 + n_outs[2] as u64).max(2) - } else { - n_inputs[2].max(n_outs[2]).max(2) as u64 - } - } else { 0 }; - let iw: u64 = if n_inputs[3] > 0 || n_outs[3] > 0 { - n_inputs[3].max(n_outs[3]).max(2) as u64 - } else { 0 }; - let logical = (t + s + o + iw).max(GRACE_ACTIONS); - logical * f_unit -} - /// Number of extra Orchard change outputs a ZSA transfer requires: one per /// non-ZEC asset (index ≥ 1) whose selected input sum exceeds the amount its /// recipient outputs consume. Each is a separate Orchard action the builder @@ -236,17 +193,13 @@ fn zsa_change_outputs(state: &State, ctx: &Context) -> u32 { /// Evaluate a state by trying every pool as the change absorber. /// Returns `(cost, best_change_pool)` if any pool yields a feasible /// solution, or `(u64::MAX, 0)` if none does. -/// In Fee mode cost is the ZIP-317 fee; in Privacy mode cost is the -/// cross-pool turnstile value. +/// Cost is the cross-pool turnstile value. fn evaluate(state: &State, ctx: &Context) -> (u64, u8) { - let (cost, pool) = match ctx.mode { - Mode::Fee => evaluate_fee(state, ctx), - Mode::Privacy => evaluate_privacy(state, ctx), - }; + let (cost, pool) = evaluate_privacy(state, ctx); if cost == u64::MAX { - info!("evaluate: mode={:?}, asset_sums[0]={}, INFEASIBLE", ctx.mode, state.asset_sums[0]); + info!("evaluate: asset_sums[0]={}, INFEASIBLE", state.asset_sums[0]); } else { - info!("evaluate: mode={:?}, asset_sums[0]={}, fee/cost={}, change_pool={}", ctx.mode, state.asset_sums[0], cost, pool); + info!("evaluate: asset_sums[0]={}, privacy_cost={}, change_pool={}", state.asset_sums[0], cost, pool); } (cost, pool) } @@ -273,43 +226,36 @@ fn is_feasible(state: &State, ctx: &Context, fee: u64) -> bool { true } -/// Fee-mode evaluation: return the lowest fee achievable by assigning -/// change to any pool. -fn evaluate_fee(state: &State, ctx: &Context) -> (u64, u8) { - let mut best_fee = u64::MAX; - let mut best_pool = 0u8; - let zsa_change = zsa_change_outputs(state, ctx); - - for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); - - if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { - info!( - "evaluate_fee: cp={} SKIP — fee({}) > first_recipient_amount({})", - cp, fee, ctx.first_recipient_amount - ); - continue; - } - - let feasible = is_feasible(state, ctx, fee); - info!( - "evaluate_fee: cp={} fee={} asset_sums[0]={} feasible={} best_fee={}", - cp, fee, state.asset_sums[0], feasible, best_fee - ); +fn fee_for_change_pool(state: &State, ctx: &Context, change_pool: u8) -> u64 { + compute_fee( + &state.n_inputs, + &ctx.n_outputs, + change_pool, + ctx.f_unit, + ctx.migration, + zsa_change_outputs(state, ctx), + ) +} - if feasible && fee < best_fee { - best_fee = fee; - best_pool = cp; - } - } +fn is_better_solution( + cost: u64, + fee: u64, + best_cost: u64, + best_fee: u64, +) -> bool { + (cost, fee) < (best_cost, best_fee) +} - (best_fee, best_pool) +fn bound_can_beat(bound: u64, best_cost: u64) -> bool { + // An equal privacy bound can still produce a lower-fee solution. + bound <= best_cost } -/// Privacy-mode evaluation: return the lowest turnstile achievable by -/// assigning change to any pool, with fee feasibility as a constraint. +/// Return the lowest turnstile achievable by assigning change to any pool, +/// using fee as a tie-breaker. fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { let mut best_turnstile = u64::MAX; + let mut best_fee = u64::MAX; let mut best_pool = 0u8; let zsa_change = zsa_change_outputs(state, ctx); @@ -347,8 +293,9 @@ fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { adjusted }).sum::(); - if turnstile < best_turnstile { + if (turnstile, fee) < (best_turnstile, best_fee) { best_turnstile = turnstile; + best_fee = fee; best_pool = cp; } } @@ -358,45 +305,10 @@ fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { /// Optimistic lower bound on the cost achievable by extending `state`. fn lower_bound(state: &State, ctx: &Context) -> u64 { - match ctx.mode { - Mode::Fee => lower_bound_fee(state, ctx), - Mode::Privacy => lower_bound_privacy(state, ctx), - } + lower_bound_privacy(state, ctx) } -/// Fee-mode lower bound: the minimum fee across all change-pool -/// assignments. Because fee is monotonic non-decreasing as notes are -/// added, the current minimum fee is always a valid bound. -fn lower_bound_fee(state: &State, ctx: &Context) -> u64 { - let mut min_fee = u64::MAX; - let zsa_change = zsa_change_outputs(state, ctx); - for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); - if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { - continue; - } - // Only consider fees that could be feasible given current ZEC sum - let zec_needed = if ctx.recipient_pays_fee { - ctx.asset_output_amounts[0] - } else { - ctx.asset_output_amounts[0].saturating_add(fee) - }; - if state.asset_sums[0] < zec_needed { - continue; - } - if fee < min_fee { - min_fee = fee; - } - } - // Also try compute_min_fee (no ZEC change output) as a tighter bound - let min_no_change = compute_min_fee(&state.n_inputs, &ctx.n_outputs, ctx.f_unit, ctx.migration, zsa_change); - if min_no_change < min_fee { - min_fee = min_no_change; - } - min_fee -} - -/// Privacy-mode lower bound: tin + tout is monotonic; per-pool +/// Privacy lower bound: tin + tout is monotonic; per-pool /// |balance| can only shrink by at most the sum of remaining note /// values in that pool. So we subtract the remaining pool value from /// each pool's absolute balance to get an optimistic floor. @@ -427,7 +339,7 @@ fn lower_bound_privacy(state: &State, ctx: &Context) -> u64 { fn initial_state(ctx: &Context) -> State { let mut balance = [0i64; N_POOLS]; - // Seed balance with negative output amounts so Privacy-mode (if + // Seed balance with negative output amounts so privacy optimization (if // re-added later) can compute per-pool imbalance. for p in 0..N_POOLS { balance[p] = -(ctx.output_amounts[p] as i64); @@ -477,29 +389,20 @@ fn remaining_notes<'a>(ctx: &Context<'a>, state: &State) -> Vec<(usize, &'a Note // --------------------------------------------------------------------- /// Score a candidate note for beam expansion. Higher = expand first. -fn local_score(note: &Note, state: &State, mode: Mode) -> i64 { - match mode { - Mode::Fee => { - // Larger notes first — fewer notes means fewer inputs, lower fee. - note.amount as i64 - } - Mode::Privacy => { - // Prefer notes that reduce a pool's imbalance toward zero. - let bal = state.balance[note.pool as usize]; - let old_abs = bal.unsigned_abs() as i64; - let new_abs = (bal + note.amount as i64).unsigned_abs() as i64; - let reduction = old_abs - new_abs; - // Light penalty on note size so smaller, more precise notes - // are preferred when equally corrective. - reduction - (note.amount as i64 / 1000) - } - } +fn local_score(note: &Note, state: &State) -> i64 { + // Prefer notes that reduce a pool's imbalance toward zero. + let bal = state.balance[note.pool as usize]; + let old_abs = bal.unsigned_abs() as i64; + let new_abs = (bal + note.amount as i64).unsigned_abs() as i64; + let reduction = old_abs - new_abs; + // Light penalty on note size so smaller, more precise notes + // are preferred when equally corrective. + reduction - (note.amount as i64 / 1000) } fn top_k_by_local_heuristic<'a>( remaining: &[(usize, &'a Note)], state: &State, - mode: Mode, k: usize, ) -> Vec<(usize, &'a Note)> { if remaining.len() <= k { @@ -507,7 +410,7 @@ fn top_k_by_local_heuristic<'a>( } let mut scored: Vec<(i64, usize, &Note)> = remaining .iter() - .map(|&(idx, n)| (local_score(n, state, mode), idx, n)) + .map(|&(idx, n)| (local_score(n, state), idx, n)) .collect(); scored.sort_by(|a, b| b.0.cmp(&a.0)); // descending scored.into_iter().take(k).map(|(_, idx, n)| (idx, n)).collect() @@ -596,7 +499,7 @@ impl Ord for QueueItem { // Public entry point // --------------------------------------------------------------------- -/// Select notes to cover `outputs`, minimizing the cost given by `mode`. +/// Select notes to cover `outputs`, minimizing privacy cost and then fee. /// /// `f_unit` is `COST_PER_ACTION` (5000). Notes with `amount < f_unit` are /// filtered out — they can never pay for their own marginal fee. @@ -611,14 +514,13 @@ pub(super) fn select_notes( migration: bool, recipient_pays_fee: bool, first_recipient_amount: u64, - mode: Mode, ) -> Option { // ---- 1. Pre-filter dust ------------------------------------------------ let total_notes = notes.len(); let total_input_sum: u64 = notes.iter().map(|n| n.amount).sum(); info!( - "select_notes: {} notes total, sum={} zats, outputs={}, f_unit={}, migration={}, recipient_pays_fee={}, first_recipient={}, mode={:?}", - total_notes, total_input_sum, outputs.len(), f_unit, migration, recipient_pays_fee, first_recipient_amount, mode + "select_notes: {} notes total, sum={} zats, outputs={}, f_unit={}, migration={}, recipient_pays_fee={}, first_recipient={}", + total_notes, total_input_sum, outputs.len(), f_unit, migration, recipient_pays_fee, first_recipient_amount ); let filtered: Vec = notes .iter() @@ -679,7 +581,6 @@ pub(super) fn select_notes( migration, recipient_pays_fee, first_recipient_amount, - mode, }; // ---- 5. Greedy baseline ----------------------------------------------- @@ -721,6 +622,7 @@ pub(super) fn select_notes( (state, cost, pool) } }; + let mut best_fee = fee_for_change_pool(&best_state, &ctx, best_pool); let budget = Budget::default(); let mut tracker = BudgetTracker::new(&budget); @@ -731,12 +633,10 @@ pub(super) fn select_notes( // ---- 6. Initialize search --------------------------------------------- let start = initial_state(&ctx); let start_bound = lower_bound(&start, &ctx); - if start_bound < best_cost { + if bound_can_beat(start_bound, best_cost) { heap.push(Reverse(QueueItem { bound: start_bound, seq, state: start })); } - let monotonic = matches!(ctx.mode, Mode::Fee); - // ---- 7. Best-first branch-and-bound ----------------------------------- while let Some(Reverse(item)) = heap.pop() { if tracker.exceeded() { @@ -745,20 +645,20 @@ pub(super) fn select_notes( let QueueItem { bound, state, .. } = item; - if bound >= best_cost { + if !bound_can_beat(bound, best_cost) { continue; // cannot beat incumbent } // Feasibility check: evaluate with change-pool folding let (cost, pool) = evaluate(&state, &ctx); - if cost != u64::MAX && cost < best_cost { + let fee = fee_for_change_pool(&state, &ctx, pool); + if cost != u64::MAX + && is_better_solution(cost, fee, best_cost, best_fee) + { best_cost = cost; + best_fee = fee; best_state = state.clone(); best_pool = pool; - if monotonic { - // Fee is monotonic: supersets can only have >= cost - continue; - } // Privacy is non-monotonic: supersets may improve balance, // so don't prune — keep expanding this state. } @@ -775,14 +675,14 @@ pub(super) fn select_notes( continue; } - let candidates = top_k_by_local_heuristic(&remaining, &state, ctx.mode, budget.beam_width); + let candidates = top_k_by_local_heuristic(&remaining, &state, budget.beam_width); for (note_idx, note) in candidates { let child = apply(&state, note_idx, note); let child_bound = lower_bound(&child, &ctx); - if child_bound >= best_cost { + if !bound_can_beat(child_bound, best_cost) { continue; } @@ -800,30 +700,10 @@ pub(super) fn select_notes( } // ---- 8. Build Selection ------------------------------------------------ - // Recompute the actual fee for the best state (needed even in Privacy - // mode: the Selection always reports the ZIP-317 fee, not turnstile). - let (actual_fee, _) = evaluate_fee(&best_state, &ctx); - // If evaluate_fee returned u64::MAX (shouldn't happen since best_state - // was feasible), fall back to computing fee for the recorded best_pool. - let fee = if actual_fee != u64::MAX { - actual_fee - } else { - compute_fee( - &best_state.n_inputs, - &ctx.n_outputs, - best_pool, - ctx.f_unit, - ctx.migration, - zsa_change_outputs(&best_state, &ctx), - ) - }; - - let change_needed = if recipient_pays_fee { - ctx.asset_output_amounts[0] - } else { - ctx.asset_output_amounts[0].saturating_add(fee) - }; - let change_amount = best_state.asset_sums[0].saturating_sub(change_needed); + // `best_fee` is the fee for `best_pool`. Recomputing + // the globally cheapest change pool here could silently replace the + // privacy-optimal pool with a less-private one. + let fee = best_fee; // Gather inputs and per-pool indices let inputs: Vec = best_state.selected.iter().map(|&idx| ctx.notes[idx].clone()).collect(); @@ -838,7 +718,6 @@ pub(super) fn select_notes( inputs, per_pool_indices, change_pool: best_pool, - change_amount, fee, }) } @@ -870,7 +749,7 @@ mod tests { let f_unit = 5_000u64; - let sel = select_notes(¬es, &outputs, f_unit, false, false, 0, Mode::Fee) + let sel = select_notes(¬es, &outputs, f_unit, false, false, 0) .expect("should find a feasible selection"); // Total input >= total output + fee @@ -882,13 +761,6 @@ mod tests { total_input, total_output, sel.fee ); - // Change = total input - total output - fee - assert_eq!( - sel.change_amount, - total_input - total_output - sel.fee, - "change amount should balance" - ); - // Fee should be positive assert!(sel.fee > 0, "fee should be positive for non-empty outputs"); @@ -907,7 +779,7 @@ mod tests { let outputs = vec![Output { pool: 2, amount: 500_000, asset_index: 0 }]; let f_unit = 5_000u64; - let sel = select_notes(¬es, &outputs, f_unit, false, false, 0, Mode::Fee) + let sel = select_notes(¬es, &outputs, f_unit, false, false, 0) .expect("should find a feasible selection"); // Should only use the non-dust note @@ -926,18 +798,13 @@ mod tests { let f_unit = 5_000u64; // First recipient has 200_000, fee will be well under that - let sel = select_notes(¬es, &outputs, f_unit, false, true, 200_000, Mode::Fee) + let sel = select_notes(¬es, &outputs, f_unit, false, true, 200_000) .expect("should find a feasible selection"); // With recipient_pays_fee, target = output_sum (no fee added) let total_input: u64 = sel.inputs.iter().map(|n| n.amount).sum(); let total_output: u64 = outputs.iter().map(|o| o.amount).sum(); - // Change = total_input - total_output (fee comes from recipient) - assert_eq!( - sel.change_amount, - total_input - total_output, - "change = inputs - outputs when recipient pays fee" - ); + assert!(total_input >= total_output); assert!(sel.fee <= 200_000, "fee must not exceed first recipient amount"); } @@ -953,7 +820,7 @@ mod tests { let f_unit = 5_000u64; // First recipient only has 1_000 zats — fee will exceed that - let result = select_notes(¬es, &outputs, f_unit, false, true, 1_000, Mode::Fee); + let result = select_notes(¬es, &outputs, f_unit, false, true, 1_000); // Should still work if it can find a change pool where fee <= 1000, // but with 4 pools and enough notes the min fee is >= 10000. // This may or may not find a solution depending on fee structure. @@ -971,7 +838,7 @@ mod tests { let outputs = vec![Output { pool: 2, amount: 1_000_000, asset_index: 0 }]; let f_unit = 5_000u64; - let result = select_notes(¬es, &outputs, f_unit, false, false, 0, Mode::Fee); + let result = select_notes(¬es, &outputs, f_unit, false, false, 0); assert!(result.is_none(), "should return None for insufficient funds"); } @@ -1022,7 +889,6 @@ mod tests { migration: false, recipient_pays_fee: false, first_recipient_amount: 0, - mode: Mode::Fee, }; let state = |sums: Vec| State { asset_sums: sums, @@ -1039,4 +905,41 @@ mod tests { // Both exactly funded → no ZSA change. assert_eq!(zsa_change_outputs(&state(vec![0, 500_000, 300_000]), &ctx), 0); } + + #[test] + fn test_privacy_uses_fee_to_break_change_pool_tie() { + let ctx = Context { + notes: &[], + n_assets: 1, + asset_output_amounts: vec![40_000], + output_amounts: [40_000, 0, 0, 0], + n_outputs: [2, 0, 0, 0], + f_unit: 5_000, + migration: false, + recipient_pays_fee: false, + first_recipient_amount: 0, + }; + let state = State { + asset_sums: vec![100_000], + balance: [-40_000, 20_000, 0, 0], + n_inputs: [2, 1, 0, 0], + tin: 80_000, + tout: 40_000, + selected: vec![], + }; + + // Transparent and Sapling change both have turnstile 140_000. + // Sapling change costs 20_000, versus 25_000 for transparent. + let (turnstile, change_pool) = evaluate_privacy(&state, &ctx); + assert_eq!(turnstile, 140_000); + assert_eq!(change_pool, 1); + assert_eq!(fee_for_change_pool(&state, &ctx, change_pool), 20_000); + } + + #[test] + fn test_equal_privacy_bound_can_improve_fee() { + assert!(bound_can_beat(100, 100)); + assert!(is_better_solution(100, 10, 100, 20)); + assert!(!is_better_solution(101, 5, 100, 20)); + } } diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 5b76aa4b2..4d84d6391 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -191,7 +191,6 @@ async fn test_orchard_transfer() { recipient_pays_fee: false, smart_transparent: false, category: None, - mode: 0, }; println!("Planning O2O transfer of {send_amount} zats..."); @@ -578,7 +577,6 @@ async fn test_zsa_transfer() { recipient_pays_fee: false, smart_transparent: false, category: None, - mode: 0, }; let pczt = rlz::api::pay::prepare(&[pay_recipient], options, &sender) From bebc3a5075171800f22cc95ec6b137376168bf4c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 23:17:04 +0200 Subject: [PATCH 023/189] fix: finalize new ZSA issuance --- lib/pages/zsa.dart | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/lib/pages/zsa.dart b/lib/pages/zsa.dart index e585e8717..4172a237e 100644 --- a/lib/pages/zsa.dart +++ b/lib/pages/zsa.dart @@ -243,8 +243,6 @@ class _IssueAssetPageState extends ConsumerState { key: _formKey, initialValue: { "asset_name": name, - "first_issuance": reissuance ? false : false, - "finalize": false, }, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -273,18 +271,6 @@ class _IssueAssetPageState extends ConsumerState { }, ]), ), - const Gap(16), - FormBuilderSwitch( - name: "first_issuance", - title: const Text("First Issuance"), - subtitle: const Text("Include a zero-value reference note (ZIP-227)"), - enabled: !reissuance, - ), - FormBuilderSwitch( - name: "finalize", - title: const Text("Finalize"), - subtitle: const Text("Prevent any future issuance of this asset"), - ), ], ), ), @@ -298,14 +284,12 @@ class _IssueAssetPageState extends ConsumerState { final assetName = form.value["asset_name"] as String; final amount = form.value["amount"] as String; - final firstIssuance = _isReissuance ? false : form.value["first_issuance"] as bool; - final finalize = form.value["finalize"] as bool; final label = _isReissuance ? "more " : ""; final confirmed = await confirmDialog( context, title: "Issue $assetName", - message: "Issue $amount ${label}units of $assetName?${finalize ? ' This will finalize the asset.' : ''}", + message: "Issue $amount ${label}units of $assetName? This will finalize the asset.", ); if (!confirmed) return; @@ -319,8 +303,8 @@ class _IssueAssetPageState extends ConsumerState { final txBytes = await issueAsset( assetName: assetName, amount: BigInt.parse(amount), - firstIssuance: firstIssuance, - finalize: finalize, + firstIssuance: true, + finalize: true, descHash: _descHash, idAccount: coinContext.coin.account, c: coinContext.coin, From a611410b7b89091e8d0c33d687d5e2509539f5e3 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 26 Jul 2026 23:50:08 +0200 Subject: [PATCH 024/189] fix: retain ZSA notes below ZEC dust threshold --- rust/src/pay/plan.rs | 9 +++++++-- rust/src/pay/solve.rs | 28 ++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index b1c80b4c5..887322ad4 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -357,10 +357,15 @@ pub async fn plan_transaction( .fetch_one(&mut *connection) .await?; - // Remove dust notes (too small to pay for a single logical action) + // Remove ZEC dust notes (too small to pay for a single logical action). + // ZSA amounts are denominated in their own asset and cannot pay fees, so + // comparing them against the zatoshi fee threshold is meaningless. let before_dust: [usize; NUM_POOLS] = std::array::from_fn(|p| input_pools[p].len()); for pool in input_pools.iter_mut() { - pool.retain(|n| n.amount >= COST_PER_ACTION); + pool.retain(|n| { + let is_zec = n.asset_base.is_empty() || n.asset_base.iter().all(|&byte| byte == 0); + !is_zec || n.amount >= COST_PER_ACTION + }); } info!( "plan: after dust filter — t:{}→{}, s:{}→{}, o:{}→{}, iw:{}→{}", diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 070ea3096..2989c184a 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -501,8 +501,10 @@ impl Ord for QueueItem { /// Select notes to cover `outputs`, minimizing privacy cost and then fee. /// -/// `f_unit` is `COST_PER_ACTION` (5000). Notes with `amount < f_unit` are -/// filtered out — they can never pay for their own marginal fee. +/// `f_unit` is `COST_PER_ACTION` (5000). ZEC notes with `amount < f_unit` +/// are filtered out because they can never pay for their own marginal fee. +/// ZSA notes are retained because their amounts are not denominated in +/// zatoshis and cannot pay transaction fees. /// /// Returns `None` when the available notes cannot cover the outputs plus /// the required fee (or when `recipient_pays_fee` and the fee exceeds @@ -524,11 +526,11 @@ pub(super) fn select_notes( ); let filtered: Vec = notes .iter() - .filter(|n| n.amount >= f_unit) + .filter(|n| n.asset_index != 0 || n.amount >= f_unit) .cloned() .collect(); info!( - "select_notes: after dust filter (>= {}): {} notes (removed {})", + "select_notes: after ZEC dust filter (< {}): {} notes (removed {})", f_unit, filtered.len(), total_notes - filtered.len() @@ -787,6 +789,24 @@ mod tests { assert_eq!(sel.inputs[0].pool, 2); } + #[test] + fn test_zsa_note_below_fee_unit_is_not_dust() { + let notes = vec![ + Note { pool: 2, amount: 1, pool_index: 0, asset_index: 1 }, + Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, + ]; + let outputs = vec![Output { pool: 2, amount: 1, asset_index: 1 }]; + + let sel = select_notes(¬es, &outputs, 5_000, false, false, 0) + .expect("sub-fee-unit ZSA note should remain selectable"); + + assert!( + sel.inputs + .iter() + .any(|note| note.asset_index == 1 && note.amount == 1) + ); + } + #[test] fn test_select_notes_recipient_pays_fee() { let notes = vec![ From 6550ad760faeb98e82231e46ba58abdc365d43da Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 27 Jul 2026 00:13:40 +0200 Subject: [PATCH 025/189] fix: hide ZSA reissuance flow --- lib/pages/account.dart | 9 --------- lib/pages/zsa.dart | 8 -------- 2 files changed, 17 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 3fc732d4e..5f8806e04 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -17,7 +17,6 @@ import 'package:searchable_listview/searchable_listview.dart'; import 'package:zkool/main.dart'; import 'package:zkool/pages/tx.dart'; -import 'package:zkool/pages/zsa.dart'; import 'package:zkool/router.dart'; import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/sync.dart'; @@ -512,14 +511,6 @@ class AccountViewPageState extends ConsumerState with SingleTic children: [ Expanded( child: ListTile( - onTap: () => GoRouter.of(context).push( - "/zsa/issue", - extra: IssuanceArgs( - assetName: displayName, - isReissuance: true, - assetDescHash: h.assetDescHash, - ), - ), leading: CircleAvatar( backgroundColor: Colors.blue, child: Text( diff --git a/lib/pages/zsa.dart b/lib/pages/zsa.dart index 4172a237e..8c0fa123d 100644 --- a/lib/pages/zsa.dart +++ b/lib/pages/zsa.dart @@ -155,14 +155,6 @@ class _ZsaHoldingsPageState extends ConsumerState { children: [ Expanded( child: ListTile( - onTap: () => GoRouter.of(context).push( - "/zsa/issue", - extra: IssuanceArgs( - assetName: displayName, - isReissuance: true, - assetDescHash: h.assetDescHash, - ), - ), leading: CircleAvatar( backgroundColor: Colors.blue, child: Text( From 90a02867f7517d89263ef0d3e34229f0dd87a08f Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 27 Jul 2026 18:45:38 +0200 Subject: [PATCH 026/189] fix: correct ZSA action fees and transaction summaries --- rust/src/pay/mod.rs | 20 ++++-- rust/src/pay/solve.rs | 161 +++++++++++++++++++++++++----------------- 2 files changed, 111 insertions(+), 70 deletions(-) diff --git a/rust/src/pay/mod.rs b/rust/src/pay/mod.rs index c3c5eee1b..1a7ca33ce 100644 --- a/rust/src/pay/mod.rs +++ b/rust/src/pay/mod.rs @@ -151,15 +151,21 @@ fn append_orchard_plan( fee: &mut i64, ) -> Result<()> { for action in bundle.actions() { - let input_asset_name = - orchard_asset_name(action.spend().proprietary(), action.spend().asset()); let output_asset_name = orchard_asset_name(action.output().proprietary(), action.output().asset()); - inputs.push(TxPlanIn { - pool: 2, - amount: action.spend().value().map(|value| value.inner()), - asset_name: input_asset_name, - }); + // A ZIP-226 split spend is a proof-level padding action derived from + // an existing ZSA note, not another wallet input. Showing it here + // duplicates the source note in the human-readable transaction plan. + if action.spend().rseed_split_note().is_none() { + inputs.push(TxPlanIn { + pool: 2, + amount: action.spend().value().map(|value| value.inner()), + asset_name: orchard_asset_name( + action.spend().proprietary(), + action.spend().asset(), + ), + }); + } outputs.push(TxPlanOut { pool: 2, amount: action diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 2989c184a..1a4ec4f3e 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -74,6 +74,9 @@ struct State { balance: [i64; N_POOLS], /// Number of inputs selected per pool. Drives the fee computation. n_inputs: [u32; N_POOLS], + /// Number of Orchard inputs selected per asset. ZSA Orchard actions must + /// pair spends and outputs within the same asset. + orchard_asset_inputs: Vec, /// Transparent input value (zats). tin: u64, /// Transparent output value (zats). Fixed once from Context. @@ -89,6 +92,7 @@ struct Context<'a> { asset_output_amounts: Vec, // required output amount per asset (index 0 = ZEC) output_amounts: [u64; N_POOLS], // output value per pool (zats) n_outputs: [u32; N_POOLS], // number of fixed recipient outputs per pool + orchard_asset_outputs: Vec, // fixed Orchard recipient outputs per asset f_unit: u64, // COST_PER_ACTION (5000) migration: bool, // orchard fee = inputs+outputs instead of max recipient_pays_fee: bool, @@ -134,17 +138,19 @@ impl BudgetTracker { /// ZIP-317 fee for a state, assuming change is assigned to `change_pool`. /// -/// `zsa_change` is the number of *additional* Orchard change outputs the -/// transaction will carry — one per non-ZEC asset whose selected inputs -/// exceed what its recipients consume. These are distinct Orchard actions -/// (ZSA notes aren't fungible with ZEC or each other), so they must be -/// priced in or the planner underestimates the fee and the builder rejects -/// the transaction for insufficient funds. See `zsa_change_outputs`. -fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_pool: u8, f_unit: u64, migration: bool, zsa_change: u32) -> u64 { +/// `orchard_actions` overrides the ordinary global input/output maximum for +/// ZSA bundles, whose spends and outputs must instead be paired per asset. +fn compute_fee( + n_inputs: &[u32; N_POOLS], + n_outputs: &[u32; N_POOLS], + change_pool: u8, + f_unit: u64, + migration: bool, + orchard_actions: Option, +) -> u64 { let cp = change_pool as usize; let mut n_outs = *n_outputs; n_outs[cp] = n_outs[cp].saturating_add(1); // ZEC change output - n_outs[2] = n_outs[2].saturating_add(zsa_change); // ZSA change outputs (always Orchard) // Transparent: max(inputs, outputs), no padding let t = n_inputs[0].max(n_outs[0]) as u64; @@ -155,13 +161,17 @@ fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_poo } else { 0 }; // Orchard: migration? inputs+outputs : max(inputs,outputs); clamped to 2 - let o: u64 = if n_inputs[2] > 0 || n_outs[2] > 0 { - if migration { - (n_inputs[2] as u64 + n_outs[2] as u64).max(2) + let o: u64 = orchard_actions.unwrap_or_else(|| { + if n_inputs[2] > 0 || n_outs[2] > 0 { + if migration { + (n_inputs[2] as u64 + n_outs[2] as u64).max(2) + } else { + n_inputs[2].max(n_outs[2]).max(2) as u64 + } } else { - n_inputs[2].max(n_outs[2]).max(2) as u64 + 0 } - } else { 0 }; + }); // Ironwood: same as Orchard non-migration let iw: u64 = if n_inputs[3] > 0 || n_outs[3] > 0 { @@ -172,18 +182,27 @@ fn compute_fee(n_inputs: &[u32; N_POOLS], n_outputs: &[u32; N_POOLS], change_poo logical * f_unit } -/// Number of extra Orchard change outputs a ZSA transfer requires: one per -/// non-ZEC asset (index ≥ 1) whose selected input sum exceeds the amount its -/// recipient outputs consume. Each is a separate Orchard action the builder -/// emits, because ZSA notes aren't fungible with ZEC or with each other, so -/// the leftover of every asset needs its own change note. The fee model must -/// count these or it underprices the transaction (the builder computes its -/// fee from `max(orchard_spends, orchard_outputs)` including every change -/// note, so a missed change output = one unpriced 5000-zat action). -fn zsa_change_outputs(state: &State, ctx: &Context) -> u32 { - (1..ctx.n_assets as usize) - .filter(|&a| state.asset_sums[a] > ctx.asset_output_amounts[a]) - .count() as u32 +/// Orchard logical actions for a ZSA bundle. Spends and outputs can only be +/// paired when they carry the same asset, so the bundle costs the sum of +/// `max(spends, outputs)` for each asset rather than one global maximum. +fn zsa_orchard_actions(state: &State, ctx: &Context, change_pool: u8) -> Option { + if ctx.n_assets <= 1 { + return None; + } + + let actions = (0..ctx.n_assets as usize) + .map(|asset| { + let mut outputs = ctx.orchard_asset_outputs[asset]; + if asset == 0 && change_pool == 2 { + outputs = outputs.saturating_add(1); + } else if asset > 0 && state.asset_sums[asset] > ctx.asset_output_amounts[asset] { + outputs = outputs.saturating_add(1); + } + state.orchard_asset_inputs[asset].max(outputs) as u64 + }) + .sum::(); + + Some(if actions > 0 { actions.max(2) } else { 0 }) } // --------------------------------------------------------------------- @@ -233,7 +252,7 @@ fn fee_for_change_pool(state: &State, ctx: &Context, change_pool: u8) -> u64 { change_pool, ctx.f_unit, ctx.migration, - zsa_change_outputs(state, ctx), + zsa_orchard_actions(state, ctx, change_pool), ) } @@ -257,10 +276,8 @@ fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { let mut best_turnstile = u64::MAX; let mut best_fee = u64::MAX; let mut best_pool = 0u8; - let zsa_change = zsa_change_outputs(state, ctx); - for cp in 0..N_POOLS as u8 { - let fee = compute_fee(&state.n_inputs, &ctx.n_outputs, cp, ctx.f_unit, ctx.migration, zsa_change); + let fee = fee_for_change_pool(state, ctx, cp); if ctx.recipient_pays_fee && fee > ctx.first_recipient_amount { continue; @@ -348,6 +365,7 @@ fn initial_state(ctx: &Context) -> State { asset_sums: vec![0u64; ctx.n_assets as usize], balance, n_inputs: [0; N_POOLS], + orchard_asset_inputs: vec![0; ctx.n_assets as usize], tin: 0, tout: ctx.output_amounts[0], selected: Vec::new(), @@ -360,6 +378,10 @@ fn apply(state: &State, note_idx: usize, note: &Note) -> State { child.selected.push(note_idx); child.asset_sums[note.asset_index as usize] += note.amount; child.n_inputs[note.pool as usize] = child.n_inputs[note.pool as usize].saturating_add(1); + if note.pool == 2 { + child.orchard_asset_inputs[note.asset_index as usize] = + child.orchard_asset_inputs[note.asset_index as usize].saturating_add(1); + } match note.pool { 0 => { @@ -423,8 +445,8 @@ fn top_k_by_local_heuristic<'a>( /// Balances rounded to nearest QUANT zats to bound the `seen` map size. const QUANT: i64 = 1000; -type StateKey = (Vec, [i64; N_POOLS], u64, [u32; N_POOLS]); -// asset_sums(q) balance(q) tout n_inputs +type StateKey = (Vec, [i64; N_POOLS], u64, [u32; N_POOLS], Vec); +// asset_sums(q) balance(q) tout n_inputs Orchard inputs/asset fn state_key(state: &State) -> StateKey { let q = |b: i64| (b / QUANT) * QUANT; @@ -437,6 +459,7 @@ fn state_key(state: &State) -> StateKey { ], state.tout, state.n_inputs, + state.orchard_asset_inputs.clone(), ) } @@ -548,12 +571,17 @@ pub(super) fn select_notes( // Derive n_assets and per-asset output amounts from outputs let n_assets = outputs.iter().map(|o| o.asset_index).max().unwrap_or(0) + 1; let mut asset_output_amounts = vec![0u64; n_assets as usize]; + let mut orchard_asset_outputs = vec![0u32; n_assets as usize]; for o in outputs { let p = o.pool as usize; if p < N_POOLS { output_amounts[p] = output_amounts[p].saturating_add(o.amount); n_outputs[p] = n_outputs[p].saturating_add(1); + if p == 2 { + orchard_asset_outputs[o.asset_index as usize] = + orchard_asset_outputs[o.asset_index as usize].saturating_add(1); + } } output_sum = output_sum.saturating_add(o.amount); asset_output_amounts[o.asset_index as usize] += o.amount; @@ -579,6 +607,7 @@ pub(super) fn select_notes( asset_output_amounts, output_amounts, n_outputs, + orchard_asset_outputs, f_unit, migration, recipient_pays_fee, @@ -872,7 +901,7 @@ mod tests { // Total logical = max(2+3,2) = 5, fee = 25000 let n_inputs: [u32; 4] = [0, 2, 1, 0]; let n_outputs: [u32; 4] = [0, 1, 2, 0]; - let fee = compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 0); + let fee = compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, None); // With change in pool 2: n_outputs[2] becomes 3 // Sapling: max(2,1,2) = 2 // Orchard: max(1,3,2) = 3 @@ -881,49 +910,53 @@ mod tests { } #[test] - fn test_compute_fee_counts_zsa_change() { - // Reproduces the O2O ZSA transfer that under-priced by one action: - // spend 1 ZEC note + 1 asset note (2 Orchard inputs), send part of the - // asset to a recipient (1 Orchard output). The wallet then needs a ZEC - // change note *and* an asset change note (the asset was over-selected). - let n_inputs: [u32; 4] = [0, 0, 2, 0]; - let n_outputs: [u32; 4] = [0, 0, 1, 0]; // recipient only - // Without counting the ZSA change note the planner saw - // Orchard outputs = recipient(1) + ZEC change(1) = 2 → max(2,2)=2 → 10000 - assert_eq!(compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 0), 10_000); - // Counting the asset change note the builder actually emits - // Orchard outputs = recipient(1) + ZEC change(1) + asset change(1) = 3 - // → max(2,3)=3 → 15000, matching the builder and closing the 5000 gap. - assert_eq!(compute_fee(&n_inputs, &n_outputs, 2, 5_000, false, 1), 15_000); - } - - #[test] - fn test_zsa_change_outputs_counts_over_selected_assets() { + fn test_zsa_fee_counts_orchard_actions_per_asset() { + // Two ZEC spends and one ZSA spend cannot be paired globally with one + // ZEC change and two ZSA outputs. ZEC requires 2 actions and the ZSA + // requires 2 more, for a total fee of 4 actions rather than 3. let ctx = Context { notes: &[], - n_assets: 3, // ZEC + 2 ZSA assets - asset_output_amounts: vec![0, 500_000, 300_000], - output_amounts: [0; N_POOLS], - n_outputs: [0; N_POOLS], + n_assets: 2, + asset_output_amounts: vec![0, 1_000], + output_amounts: [0, 0, 1_000, 0], + n_outputs: [0, 0, 1, 0], + orchard_asset_outputs: vec![0, 1], f_unit: 5_000, migration: false, recipient_pays_fee: false, first_recipient_amount: 0, }; - let state = |sums: Vec| State { - asset_sums: sums, + let state = State { + asset_sums: vec![200_000_000, 499_500], balance: [0; N_POOLS], - n_inputs: [0; N_POOLS], + n_inputs: [0, 0, 3, 0], + orchard_asset_inputs: vec![2, 1], tin: 0, tout: 0, selected: vec![], }; - // Asset 1 exactly funded, asset 2 over-selected → 1 change note. - assert_eq!(zsa_change_outputs(&state(vec![0, 500_000, 400_000]), &ctx), 1); - // Both assets over-selected → 2 change notes. - assert_eq!(zsa_change_outputs(&state(vec![0, 600_000, 400_000]), &ctx), 2); - // Both exactly funded → no ZSA change. - assert_eq!(zsa_change_outputs(&state(vec![0, 500_000, 300_000]), &ctx), 0); + + assert_eq!(zsa_orchard_actions(&state, &ctx, 2), Some(4)); + assert_eq!(fee_for_change_pool(&state, &ctx, 2), 20_000); + } + + #[test] + fn test_zsa_selection_uses_per_asset_fee_as_tiebreaker() { + let notes = vec![ + Note { pool: 2, amount: 20_082_510_000, pool_index: 0, asset_index: 0 }, + Note { pool: 2, amount: 200_000_000, pool_index: 1, asset_index: 0 }, + Note { pool: 2, amount: 499_500, pool_index: 2, asset_index: 1 }, + ]; + let outputs = vec![Output { pool: 2, amount: 1_000, asset_index: 1 }]; + + let selection = select_notes(¬es, &outputs, 5_000, false, false, 0) + .expect("ZSA transfer should be selectable"); + + // One ZEC spend pairs with ZEC change. The ZSA spend needs one + // recipient output and one asset-change output, so it costs two more + // actions: 3 actions total. + assert_eq!(selection.inputs.len(), 2); + assert_eq!(selection.fee, 15_000); } #[test] @@ -934,6 +967,7 @@ mod tests { asset_output_amounts: vec![40_000], output_amounts: [40_000, 0, 0, 0], n_outputs: [2, 0, 0, 0], + orchard_asset_outputs: vec![0], f_unit: 5_000, migration: false, recipient_pays_fee: false, @@ -943,6 +977,7 @@ mod tests { asset_sums: vec![100_000], balance: [-40_000, 20_000, 0, 0], n_inputs: [2, 1, 0, 0], + orchard_asset_inputs: vec![0], tin: 80_000, tout: 40_000, selected: vec![], From dc85dc947fa7b89e716db711645876dc05a66cf8 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 27 Jul 2026 21:28:53 +0200 Subject: [PATCH 027/189] chore: remove stale code and debug test --- lib/settings.dart | 2 +- lib/store.dart | 1 - rust/tests/parse_block_311.rs | 204 ---------------------------------- 3 files changed, 1 insertion(+), 206 deletions(-) delete mode 100644 rust/tests/parse_block_311.rs diff --git a/lib/settings.dart b/lib/settings.dart index 9695fdee7..70c7cfc68 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -873,7 +873,7 @@ class SettingsFormState extends ConsumerState { } else { prf = await authenticatePasskey(); } - if (prf != null && mounted) { + if (mounted) { await ref.read(vaultProvider.notifier).registerDevice( password: masterPassword!, prf: prf, diff --git a/lib/store.dart b/lib/store.dart index 7ce31d34c..a9f9d7316 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -22,7 +22,6 @@ import 'package:zkool/src/rust/api/network.dart'; import 'package:zkool/src/rust/api/plugin.dart' as plugin_api; import 'package:zkool/src/rust/api/sweep.dart'; import 'package:zkool/src/rust/api/sync.dart'; -import 'package:zkool/src/rust/api/migrate.dart'; import 'package:zkool/src/rust/api/zsa.dart'; import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; diff --git a/rust/tests/parse_block_311.rs b/rust/tests/parse_block_311.rs deleted file mode 100644 index 3d67c3764..000000000 --- a/rust/tests/parse_block_311.rs +++ /dev/null @@ -1,204 +0,0 @@ -// Parse block 311 using librustzcash deserialization -use std::io::Cursor; -use byteorder::{LittleEndian, ReadBytesExt}; -use zcash_primitives::transaction::Transaction; -use zcash_protocol::consensus::BranchId; - -#[test] -fn parse_block_311_with_zcash_primitives() { - let block_hex = std::fs::read_to_string("tests/block_311.hex").unwrap().trim().to_string(); - let block_bytes = hex::decode(block_hex).unwrap(); - println!("Total block bytes: {}", block_bytes.len()); - - let mut cursor = Cursor::new(block_bytes.as_slice()); - - // Block header: version(4) + prev_hash(32) + merkle_root(32) + final_sapling_root(32) + time(4) + bits(4) + nonce(32) = 140 - cursor.set_position(140); - println!("Byte at 140: 0x{:02x}", block_bytes[140]); - let solution_len = read_compact_size(&mut cursor); - println!("Solution len: {}", solution_len); - cursor.set_position(cursor.position() + solution_len as u64); - - // TX count - let tx_count = read_compact_size(&mut cursor); - println!("TX count: {}", tx_count); - - for tx_idx in 0..tx_count { - let tx_start = cursor.position() as usize; - let mut tx_slice = &block_bytes[tx_start..]; - - println!("\n=== TX {} at offset {} ===", tx_idx, tx_start); - - match Transaction::read(&mut tx_slice, BranchId::Nu7) { - Ok(tx) => { - let consumed = block_bytes.len() - tx_start - tx_slice.len(); - println!("✅ TX {} parsed successfully!", tx_idx); - println!(" Consumed: {} bytes", consumed); - println!(" txid: {}", tx.txid()); - - cursor.set_position((tx_start + consumed) as u64); - - if tx_idx == 1 { - let tx_data = tx.into_data(); - println!("\n --- Shield TX manual parse for byte positions ---"); - let tx_bytes = &block_bytes[tx_start..tx_start + consumed]; - - // We know from Rust: version=6, version_group_id=0x77777777 - // Let's manually walk through the binary to get exact positions - let mut pos = 0usize; - - // header (4) + version_group_id (4) + consensus_branch_id (4) + lock_time (4) + expiry_height (4) + zip233 (8) - pos += 4 + 4 + 4 + 4 + 4 + 8; // 28 - println!(" After header fields: pos={}", pos); - - // tx_in_count - let tx_in_count = read_compact_size_at(tx_bytes, &mut pos); - println!(" tx_in_count={} at pos_before={}", tx_in_count, pos - 1); - for i in 0..tx_in_count { - pos += 32 + 4; // prevout - let sl = read_compact_size_at(tx_bytes, &mut pos); - pos += sl + 4; // script + sequence - } - println!(" After tx_in: pos={}", pos); - - // tx_out_count - let tx_out_count = read_compact_size_at(tx_bytes, &mut pos); - println!(" tx_out_count={}", tx_out_count); - for _ in 0..tx_out_count { - pos += 8; // value - let sl = read_compact_size_at(tx_bytes, &mut pos); - pos += sl; // script - } - println!(" After tx_out: pos={}", pos); - - // sighash - let sighash_start = pos; - for _ in 0..tx_in_count { - let sl = read_compact_size_at(tx_bytes, &mut pos); - pos += sl; - } - println!(" Sighash: pos={} (consumed {} bytes)", pos, pos - sighash_start); - - // Sapling - let sapling_start = pos; - let spend_count = read_compact_size_at(tx_bytes, &mut pos); - println!(" nSpends: {} at {}", spend_count, pos-1); - for _ in 0..spend_count { pos += 32*4; } - let output_count = read_compact_size_at(tx_bytes, &mut pos); - println!(" nOutputs: {} at {}", output_count, pos-1); - for _ in 0..output_count { pos += 32*3 + 580 + 80; } - if spend_count+output_count > 0 { pos += 8; } - if spend_count > 0 { pos += 32; } - pos += spend_count * 192; - for _ in 0..spend_count { let sl = read_compact_size_at(tx_bytes, &mut pos); pos += sl + 64; } - pos += output_count * 192; - if spend_count+output_count > 0 { let sl = read_compact_size_at(tx_bytes, &mut pos); pos += sl + 64; } - println!(" Sapling end: pos={} (consumed {} bytes)", pos, pos - sapling_start); - - // Orchard - let orchard_start = pos; - let num_ag = read_compact_size_at(tx_bytes, &mut pos); - println!(" nActionGroups: {} at {}", num_ag, pos-1); - if num_ag == 1 { - let ac = read_compact_size_at(tx_bytes, &mut pos); - println!(" nActions: {} at {}", ac, pos-1); - println!(" Action start: pos={}", pos); - for i in 0..ac { - let a_start = pos; - pos += 32*5 + 612 + 80; - println!(" action[{}]: {} bytes ({} to {})", i, pos - a_start, a_start, pos); - } - let flags_pos = pos; - pos += 1; // flags - println!(" flags: pos={}", flags_pos); - let anchor_pos = pos; - pos += 32; // anchor - println!(" anchor: pos={}", anchor_pos); - let ag_pos = pos; - pos += 4; // nAGExpiryHeight - println!(" nAGExpiryHeight: pos={}", ag_pos); - let burn_pos = pos; - let bc = read_compact_size_at(tx_bytes, &mut pos); - println!(" burn count={} at {}", bc, burn_pos); - pos += bc * 40; - let proofs_pos = pos; - let pc = read_compact_size_at(tx_bytes, &mut pos); - println!(" proofs: len={} at {} (CompactSize byte at {})", pc, proofs_pos, proofs_pos); - pos += pc; - println!(" proofs end: pos={}", pos); - let sigs_pos = pos; - println!(" vSpendAuthSigs start: pos={}", sigs_pos); - for i in 0..ac { - let sl = read_compact_size_at(tx_bytes, &mut pos); - println!(" sig[{}]: CompactSize={} at pos {}", i, sl, pos-1); - pos += sl; - pos += 64; - println!(" sig[{}]: end pos {}", i, pos); - } - let vb_pos = pos; - pos += 8; // valueBalance - println!(" valueBalance: pos={}", vb_pos); - let bsig_pos = pos; - println!(" bindingSig START: pos={}", bsig_pos); - let bsl = read_compact_size_at(tx_bytes, &mut pos); - println!(" bindingSig CompactSize: {} at {}", bsl, pos-1); - pos += bsl; // sighash data - pos += 64; // sig - println!(" bindingSig END: pos={}", pos); - } - // Issue bundle - let issue_pos = pos; - let il = read_compact_size_at(tx_bytes, &mut pos); - println!(" issue bundle: issuer_len={} at {}", il, pos-1); - if il == 0 { - let na = read_compact_size_at(tx_bytes, &mut pos); - println!(" issue bundle: nActions={} at {}", na, pos-1); - } - println!(" issue bundle END: pos={}", pos); - let total = pos; - println!("\n === SUMMARY ==="); - println!(" Total parsed: {} bytes", total); - println!(" TX consumed: {} bytes", consumed); - println!(" Match: {}", total == consumed); - } - } - Err(e) => { - println!("❌ TX {} FAILED: {:?}", tx_idx, e); - println!(" First 100 bytes: {}", hex::encode(&tx_slice[..std::cmp::min(100, tx_slice.len())])); - panic!("Transaction::read failed for TX {}", tx_idx); - } - } - } - - let remaining = block_bytes.len() as u64 - cursor.position(); - println!("\n✅ All transactions parsed! Remaining bytes: {}", remaining); -} - -fn read_compact_size_at(data: &[u8], pos: &mut usize) -> usize { - let len_byte = data[*pos]; - *pos += 1; - match len_byte { - n if n < 253 => n as usize, - 253 => { - let val = u16::from_le_bytes([data[*pos], data[*pos+1]]) as usize; - *pos += 2; - val - } - 254 => { - let val = u32::from_le_bytes([data[*pos], data[*pos+1], data[*pos+2], data[*pos+3]]) as usize; - *pos += 4; - val - } - _ => panic!("bad compact size: {}", len_byte), - } -} - -fn read_compact_size(cursor: &mut Cursor<&[u8]>) -> usize { - let len_byte = cursor.read_u8().unwrap(); - match len_byte { - n if n < 253 => n as usize, - 253 => cursor.read_u16::().unwrap() as usize, - 254 => cursor.read_u32::().unwrap() as usize, - _ => panic!("bad compact size: {}", len_byte), - } -} From c4b1cef8761947fb9c2df4eadacee79ed989365b Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 27 Jul 2026 21:34:58 +0200 Subject: [PATCH 028/189] chore: update build number / release --- build_number.txt | 2 +- misc/ios.mobileprovision.enc | Bin 12304 -> 12304 bytes release-please-config.json | 3 --- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build_number.txt b/build_number.txt index dda3451cf..27a69f601 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -318 +327 diff --git a/misc/ios.mobileprovision.enc b/misc/ios.mobileprovision.enc index 9ab949a9d51396a39bde2eef71bbde3fe7d45a84..816851f42e2bef7d8ce506230db4d456e0a81dfb 100644 GIT binary patch literal 12304 zcmV+rFz?S(VQh3|WM5zJP?7w}tAx!>%sQYJxi~QXtZ!}|@wY{M5utq)kV)r~^s|f; zF=WAY;UYJK_-yYwg=Rw1kg&1xwU0e>LYLdOY9-5mkB}}^VL!zqEczfi5T~_IdhvuS zE1cu5(uSak$u1xbI3V!OSoLbeVfSubd{ag!!}}?1DhDNUyz3W7D$IwkbBr>h=`#vZ z<#dK0DC9ZY5R9OCm7?XJd*{wqa;{+>H zCMHabxe`a$*`bvlw)Y%|pDPxf5~MC1aw@k@pYu+_jSL<7GvSz%bg}-!t{_(FsN3e|4xy0Go8R0+#r}^6#ODpN z0*2apmOZ5X;+Y4zK?z*=Qic8BFd!O7YDRE+u$qGlZjMSRZrq!*oEE#}%-;)`Bkk?b z2PtIUw(QOVR$C_*0kydh73u^Y+j%Ake$DQ zAhI_n9sN6QB3)5#dI73;I@StJWZw&p=${PUrZIkud;r-^=?sG%I>l?HbPj^<3NyC$=sm-2aSQX|(xm{}y*U!ARq>O9( z`470cM02yrj9tz-1Gg@q=Q_%C+|j=DN$qDD9W%!#DYVUOf3n*X0eNhJ=htQMQ$pY6*D zX&b7dHdjkE?9KDj29_ZfI3b{xD8UrA-b9BE8iTggI=QjxQ>VkG9_UEES4GI2U!G@D z@f_krSgC5R2ZjNcPU|NWV`sv4S~+k-D4WJSGoPD^)7xO&T`@U{T}y8FMoNNtpaW7Q zYN%QXpD17D4K8C*R7Vdh6Wz$gO@Sw+RpH_k{Ql^%;5OMaeO`}G+PM1VPFPXoq`h(_ zK+ghHQ28;oZ95FIPv)j?xKFQxVNnDB$P?X`9rJ4&eaX0=SY|}_Lx0RMx5e>?A|S^7 z)i8ZgBYdAT4)D0LJGQcc>AjoB2pA-q!5Ox9x8VS-jeX@KkIUxPWh`JW*&@aIQsm1{AHhukKjhjG;HoTi8$d~ggUM^bhR!% zn4JMlH!1ln7f9Q%w}pO*b;s=D*tqFE4vxT)Od6i{cZ#T$YYW!=bI@Wv!R*W2{V~X$ zxL$SER~_fs8<3LE{(}j=sM8m@dSU6*5tLb<>Ib2@=327&k_J*GZZ zh{`X<)FYUUEk)cRIiP!tn&XVO>6M0=_LP$d@~iofmiLNOR7C->#>T;U$)Ugu6RIch z|CQHTAT{8RwAWSagK_;XsVN!08w*nq@bt3PXN_#`Qb>tyqjfKaFi87&T27Wu4P3RL zHRkXB)qIl=pl3prAwg-_7+jyQb?kDeN7q01Z1K8w!Hu@oq91r!G=5fs0?}+!%jw6= z%LeJ`Hff(c{lbRL3DAduRgut(NiBF@xa8XDq=toK7O0|?DVg(*;QJ!BLbp;NV**~H zhu|Doe-x{l zXFxXte1h+JmV1_5qX85rx$Xw9KQv|SKzCVqdnpu8VF9Ji#ozdt^1aIV>;?^g#JczQ zOwXN<5b^gHw8dc#IrdEUUp^66#3$n>n<xHA33r2%8+9g; zouc*>MH=xLx23pO``>Y30wNzlXWR4 zh4?{(i!wPq2@fs3PO|WTqKiteR%YLW%*NHY@vuUSFL5V?&-E$vyk3d>$JU*9PTCnf zZ*uy#VGbmrqpb`fnRR?K!kOS)r?=SkMD6Ir`3)JwNV-sPEgm+$Jr&pA{Nqw(Ry^hn z7z;|%;bG6jUWzPoud`6AY^Dk=-&Ss7R6sJa!xePGdJHh&?R%o`N+YYlBV6(+&2GPjxgPy@f0K-u%R<*uhU15sRsS!Y1zB9h!jauQHmBL|7I5 zUa#IS_mIPDdY%e*R-T)b4B}R{-yi@x)RWBcq`{` zLU9~UX8rqrdU9Id3*T~1IX$#Uj0EKo00=JG0YMH3aZnNVoFVd^wpI_N}@*$A3=x3km!Mcbkc#LL{w?(&wa%_4SlGz;qXwQ zH*?tnF^y@VL;lD!VRh{B9N&^EbeYu8s(9C92_GfqVI61I@p>YKO>B{q@!LiOlAR7V zF6cXF%xh46gJw(K*FLH;PLk3yVf<%k3K!=DE0&A3ear#K!s$PVnA9~lY9L-AZVp`8 zSg@F(Jhr;3FB`AcPRe)1cep1}B$}o*VU9geCQTT^uki{>{Y?#GE}sc&UH9$OF}kaM zR5~!y_`k@0JgR7o5Slkt19E3$B4 zs6>PVq|*9hPIsi#o7wp4xgEASSQUe*W`vZ_;g)4jj3M9`vX@{mtpDvWSBPjrM~|HG zo3*Yqme(C`9;oD{eiKw~N4Hf4c&KoKgKgj`yrWOhPJzJw=jg$|;*~Nego$#3s z9Uhi`sOuyn;tZQN6?}uol~`8?mbCT=h5;h#_wylyb%Rv2;*7<2 zhN~a97;81-0jHwFEH+yw=wN3kHi$9?zHOdwO*uPie#4ba8+Cw-?Zkk^iLdCpPWI=O zk6gh3s@^%P_%)U)qYVXpQUVt$o)-4*0el36F0G7Plc*QjIjQBqQrJ~ar7%~QsciEj zO_+9R2wkk7dxn*nCGVWt$Kj?P^V?(fIz~*tFj6>0cFc>oyW9m{66fQiC?zBbhQrVG zP6~jXJ0qU_)Uak1NAiNX5QGM)&`F~8zy_!@k@}9YNTNT&difgYF=G@dUJWkNhj+PxEe?%{shEuKX-73nVg@O-1#q@uZs?5j zAo3rBie5bU5Hu0j{~KU&>?*p;n=H^X6st3Khu}2H1KzJcC7oMZpg&z&Ie+IUO1AXG z)5zBS0CYK?0eVhsbXN2-1eh!wAmePpL_+()D!2i~S3)5vY?f);l$h%9;$sYUlxM>q3(NjqL6SCx2mc?b!V12RUkXT2O5(&3GAUnD3+`px ztjYsf4wH+;j{M?U;Jx&oC(iME2qk8HJ7pLvQ8p|Z7_Dzr^TyFm zVJ7lSfX05>pPwtIi@55$Pw}i}0geL6Cf()j&-?MQ^EL#Y0IpC1;Uj?fk4iUP0#dSA z{|*Fo#r}RUfd~}&c)O7jx1d$Net-R`i2QwzRH~+-!d2_pcHw$DKk-HLQZ|0E2OxvE zkh>zz_T%#E59v;)*=iArzEaY|!kOyobZQ-XOD;G)JF1h;hSc0KZmD!@kY`$3*ST$< z55-+@7u{Y2hs&B_;K+)(jWQQnB>+I!$|(tZRp9?(5e54h60nBRKnBA z%Q@KPvYVSvb(RO&$dRBw|7neaN8OC;RoagB6BEC{i7FDBHeE$c)kTs!7%C3yd{?Y= zUY&4b5#ug$WMeFLZm6RZ)4{{O3?b4grpttd)G<#tQ6mhO0oa9S0NndOJf>El~6*XMKD*-q}=crU&upIy;! zdok9T|C#F7^#dZ!ZwtpTJf+E@wNqt%+(_Jig46gzChru(f&MIr_BV*n9 ziELV#nQqoUUtWOT*0yfNiX8Q6)_(n8U>Q3^SH2;sRtu!@Z#lKyx+`&}yW7w@!_HF! zxpX%>e3~jnO29b?JqZZuY&9x~h(tAkk%JGfjF4e580Bu43m4%;L%jh!wd>kD!9Yv7 zO0p{hO4U%rl`HhKC=@f2I&O%M{F*=!tD;Y#Qoj^YuyZ z6)=T&PoPZxWnO9R;8D=RA^RBNFzJ@F>+9__n_9dmDbjDwcbDVpb}a_B>l7* z3b8^Z(kB}l3}{jdt=(xZt$*2q)gydo4=(xnbS;Zp7I;#GZ1@rNcL4V{3C&pj(x-gZ zMrSHOvwt7)EXJ3#`@2e&diVT-0;>rMKJ;=JZ<8RkCI`wM{TqyF<3nW&oro>DF{4f$ z+kP4-gtWxO==GVRqxk1@eV^90ZFEF>z;XcdS`z*|^I7YZZ7eCgOmQ%E9%i$}Hl-h_ zaqzKbAA-4l+ttBSpl3qDm1(I3W6vDL=!eXDk+%#-#{y-fK5fGL&Cp%h@YVEH6q8rK zzDCo!CU`~@By?sB3@jks)H!ypwRZ>7F`u!+%zSAg)>&=q!x9?OMEea>@Yy=#7nOZzFsI1oLY6z7+X3n5B z_h^=+i2YZ3o$HOsF8P2W@@pMVHhL~Nl_)nBejZy7_hf<*P6a@hX`gMQZE}lUo`Pa3 z$ypkidFn}p7ap1ZwJ1%PZfALA(?0Rg27KIj(8t|B1fui|@=97LFpv_9!u>ir6cB7P zdb>b}@0+aEz!(a>TCd^(7C1Iy*JC?Gp2FfJ@W~K_Zg{G>4%{BvindfB{ zCm1RYPQhvcr0A?(Xyo;ZmZ?3g`t&QMPicic*d$P_z4!m^`O%>5R>!^U!{_ zk%lX1C{T2o3rCQbt7Lj>Dw8E2jqT>c^Y!{G5Y6n(G-6kGSBR4$O~g)t+8O5$fz-9M z9u!Be*BZ1U9cp8Uq|DPFek{Y-_EZirdyhHg{baxv?cN_pI^um*($W>5&Mg6d^W>IC zD62vd4QtFt?P7sl#i z@aoz+eY9bF;3r@KhqbbSOT(>|2~ttdN3qtS@WN42A(F~9u*&lo zQsUCYo!b2tN1^g1xjBv5W72Ev$XFoQF&LiweVEX5R~m|!TR%?{YCz;tA5w7(1rRf4 znm#X6I>aRO4bXN-s=uoO-KxNEFe07V@OOye;0D{qm_guqc&x*_M=Dr1`H5@8GtLkv zE(HekFQzQ0xGSKwmKoqkEjMnj_m*9TA)OUn_ZYvCKq!VZe~YtvjehV!Pxs(jNmZ=w zZ%@SJ3a#Vl-Wjt!AdSOC&xSeQ!!bzQD46xsACjcJ*gCv&uRZmvp*QP%NBNXYZ0ptw zA9OGq><%%c;TSWx$5a0a2duqG1@}ANW8_CUstAm~%q!ML9*pF1xsWSqE5Ype9cPLZ zTVv=xy=AMx!;`47uXaFdtPxi>tU+}3E>pn{oXxlMA8yr}m60}}H;sd-@{yb<7Wyqf<|1vTx+rYc=(05{hS%UeIZHh9o$wtXHQ$kA|Kf>N?SdTQ74uJAp+t}4 zj5zWSbQ8L1Otrva%l+aS;gzbXD=3c9)&7EA3 zQ3qAlFY#yPVb&@oQc`ff9>4mQnI`0KSO{YBx!$iKM!*m6_{I3X|gHin^{q&IjWg z3l1vG!X-x65xcbrNI7cB0%IIcyVTA?_u~ng64xRfkkCFzg|6oB_0`;GO$)xbDKsIKqZAgkV|7MtsgnO<89)4Twj3fwa#&d!e6d)XX1Cgf8g4UL*oW z%g)eWg6sfjBojxdR!)LsaG>7wl^4Y^$xP@_0&)@}e^>hg2KAU+1#HaL3GU-pzVy@W8Gy4P3REV4o zp8=1n!9hg}N?!?uB&LYJ4O(f!3r?a>rEx*+>vC_=bmV6X*N3%haJl-0c z6=HzvvRc|wOI@~!<1>0BV-Xl~R?g@wn<((%O+Ehnc>dqJWL3_kO4a0ygu4B*(YgC9 z&uD8}x5O)Gwkg?}*8!I+)6tTa{X($JJ*)SvJkq4}f8gGd#@+S$`|`U-eAl|v$U{oZ zDG-*>&wepic4>+w8v#OY`kfX4BYI)kTo_v*fH@A!)4_o(YX)`P6A@m%J)2iT;mT`N zztiIWV+@17!!F-0R$M1)9giim0)PEIc7Sr`*p>t8=ID|b>jNZ@JPz*YPddxCou zr92oaXoUudjHH+8TuL?b`OQZ_nQl&vvHsZbNW(Dbzjw`2Zlg4<|NmsK)d@oMa> z)|hOjpBT||zyn?~)tSPwI*$^Yk2Q%k!2?h4 zF(d|%ag!@+j5Cs;L*M;05bNGhP1!Rd9zYcA&vx+@p8l1!Wu?&GwW|+X2q`M3a?cws zjBZdj5&mbD%+j&CfF>GaaaCI>*CjRb?J9!>Q#WM)73U>r7mrfy0=}-=3_xt=mXSvP z1_fP4{F;-u<@iB|#t-+_tkolCE0DT0;`cr5^64)Cv*Q!W9pV4RoKU1L_r0@T*oZ(H zSFW%`V-wh2mJMsvW<8;KLT67%!jz~AG|tt%`m($A`8`OjbMD1Cb~g3kxpzLrTDc3V zQFa9DawvZLSS{d)5J&#mVJ0BQTM7+atyMWxjHQ8n=BEZ~wvo6LWS<}h2pw($gCZ2r zxl9UhCO#;Z<@bX^6R<_^9b$K=Un)S0A~EgNS-`M`G2c>7HesAWFtn4w7a0hg+Q^Zk zOJQ?)0}2^-2!*_NmxJwd9}>Gd8=2$I)l|)s^S|uC(N_O+x06u%c7cJjima?Szqp(9-kKsva8l@&$g`L0#*E9m)tV<=?a@*(kJ2zl$q;T?mD zccY7<;Nc}*^&U%1P``_hpKXF8p===hznf(o#KNfm7H!c#E94)%3JqR%B#-8)r1r}z zW>kuNorUvgf!v(p2bjUV4ky-z&VmbXc!`C!<##nJ)CKHlZ2jHK={#?g9qNEgHQIN* zvSF{^Mh^A~)~95fc>`HsV{ydfSgvN`xiGX_d2%HadimZsI>iWgci*RCe*3(*_-pX> z6XmbGc#k;MAB4_rocZ8iAhl5zvk^O#Y=p{EykzinfdLvP|1_X*)p26xOoVasSnu?0 z#_*tX_rw|dAe+51QrzK~DpSYJyX_I(Lu&S5)otVK&|I{Lls+H!Cha^k<$YA(33vf1gLo+izcqoA6OXg zTxz29!GqX7N}iOK-C(T8^setAaAZyp{vc-n{MT;Yv%9Mh435q=hJqDhV>gzgQ^jnl zYLok^_0SDz3JXr&PcO*g+dhTgwFwbo37!_k;aK21 z%`l^{cS_ah6%R$k(Q=yW`|?GX|Ep%&DjUtEJ7W)!--<~MG$FId;zWC17L>EV3FCjd zU^A*GtB7D#6mS5mE>kFK6To37`@`@6d*)8?4ScERIJ(jP~0_mv&Jm&9d!j zlZ4ZRWwG3S~S)2T;Rarc0yn~H3q>33= zsI4fN%4@+47*}R3)wh*tF*pTgRyT$>gGNc^&?yoNsaKG+UzD_pK0G#jI7AV<1d3^G z#iR&t7~QVkXz~1n8tcB#EGO)|9?6(hh|Yl~{BMuU;a9u)iZ`aY1L^-H=r z-P*J{Y}k|L6Z-hZL~WO6l}|-B04K|H?=Yhj*oo=^?&A~j&>g=}fkd?Jw=Q$q_AB}S zm%I_qki!t{+>PF#RfdieKZ_Ndd%|#6?33eZl@+_i!BeGCpBVe(Z~la(K(ly#9{pnM z+AS?NHLyVyf#CS5#>M|ui2?q8CIe>!V;Rczfqkcj-)F=EP8r%PuGJ_aa zq?0f_xm^%-&{X*4kCuW|N9sb7;F6aEg!{#T$6h>T=ZkU% zwc;leHbGA#E~Y9IJ0ty{HU6gnd7ecrJw-_r8iR~^KUb+r@z0rdI3RDNIRR~zI-rs$ zjb;W(h!wQYTFELkmUU-c_?kzBbjKv>YEj1ckiOZB)*wEPV@IFcfnwI++T1~#HM~fZ zI}K=rt4`wTl4zE$91cWmtFNHpUdB=>uZD0%PA%XegPdZQ?dmvHOQgyll34&er+0k- zLUw8cxe*ZYD|i8qZgM9iZ5>k7a%mr7LX3$h0jc8>`mY%+h|MOnwDpr>TDyZ%E)4yr zrRv=&G6%Mv`zT^Upnoh)Gw!WOz*fO>24zM*REgTAvE7We1{yYWzEKFc4Q80#W>_x) zkkbai(g#qwGdOI|KV((^sXH3v*E4G8ZauqCvp~gmeM5*xd7hNU&O@(-N#s@q0nx^r z2?IHxmF!Hhk**que7-NRv=@1w8wDBGx& zaL1OYvY!RhW^+N|ZlJ9#dG=tO4s_-024_ZK@R2C%KB(0!!G^d(nzWn-FTJ@fNrx@j zB=X1v^b4(Kns+F2LRjK{+U57KNw$auTFQnhDtL;5OK~RRx&`M-L1ynb-)IOdKk&wW zU5k&2d?0`(r*u_y!ThyMaq>=1mlWq1toc^R`h+<%p3ta2%t9s=9np=gON zaB*nTI?v2@*5U%1*8Sr0x}~bDs52%gO&#H#S|~)|WiXkQ#*QC!fQJ1waxBML|JF>; z0B?isqtR30E1i0jQ+A&q1JtQYXR4%xQ&U@4%rkf90-bml)^lTr4c$~QPhpB!H(E7G zyiImTNRjEjv|Pwt20d+J2L**d{fV~{YG=;(8qNY24+*WxY6F}l+Ym=aYDEUQv`~Nk z59c~zAZ8;{Z17k%MTwsGSScce-17WK@8cb%D`~zyUEAJ4ANa>v552jBdiF>`=XH*m z%=5piK5ISI(Y^s&i6lZjSZo#ILla<=*A{uTx>Pt0u!Lm3OU{e4+vJ1)=Y_z9r|PnUR?7-57VdH-H2@30y@bcoD0+Ix15@_ z9VwY?W7g@g$%5~=oIJUQ41Nan`;dqmuQf|ei9dAH@0IrGIAaUo$KNsEB2IRG2m((Q zX#=?Cz+v}?2t@nAmqRS$3XL7@#3-1)-_hyPj?e!JCOnkk>XUfz2sa$7E-u#_<~OJn zd$Gp|@9PN^d8O>P#S2?ZR2$Uq#g75Pc)&w;CY=x3+Z@ZwZ`lsv9_HZD}{0_`JS<3}gX(S@vlEGJ*h*4@DgeR|Iz^lYE7yrB$N?BqT7B{Tz zYfQY!^WbVp_65H_JH90nvt@2Q;oC;BCO!qTPl7=a{ivu`a46*7JzFJ9jjj=FEx~62 z_-r`f&H9@id*Ki*WaG8X^SRTXgmk2hc=sKbJ<}NSWyY(Nu-X=ybKhU0*ox`vDLTFU zr$i#S2J)-bfCf`F*~xwd&_&y{F>e@@=StENJBwo-cq_aeU;WH+$&A+(`c~Q+DE359#%R+tSeBqQeIe z`!0CR;zhrgH+?7>D76Ad<$&fg`WT~uUin{LRRp>$c`Z_ zt&(_@Td&B%8%mD`SgmfZ`xA?+N3(r(Zg0yI`A#Gj(qJdL#6WxC0-VUSRF02Q+JPc3 zjK!MK(Pl4g=m_#>5oV=42Tw=g3ZDI_bq5kLoS!3JR0vI7MhbvcA?#I4L4hyqRxA=^ zf@wVLIWmEKQ3O#Q&`%Mb+M4g|F;ydzjr|A;P;~jb*Ntwp=nj3uPAQoO*^bV8DXGA- zH_qc?Y0Vw@pq!}?Eo;O+M|aj}?Ci}swAk=EoF_G=uPq*{#zjQajE16Iwg2X0GqX1{RmXX1`t8~gjZUWF?B&y?`n8GycESi^dp z#c&>5ojPN*qq>H8_K(BInU7h0Kxq;?c_RaKg{FVDM%P*7bhPpH_n=+}p9J&aq)@;P ze%@O+cvLtd1EWI{+DyFno!qvr``sBQTbrKWEw4DY*f7k*yG~~d zl%|xk@q}J;ox$~}a#-rxkk1jiaP$@~F?yQh*~mzd0^s4r z+%&j+o*|*j6XsF1c12?9=RI?>hM2lHGJ{H3(*~q8IN%|ObAptTpau4)qS7I>6!{bV zPZnS;2D});@5$?PA18DGC}t_s=sUHQV$)T}@Tic;1mwrK6=bnF(!9(=MRe{&8I;~3 zzZF#fW4IEQs5qm5yzBVVTKzwb2An@#_%B}0NL+XL&&HQDYrAIy`Ma|ZYTsRA(shlH zEyFfX-GQbBX1^YIK8P^MIQH1*CKSD3aJIoZi}~bw%z>qI8Xj702zy-9O;AUg)Wd59 z_dX*^0MULg;J$(DT=qBTAK5iHLA})wqfyoUA4KVpjuqr9ZjIJttth#-x+v!4BMHd~ zof1aRTZ+?GK+_P&r~~SAJ)#9zKn%UMfwj~X8W(H$*tE;{? z(K#02wkiF~tS84Whq;;!3HMLJi zXw2-*vICF>al%cBJX#rC?$vjg!O7iLhO+WXFhb$7yzjks_r|_8TqtN8Q~5vOyg0k> qSc#5@pe*tGoqb!yNE;f#8s!;_5slqB3cSxn8rSGDHk3a};nZ=%+$G#&z%n(;liP*0Ad|Rw8QJl{ z#!*#gsD|=)Dm5BIQ=v93aQ&MXL^Ed`u zm0kvcD7dm?YSFbuXXJ;nG)}ju^fe`G{${1IiFDb_GaRE|P6b3eALD)Vr76%i z7bEwCL>BRo65?qaXoSgrA6Q^dkx zF>t3MaEUt6y8$Q38&OLf!y&S=C%kdZIG=VbGxO1;STg&ycbt&N?XmP#DUKY)pR zH81r2aZxEJJf4xuF~EjmK{2mdHGj}|u}Dtkg?PSfu37Wxkz&tQY~8QCKZ(ad=U)*f z<4UTNd!1(+$VX1cR3h6ir0>Nu{>&f}%F#&0PXHJc&ExVlv;8@3A+ zAQqeqNS@p=k>P?ib?n=eHn0)H?Qj9{;}o~XJnd-={$8=13|sU#qGyf;;Wv2^o{h}P z2a&d<4@ysgWWTQikTHOVn4>Jb#J#9Opf&M8AI`^_0=-<7{9HkJQFEngbJKB3^lv zE0$h`F}w)6WX~^!6ZF^bf+63E(|kI?JDkwNfQNZry4xt0NFfDsEpd}H;OWV1gPl8= zhaopaXvrnM!o8^Gmu1=y$s!(|1c9tr9OZ8vy#%qFsTh4#<)6`uJ~kv{jE&XKEO?%( zvsS?)hU8ZNw^#{q;a z_F}{0utgkYGRA~Xm#NC~4~9`YCHL)4&AP|+8!e0bXN z2O|Q|%eYC|P}X6YkNU)tNXBs{y99|so&w-7X zI(zlr8>RC!Eex?$B>!0${?~~{Qy?a~z+xHaCbX?4BuWOg^-_m6uKL9^%`$E>tk6H& z{&sgkh@`3wmfFPD_99H4!5GC`xDu9hJJCFgMSbK`;;FfE&Ht9J1g9hD@5wqT?VvTW zi*Hvwx!L$t7x5nIaT7m)b`qXEvzUs8nLu^TgeF+N6yVFdw3G?)3Des&{iqnVHASw& z@!h);N-WMjBp~lIhG0gfva|br%H_KfQ;hB3$U&h+J+sXU<(ll|A;7~`g$m9!g;;%8fp|jIX+c1H&Sv8^3#f_-wydjP#7>!s~>CF8Ksj<(_Kre zY&yJxm}^ssI{yg4FEC(xZ?x^t^7iyAE=xeH3CArs*t&E<~nMFNBfB&BBf z?Ewih^FZNOCi*}Oa{U+Y0&jxLe`)pnadE2~(AB<#rFJbWM!-30XXG&ja&6k?IemtF zrHcF`qJ~VXPw869p#7B>SjJ;-RQgsgGuD8~>qd|~pGA)-D6C9Dh|3PXZ_ zOQAtsJc@`+(}ljpKSVzsj`h_cZQrdskn1C`7Qvu&?%bCOoWZeM@-<2_oP zuF%#OdyPn2bu(=nMn58+Y+xKF){du_0wD&UiPT^$2djK1<#-4&^IvFDPWRia8h{#c zMs3M&=i&*nhGx0TDb!OXC1dvuUiQJw50CundSeSuWgyn;QN%D@N8@?pZK`AP2zRXhQGLyy<^gwJNO4)7o1yz|Fy^`C zhAUGAO@8X6wq313(tq5K#lmnhc+zfWbc8L&NsF1&^TxSV8cnj%)z7AwNx=w^b>)|; zTR|!1K7b-(x^N=pgIyHkVjVU?Q`mUV!tb0y$&?vA3RJQr9Sly;Nptv8fD?69;2PA= z!N7TK8VPmIpNz`B(u;voLGq{TB^2qu-KiMhnEC>_Fn(v@g$mYK#~z*;RFD1<6j117U41 z1G0dOyJn2UE8{QL*ixD(j>GS`=;%FyX-B8gwT}RZ@me&Fg2?&iW)|x+nlM%&y8D&K z45|&aQ9$mB!6kK@`o7kAcY^BPE5%`W;R?^y!qhL3eT(v?!p1lkoKlO9^g;QNYCU=( z>w=C#1J!DxcZ>c#K>T(6xrkWf_!|aw%#lU7h!M%U%JsyhHOThdn(RK26DAEg3Rg(Z zrALeGE$BaB$9K!NlqsWSrM*&)xXwuv_Piw)# zpZJTTZFe97SIyvOkXmQDpqT5+D@J^LSiTyE8apjL8zE3B?!}Fa7L17*BZV9!rsJ!i zHMo=Zuz?GzD620TkHs(4w-3T>jE~}Ztys;Fpm0SokXu$qBhm1Cu*0aXs6&LH$^*4u zg>1g`eE>rakt9(6?pehHmESNj@)F7?&$(%834)P%^eodH{J29?tYrE(d;WyxaVkrq z?2(s~ZT$ZcjKPrq#l>7Rd-DC|Ol7-3wAnRc>^~hvY#7;}YYcoWbp=~wOghIZCMou> zq;2<}|6g}0*M=0WhFi=cBRhZqex9X&KUnx3`JvIc=C`ZoRcbzSU6yAn1FDc{we=Gl zvsi&Qh2-t|vk5X%?Ecn4@t!3W&aT9g&~rD&ZKhO5kztLdlgFwHv#J{ZBE_rc4lQgJ z&uIEO9c>!17Us80BMs^FJ#;bPON(`U9)7S`DUB_DDKVLKL6%tZl4&PbQSQN>nXR)^ zF(3pu98GBTXbI7g9}Vt!<6jE#by6&s_-~Ilu16S9pO{C9H1ShX}i&Ri1 zqgdAYLC(=JJfSmCZa_rA!p!mlH@hLclO*_PWSe`>LRWM*Q`K{K>(kAbsH;xgo^!QD z923NbBdImnH40))AwXjD!Xg2UoKTq-l7KL>}>@)kc^3yWRt zUo-__9P~N_U;hvxnu$1ng5#qWO6ansRnpU*y6I~*_Y5qsHDzQ}8Y?`=SS20H9SY>rI?O*j!1^8e6J84H3nm}5xT z-=N1(#;?}ERR1bi>=ItCKXN)y?3QTQhk4Vsey-+L0amC5G}r> z!|{@)TZibV3WQ3GR`^k{o#Z1yAY=4({7G9QjadN7nMskOYEDT_(QWHtK-s-lA8ECY z3wrw@@|UU4)Rh_>1_sd)7w^(C9ueR6`lCM3od^edXusCg2+{~})&fkI7E+v2{X=>kQNxTNOo;fbd_h#)j1wo^HM;qq4f~KfGLZU(f{eR6Js>ooitd8&YPR$ z=}zAlt9#+HZ+TVz%Yi)Nh`TQqX~WOoBgLkRr!a?moKW<{7B$6- zT8lfAeG zu^}%ZOkPnN4_pc2hEuOP@tv={!6i4H+NStsG&u7ACvF(UE+6O1~ zp}efrW0mpLyW-v!%WL4W@{z&ErNQy4=@q4?Wx-hkWJb0&YvioMu~+wM@?kgLnz0xl ziU_8p!AxdTVu3~?pvkF7@DAmO6qd%>;(WC6XSvm%Aq>0fci}szNL0=(Rs@lNr_xON z7G#yjStifin6|UY#vF)~Zmyf6jWBaT5?BeED#bp!iPA+KJTt4aZv_-jyEVTk7K}fb z+d&+fcm&Y~4O!+?Ka)Po3@F4bv^CM2EVsd_?_Z29F~NJ+qq=`Knst#1Vbm8=oDf*X zLj%E2%*);^PoxCZL&VE(V(C9+w$|^r;EozQZCV466iz^_krlDLZ;?-x&_F386O-y! zD??__k)m=&QC46HvO#?wK-A@;tN3nAEjPvsf%*1wC$4Ew1H6^3W3OfTN*2%yO$aQ* zg@P6o>HK_=YgCLwCFZ$6Jn1aTOo>33uic+Hp!apYeXntEV@-nOCa$+eMoZL;SQmve#IFFsUJ1{QUYrdImJ;vX+(02N?LVl^t!#agJo&%QOqq z_jT-@a?h(+0NRM8=QEGnv{L|6&5Pq1UHpp=HpS*}mF3d(3Nm@15JjYljQQb$PH!Az z^BuUK67_Rz9d!jpXLV+H10q>VC&DE0(+2hunK|+HB&`Pg4L*f^JMjA$LV?Q=L@yPQ zyxEytxR4+R&-?5*#$)WkaXnU7?oluzjB`PL9U?1d@mo0?rmBE5&fg0_OWfqxA5ZPk zw{80`K=knymKJ3O^!EI!&--qUX+&9b;uueNz%)EErXE9tZVOdTRrrwi_nV@>z>rXt zL-4R<$77#5>f!gr@^a0OJ%I7zB@n=4!|T8NWP{T+UCQm>!?^=B@hxJLuy&VdFbPgw zgan57zt8PQ#&pd*ZbE$xXX%02HLmJYC;6v!(AH_lQgR^s{%IY#9pncD^j43v;r7=f zC5qIW>L2TxOol*NJRO7w{Dpy-^}O6a1^*3Vwmsx;S@AsxuxN16=U%j9uD;whzB1Tb znytDlfET}NqZUYa$kcaeif45eIJZn)g{Amk;m6Mtb?uwc*DP z=y>8n*AWMj{7+6n7&y6vY|C57IAN|-N_J}zFkT^!g&%4L&sEcvh>pL~%*eZp14gC0 z^27x8y3j(7%41SRkkKFU4d%-GR$2cil|M6ed!3AN7EPA$;2APXX9Ca{(Sx=$wWsm( ze+b*_ON=1;rNHmi8%fuu8cfx}*D(gx+<|U}EGJdBKzVqCWuw<-71V3U)^{eXetAf^ z^j$oF$&VLc>mwro`QF5BNc*%e6c)1rr$XatY9`?4Q{oY12VTPWPv~#vlI2Y2|Mz^{ zT(L8)d-7q(*Ig7+TGMy_`J8hLTIjq?YMYCUwALlTuVXsa9L!Fjv0MwLH72%K$5tR- zf*DkY8|oNn(@}4jICDHnU~UFR_(5l>J}-(K!@!7fzRPF~aj1A*%)EX1s^{~3SL?e` zXw7q(JE`)g`rUU+WOUbJ`xSr2^5!R`PiP?7+|#8v(vQmbU(v7NXi^Ajd}JP85#`O@ zNLP36bpi^DbfeamGr;%(j%Xl1|1E-j@3#W&Y#5ec-lK~z5rU_FnIa2qjWXPK ze*C*z89+@X(#!6=+k)}$`}dC9D1?}U@N3?lDiv_gN^yYY$7Pf zzkg@KF$MuD3rfZku(r+nzVljar**6&8i zbCNVqEDaYEy=LhZ8VpqAr=y>Bf?jOj^lj&tJMRFfqW4>_gs$N>p?R0*n)7AfUwwpTPW6vth`Sv{}6%q zX520zmt>)qzJq>Y-9#Uu)E$*G?ERV z^-x_bJH1J)S1Az3uJ;=-rpb2iVI^gJ|?56n!+N z4Itwcj|RGtU_Eo@7NH)rXAbD$hL{AVYqD=3pF~{qmqag@(H$IWj7LT*g$dE-eam4w zh%KcHlsQ#j^38{1Ij0Hy8U~F~ao2hyzpi4f>#4vXD~0bqCKd*`{T?S0vB$YucS^pg zQ0DR~e=xp28W|dA!2W~)4~so!jW-5CTZ6%g$|dAEo}dyiM4>xdy+l|5dp$+Vsm|_dQ@r9 zCJ=+2wE96w)c9R?qPXWOn~)VqwgM8)Y{q9vH47$j)#oUcV%Mxw!S*td{$LG-oDAqv zQmI>T-Zx;Bf+;X$F`GShaEQjM{LR1~=)0BlGdrX&nbZJw0F4|>PMPz85L!`*BUV>q zOR}D}XR6WS2V7v%`EJ5b1?z!Nek0NzeRE;EWe;e_3cBF6C=c>U{#scY>gM&{N?&V! zq*^Lt0o1w!I2ZYV_Cz#ETBhu^z}O&F`0kNS@_WZ)i6T{MEb>7K03H6Fq4U2fmYTql z8LeB!f0w$^92=U3Kp}H8?sv7F%8I$z6@&#xQ_g?Q3X|AEGLpH=W@wjce}>+@O-WYx z+_yH-5>@a+()hz`K0%!YQKF0`)dBi4j#EjveOxSXiwC{)dm>bu%k<=OPAE`xYw z9JX!PYmf457~Z*+hZYIQJ5&%T>6Aw{&s*o8#iJhkvp1zoY}!CsnzOd~Kx*AGo&2eV~$-4p>EJp8aOGUYv+rLWzZ-2bARZ6 zg_u5*g<5GPDVZd%X1h&v8W0!UCl}b+gI|n2UvaT}kCZ7--n|ySRh?iKR91hbQKD;42axOd!(@KwpJZfK}rT8n(YI4s7aD?xlQB8jDvXlJ&%NSy$^)o<_mn zaSllL+LwPQ>K`?jSRAxWzmK37UDU8Kc)J@HhSzN503znA4rjZyTPE2iVo{g(fynrR zw+Md5&sb0|>nooD+5;F10l_z5+yeO8(?kLY@T7a_Q1NGY_p%+~UXzu!Lrh}5&cTWh z-H}OxTlINp%3OjLWrU~?8w2|+Q(jKh!CH!1&TLw@Q-UvAgoTPoRuSnQP;>hLqh2Lw z$V}tO5I@d&1%pE|a`e~HF=`+Dp@Y0W*_SaWKN4(`>90G?2O=h~rqg4c3yT@o$P&O> zgCwHV`38E1*5P$nkYIxcr@>mtasn>OQmawt9Woc?{%V<{O&jOrnue3PA#$m3?C*+e z!Sl*+a?grm1KE8DUW`uKvTe$rV>Id}npOC=uSfMk;^J|w`1M+3f%KhT#0V=8vw1_o{KDLaj9Vg^gcC)helAxn%+%Ore?Lb_!#@bvDXXSc> z4rU~&C4}n6+Xy*0BJq7vb?2WFpiqY$+M)dl;3Q67HnFrP(E5nzZ@EYJoYv{9bBgr6tDQ0^_rD3>I>$27KvxooMN!E2x;*npy?t zF_D{Xh4+p$Vc7uI*Km7Kllgp{KG^|t8uApqL#*yK2u+6(0sL<4kd) zua|}O5{Ht6kfrQuw|KD{WSgK`scJWIYF%g>hhDV8O&0RT*!t^4A6BBhZWnk#%)N6y!^4nNh~)8J7#*0P+@2T>83g4a!guSGpzno zrloxQp)Q;L=Ql9;gz?fn{~D*u0^MNXB{E_-D5F9bC6W(zA|hN>W}g1oY5;DuCRu9S z46~~t`5VwHV$w2cuiDz`PM77Yps5O95sZE9!46jz`~VKSt5*_4fIqCOaj=Q!#B{J> zF(Hb&uR8kVpxBb>D1+H{$L0!_9#PG4K`-nx{EVFJ!2>w-I_4`Md46>lxK5WrsdHwx zDTJJU*ty+!-1e2^Gi)fLo1c&XLF%kAHR>L%Pvr+zZeJs^=p}lWxCgNpcNgt)#rJgfQ|J5_wN zn}P-GyRN`X#fZdCFR}pac%_0G`1)D=EHL>-_%DtfRH0vBtBWhi?cDTmlNus8t(w7- zROppMZ39@#;bX+b`ro4Ycma);F+C3SrsMKFQx{-5zK|uF6y|z!Wn0mIxkq^^?TR`| zMH8h7#t=qXMVW_eXdHmLghppLK|B@DJcZ{x&*n7UiVD78i&}D4y zs#*J|o;8+Hu++X;r(Q4JF)ATSQbW{iVfU1ZeEF3_mb{n?U^6i~r3a4oW(QP=?n)tw z9ev*XMz|dCDnFauxYI)Q(YN+(>eb=Xa0Zh3uuV~A&Vi&zg{RWLe4Wu+w8PLb>b;4U zpN|f{f5d}%|A%sh{G-%AUz%r|D|~ocoN2*Yp>(+ z`_MZ#5h74K;KDI-o2a@XG4&dOkc^0&`V4#~XEuWGZ#VN%#GQ3vDP2c5pUbx0F;_}&5gS88j z%{;(NxCx*%0yyqwwA)5B53M1-fN0TE!hC ze2(0UGBZ`-p9Z^$?fY{0oq2gBU0MCRy>t%W7n$N$(B7!Rn^xeo%X95hKHf};x3VLeD=s)Z|!g1o^`YCE%)cDQCbqe-^b|SEhMEhW+4B2 z@9jsDqQk6lN)W~Rc5a8oM>&dHuhI$7Qm12iu|I21h(ul3*ioY3ukg*t!oIa@X_Na*$s@VeWpl_D`4*AcvHYcK5W>W_ zgd3|FyJ${g@0w7&;-hwHt-Ar7n1l0}y(;UI5phN|(5gDR(E+z&z5f!5x~xzsL>ZJN z#5oHemm)plbf7=QRztwV?}EaM!E;wQGJBA6BqqH{8>ZZ6ja*;47T6<_=-VCHb9L5aoyAg{Xp9sU%uPrDuVQv58 z(=}*3|3C55FlI*SA?{u_9py!c1LZBY#h18GB$P=;MLB}@EFXG|QBMx$Jllh-?Us@g|7H%u?}67a9KO--p5>=D`=O(nMhFXkB{s?z7M7* zmaZ6tDd1%pqHe^<`A8hisw6cDCf?AcDvyHb)M7Y#v`jL)*Funhi^Q^TtQZ>gi zUTzrDGkY>8Rx}^+?NbnKQnp8bD%n_0O^P!9e$&%uT;BvYfg10%0n%n#?u6pHEky`I zU@usBORgSy9a|`N_+?>!Tc?-7T>d|2P?(G)<9Vf2A~b9 zzz1glOxkLm^~YFarVk!PqRaA9Gv(-kzTWeZpP{2eD)S7cr?tFPu_7L?iDh%=um5(i zdBV8wV?Mi4xo5K`s8{IK>E&jBJ|!E2(oW_ij;+xGkT4maRpF5&7Y$5d6_yq!zBApY zKlWk$zLB(s?*Pn+T*4n+<=Q5ONJWoBj$K&G#6%TA0X+qLmV`=h5{r7q_9vluobWWu zSE{((_rcBTBI-~U1ane4#1rw&BBiaqRph-;VO!5riR`%{tSORwvX%h@S@A5>T)yH$ z%H%0f3__W=lY6R~7vOd#6i#}35l#|d$l+>1gI+dy8!jgVwCtGYCDKDJUj7I-3c|=W zmJgGjbr9}TzCBlPcTfa|C3vp|Mel*7t6E8Z% z;WE=u+qUyxya9!uuX%)V4Z_?!gEz3TQi3EbYW$;tt$h zgl8MWj2-cLV!_q&RvZGl*I!JhriZXb&=;)L!rsTPPRS_(AJMT@hU?Y#8at`y&o#;KT zBBBvfO|)|CG$1C@G(0lCcbZW7d+_IBVDgRfojzqTxV`jRcN$XJdnt8|3xc}8r`e7Y)x!-fxQ@Vs_6Cj`PpOY4?oLOwQMC?V@Df4#zO?Ju7_J0|Si>G_y z5x*$*14WTb{OIwKG;VafqZ{l4N^X+2fX5dPgww>IP5zW@e`HVLkIvs1d_;dM#jb%@ z!e^ARjHmB=6boE=;1@)_DnD>fA{G>Ik>iRiay?)Axjc6)t4V)@(*e^!j*5mtHc}~-QZ}9pk+r+A*ewxdhYrQGY@LYdJ4Kbg9JnEowQ$lFKI(du%a?# z^GZjFODuwBs8!<{Tcbdm@Ff9x2~J9?LO4jH+zG8Oh5^qBcpZR@uVCI6w;3yqJb+ax)9)H*= zLqOOyV0O43!A%X-9%NVK7^&OrW!Pr-w4`=ri^LgEhC?t{I@=YkNHlZJTY{;{O#jE}IpPCV^ z{yJzp%I9XQo8g$QHRkV{4_OP}3?D&VWF z2ghts`h|kvZn`lA0V2}Soyd4M6cX1-*WI%l`vC1!$m#_&6!Gr70xyyaHvXZZtX;MY z!#3#U9)~f}B{=T?6yB8ymk2#Jv3yF2CIB>c)D60zu4m6Aj zJBC9)C${3(AqS9vj!^8LC!5+#s&`q4aj6?pl>mFbV!_0cj(CE05zKXxaC2+Dd1n0t zE$A&2J(E$1jG#1_r6;4=)815$DnIR--$=kwbK!)hx#B0qKMD=|rv#zD2{V7SeC6KS zQMREc;C7p`k?`B(5wswo&9*s3+eeK=)#V9O@IS(JaLBIx2GxL%#Js+a|vGg7fdvKIdSJBj_NKTTayQk+}~*;=_fgCHvg6qNh7h zM1ke&X}!v%ABS%UWm%fcu?ZC&C&2MS!#K7lEqT0Y*1SK9zXnMd9XgM?5#ynSzV7u> zV=iJBunLOXw8p7PR8t;!Nf>yB>ugf~``a>o#pJLzHr8h_z)iwwf4|cU;>k{M2?DlwI0B! qsygqv5M()3@FQT3ifv0hBa7C^Y>+0>3BElnB(2}^2ADJ>Fx(HVGvllP diff --git a/release-please-config.json b/release-please-config.json index a056d2f03..64e021bb6 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -4,9 +4,6 @@ "release-type": "simple", "component": "zkool", "include-component-in-tag": true, - "prerelease": true, - "versioning": "prerelease", - "prerelease-type": "rc", "changelog-path": "CHANGELOG.md", "extra-files": [ "version.txt", From 158a33095859674d9f867fcbc2cc40d393a96c87 Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Mon, 27 Jul 2026 23:18:16 +0200 Subject: [PATCH 029/189] chore(main): release zkool 6.25.0 (#1175) * chore: update build number / release * chore(main): release zkool 6.25.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 27 +++++++++++++++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 72bd931d7..2e7a9a670 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.24.0" + ".": "6.25.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9190dd508..17262cb50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## [6.25.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.24.0...zkool-v6.25.0) (2026-07-27) + + +### Features + +* log per-pool spend/output counts before build_for_pczt ([2aebcf5](https://github.com/hhanh00/zkool2/commit/2aebcf5a85dfd826dd632c16776bf4088b892d43)) +* PCZT-DUMP with enc_ciphertext length, per-pool counts, block-wait loops in tests ([e1b8868](https://github.com/hhanh00/zkool2/commit/e1b886859d231404bea910beeeea97ff5c3e76ad)) +* re-enable ZSA support ([#1164](https://github.com/hhanh00/zkool2/issues/1164)) ([4fd9c66](https://github.com/hhanh00/zkool2/commit/4fd9c66f1bc620ddc4821fe9d2279ac58b1a81c3)) +* TransactionData.orchard_bundle -> OrchardBundle enum, ZSA PCZT domain support, test: block-mining wait loop, per-account coins ([0f75d5a](https://github.com/hhanh00/zkool2/commit/0f75d5aef2d8fe0fc5da37651197fd40fb49dc04)) +* TransactionData.orchard_bundle uses OrchardBundle enum, ZSA PCZT domain support ([314c281](https://github.com/hhanh00/zkool2/commit/314c2815b5e3e539d7d152dcc88fcaa975212fcb)) +* ZSA circuit separation — use vanilla PK for O2O, ZSA PK for issuance; add zsa-circuit feature; add ZSA issuance test ([38a3838](https://github.com/hhanh00/zkool2/commit/38a3838e44b9bdc045cea9b6030733791db483c7)) +* ZSA prover uses ORCHARD_ZSA_PK for all Nu7 txs, add pczt_replay CLI ([9a6d304](https://github.com/hhanh00/zkool2/commit/9a6d30465e881d238028a2d4e4e6a24baba2ae9d)) + + +### Bug Fixes + +* always select notes for privacy, with fee as tie-breaker ([329a1cf](https://github.com/hhanh00/zkool2/commit/329a1cf1373239a4dca5dafa4b3cf130f384958c)) +* auto-pin db to coin=3 when filename contains 'zsa' ([42ed01c](https://github.com/hhanh00/zkool2/commit/42ed01c8d69478e13a58054740505fd0f62792f4)) +* complete ZSA PCZT transaction support ([850ad82](https://github.com/hhanh00/zkool2/commit/850ad829e475ee2540a53737a47a462edbe123b1)) +* correct ZSA action fees and transaction summaries ([90a0286](https://github.com/hhanh00/zkool2/commit/90a02867f7517d89263ef0d3e34229f0dd87a08f)) +* finalize new ZSA issuance ([bebc3a5](https://github.com/hhanh00/zkool2/commit/bebc3a5075171800f22cc95ec6b137376168bf4c)) +* hide ZSA reissuance flow ([6550ad7](https://github.com/hhanh00/zkool2/commit/6550ad760faeb98e82231e46ba58abdc365d43da)) +* improve error handling and diagnostics - fix IRW detection ([b42acbb](https://github.com/hhanh00/zkool2/commit/b42acbbfda59bb237051b2cff4b669287bb571be)) +* remove cargo config ([484563c](https://github.com/hhanh00/zkool2/commit/484563c9347410d14c1e35bd5a57652e012dba67)) +* retain ZSA notes below ZEC dust threshold ([a611410](https://github.com/hhanh00/zkool2/commit/a611410b7b89091e8d0c33d687d5e2509539f5e3)) +* skip loading state on account page reload, enable prerelease versioning ([fabb1fe](https://github.com/hhanh00/zkool2/commit/fabb1feaf554a0729513bc3aedae56fe41bab984)) + ## [6.24.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.23.0...zkool-v6.24.0) (2026-07-20) diff --git a/build_number.txt b/build_number.txt index 27a69f601..86619979c 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -327 +328 diff --git a/pubspec.yaml b/pubspec.yaml index f6501ecbf..4c2a2dee0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.24.0 # x-release-please-version +version: 6.25.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 2496b04b8..961b1c8ec 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.24.0 +6.25.0 From fba04efaa3bca24f5446af73470fa3dd7930ea11 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Tue, 28 Jul 2026 07:59:17 +0200 Subject: [PATCH 030/189] chore: add entry for NSLocationWhenInUseUsageDescription --- ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index c45892108..d90a6edaa 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -32,6 +32,8 @@ We need access to your camera to scan QR codes if requested. NSContactsUsageDescription We need access to your contacts to import Zcash addresses. + NSLocationWhenInUseUsageDescription + Zkool may use your location when capturing an image so iOS can include location metadata with the photo. Your location is not otherwise collected or stored. NSPhotoLibraryUsageDescription We need access to your photo library to import QR codes if requested. UIApplicationSceneManifest From 7059ac731073ef15f1d941927300feea5aaedae8 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Tue, 28 Jul 2026 21:07:59 +0200 Subject: [PATCH 031/189] fix: ZSA dependency compatibility - Use production versions of lrz Pin the production-compatible Orchard, librustzcash, Halo2, Sapling, note-encryption, and zcash-trees revisions. Adapt transaction planning to the explicit per-pool padding API and include the Ironwood serialization regression fix. --- Cargo.lock | 83 +++++++++++++++++++++++++------------------- Cargo.toml | 30 ++++++++-------- rust/Cargo.toml | 20 +++++------ rust/src/pay/plan.rs | 4 ++- 4 files changed, 75 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb89a0cd4..a48b2cbe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "blake2b_simd", ] @@ -2900,7 +2900,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.5.0" -source = "git+https://github.com/zcash-shielded-assets/halo2?rev=d687ce0e3e913549cab370ec66765e6d59d4612f#d687ce0e3e913549cab370ec66765e6d59d4612f" +source = "git+https://github.com/zcash-shielded-assets/halo2?rev=dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00#dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" dependencies = [ "arrayvec", "bitvec", @@ -2925,7 +2925,7 @@ checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" [[package]] name = "halo2_poseidon" version = "0.1.0" -source = "git+https://github.com/zcash-shielded-assets/halo2?rev=d687ce0e3e913549cab370ec66765e6d59d4612f#d687ce0e3e913549cab370ec66765e6d59d4612f" +source = "git+https://github.com/zcash-shielded-assets/halo2?rev=dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00#dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" dependencies = [ "bitvec", "ff", @@ -2935,8 +2935,8 @@ dependencies = [ [[package]] name = "halo2_proofs" -version = "0.3.2" -source = "git+https://github.com/zcash-shielded-assets/halo2?rev=d687ce0e3e913549cab370ec66765e6d59d4612f#d687ce0e3e913549cab370ec66765e6d59d4612f" +version = "0.3.4" +source = "git+https://github.com/zcash-shielded-assets/halo2?rev=dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00#dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" dependencies = [ "blake2b_simd", "ff", @@ -4711,8 +4711,8 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" -version = "0.15.0-pre.1" -source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=9f4d3561f142c5698cb25b674e89af0592e15ffd#9f4d3561f142c5698cb25b674e89af0592e15ffd" +version = "0.15.4" +source = "git+https://github.com/zcash-shielded-assets/orchard.git?rev=4cf06bc19e52d1e8e43438cdbdd703ac2565bff6#4cf06bc19e52d1e8e43438cdbdd703ac2565bff6" dependencies = [ "aes", "bitvec", @@ -4894,8 +4894,8 @@ dependencies = [ [[package]] name = "pczt" -version = "0.7.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.9.1" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "blake2b_simd", "bls12_381", @@ -6134,7 +6134,7 @@ dependencies = [ "x25519-dalek", "zcash-trees", "zcash_address", - "zcash_encoding", + "zcash_encoding 0.5.0", "zcash_keys", "zcash_note_encryption", "zcash_primitives", @@ -6410,7 +6410,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.7.0" -source = "git+https://github.com/hhanh00/sapling-crypto?rev=bf29f9732eeaa417b63982aa8001acb542343b83#bf29f9732eeaa417b63982aa8001acb542343b83" +source = "git+https://github.com/hhanh00/sapling-crypto?rev=fb16242558b7119d2cb29e752ba9590ad905a5bf#fb16242558b7119d2cb29e752ba9590ad905a5bf" dependencies = [ "aes", "bellman", @@ -9807,7 +9807,7 @@ dependencies = [ [[package]] name = "zcash-trees" version = "0.1.0" -source = "git+https://github.com/hhanh00/zcash-trees.git?rev=0dc1bfd#0dc1bfdd4611ffbb8ffd4524a17fe44f0d1974b4" +source = "git+https://github.com/hhanh00/zcash-trees.git?rev=71acd627b129fb6cb2c3beb963c5e3b22070ff18#71acd627b129fb6cb2c3beb963c5e3b22070ff18" dependencies = [ "anyhow", "bincode", @@ -9822,7 +9822,7 @@ dependencies = [ "sapling-crypto", "secp256k1", "thiserror 2.0.19", - "zcash_encoding", + "zcash_encoding 0.5.0", "zcash_protocol", "zcash_transparent", "zip32", @@ -9830,21 +9830,32 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.13.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.13.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "bech32 0.11.1", "bs58", "corez", "f4jumble", - "zcash_encoding", + "zcash_encoding 0.4.0", "zcash_protocol", ] [[package]] name = "zcash_encoding" version = "0.4.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1440921903cdb86133fb9e2fe800be488015db2939a30bedb413078a1acb0306" +dependencies = [ + "corez", + "hex", + "nonempty", +] + +[[package]] +name = "zcash_encoding" +version = "0.5.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "corez", "hex", @@ -9853,8 +9864,8 @@ dependencies = [ [[package]] name = "zcash_keys" -version = "0.15.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.16.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "bech32 0.11.1", "bip32", @@ -9873,7 +9884,7 @@ dependencies = [ "subtle", "tracing", "zcash_address", - "zcash_encoding", + "zcash_encoding 0.4.0", "zcash_protocol", "zcash_transparent", "zip32", @@ -9881,8 +9892,8 @@ dependencies = [ [[package]] name = "zcash_note_encryption" -version = "0.4.1" -source = "git+https://github.com/zcash-shielded-assets/zcash_note_encryption?rev=57d048381d376f71ce6ba753d7876ef04b6e57cb#57d048381d376f71ce6ba753d7876ef04b6e57cb" +version = "0.4.2" +source = "git+https://github.com/zcash-shielded-assets/zcash_note_encryption?rev=bc7a9370e1a7253cf496f24aa0bd4d0e49c3977e#bc7a9370e1a7253cf496f24aa0bd4d0e49c3977e" dependencies = [ "chacha20 0.9.1", "chacha20poly1305", @@ -9893,8 +9904,8 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.30.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9914,7 +9925,7 @@ dependencies = [ "sapling-crypto", "secp256k1", "sha2 0.10.9", - "zcash_encoding", + "zcash_encoding 0.4.0", "zcash_note_encryption", "zcash_protocol", "zcash_script", @@ -9923,8 +9934,8 @@ dependencies = [ [[package]] name = "zcash_proofs" -version = "0.29.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.30.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "bellman", "blake2b_simd", @@ -9945,14 +9956,14 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.10.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.10.1" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "corez", "document-features", "hex", "memuse", - "zcash_encoding", + "zcash_encoding 0.4.0", ] [[package]] @@ -9982,8 +9993,8 @@ dependencies = [ [[package]] name = "zcash_transparent" -version = "0.9.0-pre.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.10.0" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "bip32", "bs58", @@ -9997,7 +10008,7 @@ dependencies = [ "sha2 0.10.9", "subtle", "zcash_address", - "zcash_encoding", + "zcash_encoding 0.4.0", "zcash_protocol", "zcash_script", "zcash_spec", @@ -10131,8 +10142,8 @@ dependencies = [ [[package]] name = "zip321" -version = "0.8.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=85151b802284ef70baa295823b81dc062f0c7626#85151b802284ef70baa295823b81dc062f0c7626" +version = "0.9.0-rc.1" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 84a6d1bfa..5d72b6b27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,25 +6,25 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- -orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "9f4d3561f142c5698cb25b674e89af0592e15ffd" } -sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "bf29f9732eeaa417b63982aa8001acb542343b83" } -zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "57d048381d376f71ce6ba753d7876ef04b6e57cb" } +orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "4cf06bc19e52d1e8e43438cdbdd703ac2565bff6" } +sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "fb16242558b7119d2cb29e752ba9590ad905a5bf" } +zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "bc7a9370e1a7253cf496f24aa0bd4d0e49c3977e" } # -- lrz ZSA branch -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "85151b802284ef70baa295823b81dc062f0c7626" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } sinsemilla = { git = "https://github.com/zcash/sinsemilla", rev = "aabb707e862bc3d7b803c77d14e5a771bcee3e8c" } zcash_spec = { git = "https://github.com/zcash-shielded-assets/zcash_spec", rev = "d5e84264d2ad0646b587a837f4e2424ca64d3a05" } -halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "d687ce0e3e913549cab370ec66765e6d59d4612f" } -halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "d687ce0e3e913549cab370ec66765e6d59d4612f" } -halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "d687ce0e3e913549cab370ec66765e6d59d4612f" } +halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } +halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } +halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f58e52ecd..644751498 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,7 +12,7 @@ path = "src/graphql-cli.rs" required-features = ["graphql"] [dependencies] -zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "0dc1bfd" } +zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "71acd627b129fb6cb2c3beb963c5e3b22070ff18" } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" @@ -58,17 +58,17 @@ qrcode = "0.14.1" raptorq = "=2.0.0" orchard = {version = "0.15.0-pre.1", features = ["unstable-frost"]} -pczt = {version = "0.7", features = ["zcp-builder", "io-finalizer", "prover", "signer", "spend-finalizer", "tx-extractor", "transparent", "sapling", "orchard", "zip-233", "zsa"]} -zcash_address = "0.13.0-pre.0" -zcash_encoding = "0.4" -zcash_keys = {version = "0.15.0-pre.0", features = ["sapling", "orchard", "transparent-inputs"]} +pczt = {version = "0.9.1", features = ["zcp-builder", "io-finalizer", "prover", "signer", "spend-finalizer", "tx-extractor", "transparent", "sapling", "orchard", "zip-233", "zsa"]} +zcash_address = "0.13.0" +zcash_encoding = "0.5" +zcash_keys = {version = "0.16.0", features = ["sapling", "orchard", "transparent-inputs"]} zcash_note_encryption = "0.4" -zcash_primitives = {version = "0.29.0-pre.0", features = ["transparent-inputs", "zsa"]} -zcash_proofs = {version = "0.29.0-pre.0", features = ["download-params"]} -zcash_protocol = {version = "0.10.0-pre.0", features = ["local-consensus"]} +zcash_primitives = {version = "0.30.0", features = ["transparent-inputs", "zsa"]} +zcash_proofs = {version = "0.30.0", features = ["download-params"]} +zcash_protocol = {version = "0.10.0", features = ["local-consensus"]} zcash_script = "0.4.3" -zcash_transparent = {version = "0.9.0-pre.0", features = ["transparent-inputs"]} -zip321 = "0.8" +zcash_transparent = {version = "0.10.0", features = ["transparent-inputs"]} +zip321 = "0.9.0-rc.1" frost-rerandomized = "2.1.0" incrementalmerkletree = "0.8" diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 887322ad4..36efafe24 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -31,7 +31,7 @@ use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; use zcash_note_encryption::Domain; use zcash_protocol::{PoolType, ShieldedPool}; use zcash_primitives::transaction::{ - builder::{BuildConfig, Builder}, + builder::{BuildConfig, Builder, BundlePadding}, fees::zip317::FeeRule, }; use zcash_proofs::prover::LocalTxProver; @@ -653,6 +653,8 @@ pub async fn plan_transaction( } else { None }, + orchard_padding: BundlePadding::DEFAULT, + ironwood_padding: BundlePadding::DEFAULT, }; let mut builder = Builder::new(network, BlockHeight::from_u32(target_height), build_config); From a9143440800318a3417f559ddd927d1fb73e2f88 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Tue, 28 Jul 2026 21:33:20 +0200 Subject: [PATCH 032/189] fix: restore Ledger build compatibility Restore the Sapling PCZT updater surface required by Ledger signing, pin the corresponding ZSA dependency stack, and handle the optional Sapling anchor API. Co-Authored-By: Codex --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 20 ++++++++++---------- rust/Cargo.toml | 2 +- rust/src/ledger/builder.rs | 5 ++++- rust/src/ledger/hashers.rs | 6 +++++- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a48b2cbe0..5edc2e715 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2173,7 +2173,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.3.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "blake2b_simd", "corez", @@ -2236,7 +2236,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "blake2b_simd", ] @@ -4895,7 +4895,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.9.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "blake2b_simd", "bls12_381", @@ -6410,7 +6410,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.7.0" -source = "git+https://github.com/hhanh00/sapling-crypto?rev=fb16242558b7119d2cb29e752ba9590ad905a5bf#fb16242558b7119d2cb29e752ba9590ad905a5bf" +source = "git+https://github.com/zcash-shielded-assets/sapling-crypto?rev=4c47c84845436aa1b650bd5367ed4de67421cc0d#4c47c84845436aa1b650bd5367ed4de67421cc0d" dependencies = [ "aes", "bellman", @@ -9807,7 +9807,7 @@ dependencies = [ [[package]] name = "zcash-trees" version = "0.1.0" -source = "git+https://github.com/hhanh00/zcash-trees.git?rev=71acd627b129fb6cb2c3beb963c5e3b22070ff18#71acd627b129fb6cb2c3beb963c5e3b22070ff18" +source = "git+https://github.com/hhanh00/zcash-trees.git?rev=1c820645e9116bbdfed5719ba8ff1d89b9be6cb1#1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" dependencies = [ "anyhow", "bincode", @@ -9831,7 +9831,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.13.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "bech32 0.11.1", "bs58", @@ -9855,7 +9855,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.5.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "corez", "hex", @@ -9865,7 +9865,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.16.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "bech32 0.11.1", "bip32", @@ -9905,7 +9905,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.30.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "blake2b_simd", "block-buffer 0.11.0-rc.3", @@ -9935,7 +9935,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.30.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "bellman", "blake2b_simd", @@ -9957,7 +9957,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.10.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "corez", "document-features", @@ -9994,7 +9994,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.10.0" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "bip32", "bs58", @@ -10143,7 +10143,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.9.0-rc.1" -source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=f8684db9e984a894f0d91012d02241812cd6e1cf#f8684db9e984a894f0d91012d02241812cd6e1cf" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 5d72b6b27..2ff7c2da8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,19 +7,19 @@ resolver = "2" [patch.crates-io] # -- ZSA support branches -- orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "4cf06bc19e52d1e8e43438cdbdd703ac2565bff6" } -sapling-crypto = { git = "https://github.com/hhanh00/sapling-crypto", rev = "fb16242558b7119d2cb29e752ba9590ad905a5bf" } +sapling-crypto = { git = "https://github.com/zcash-shielded-assets/sapling-crypto", rev = "4c47c84845436aa1b650bd5367ed4de67421cc0d" } zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_note_encryption", rev = "bc7a9370e1a7253cf496f24aa0bd4d0e49c3977e" } # -- lrz ZSA branch -- -pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } -zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "f8684db9e984a894f0d91012d02241812cd6e1cf" } +pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_primitives = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_proofs = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_protocol = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_transparent = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zip321 = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } # -- remaining transitive deps -- reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "975f9ca835c4b9196c81608e55192b0f711e951d" } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 644751498..479fdcca4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,7 +12,7 @@ path = "src/graphql-cli.rs" required-features = ["graphql"] [dependencies] -zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "71acd627b129fb6cb2c3beb963c5e3b22070ff18" } +zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" diff --git a/rust/src/ledger/builder.rs b/rust/src/ledger/builder.rs index a52d01050..93bd51704 100644 --- a/rust/src/ledger/builder.rs +++ b/rust/src/ledger/builder.rs @@ -471,7 +471,10 @@ pub async fn sign_transaction( buffers.push(data); } // Read zkproof from sapling-crypto types (pczt types don't expose it) - let anchor = *pczt.sapling().anchor(); + let anchor = pczt + .sapling() + .anchor() + .expect("a Sapling bundle with spends must have an anchor"); // Use update_sapling_with to access sapling-crypto Spend/Output which have full // getters including zkproof() let mut proof_bufs: Vec> = vec![]; diff --git a/rust/src/ledger/hashers.rs b/rust/src/ledger/hashers.rs index 2ea26e8c0..0fd15de61 100644 --- a/rust/src/ledger/hashers.rs +++ b/rust/src/ledger/hashers.rs @@ -107,9 +107,13 @@ pub fn sp_compact_hasher(pczt: &Pczt) -> Result<[u8; 32]> { pub fn sp_noncompact_hasher(pczt: &Pczt) -> Result<[u8; 32]> { let mut hasher = create_hasher(b"ZTxIdSSpendNHash"); + let anchor = pczt + .sapling() + .anchor() + .expect("a Sapling bundle with spends must have an anchor"); for sin in pczt.sapling().spends() { hasher.update(sin.cv()); - hasher.update(pczt.sapling().anchor()); + hasher.update(&anchor); hasher.update(sin.rk()); } Ok(hasher.finalize().as_bytes().try_into().unwrap()) From d6a7f4fbebdc00988510efc1efac1db1303824e5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Tue, 28 Jul 2026 22:35:12 +0200 Subject: [PATCH 033/189] chore: update build number --- build_number.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_number.txt b/build_number.txt index 86619979c..db2cef56d 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -328 +330 From 973f86eafc76b2f62eebda5e16ddb6032387b3a4 Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Tue, 28 Jul 2026 22:40:33 +0200 Subject: [PATCH 034/189] chore(main): release zkool 6.25.1 (#1178) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2e7a9a670..c8e2ff80b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.25.0" + ".": "6.25.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 17262cb50..94b1a2db1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [6.25.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.25.0...zkool-v6.25.1) (2026-07-28) + + +### Bug Fixes + +* restore Ledger build compatibility ([51ff5e5](https://github.com/hhanh00/zkool2/commit/51ff5e50437dea22ca539aec922f122c62f34bab)) +* ZSA dependency compatibility - Use production versions of lrz ([2dbe9a3](https://github.com/hhanh00/zkool2/commit/2dbe9a393d3f7a6149812605a89e817769b4b001)) + ## [6.25.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.24.0...zkool-v6.25.0) (2026-07-27) diff --git a/build_number.txt b/build_number.txt index db2cef56d..ec6cab011 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -330 +331 diff --git a/pubspec.yaml b/pubspec.yaml index 4c2a2dee0..683a67993 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.25.0 # x-release-please-version +version: 6.25.1 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 961b1c8ec..41ce415f3 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.25.0 +6.25.1 From ecb0a6116889b4fdc9c057d24d9e98e33fdb35fb Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 21:28:15 +0200 Subject: [PATCH 035/189] feat: add toggle all notes button to invert lock state of every note --- lib/pages/account.dart | 11 +++++ lib/src/rust/api/account.dart | 3 ++ lib/src/rust/frb_generated.dart | 59 +++++++++++++++++------ macos/Runner.xcodeproj/project.pbxproj | 14 ++---- rust/src/api/account.rs | 6 +++ rust/src/db.rs | 8 +++ rust/src/frb_generated.rs | 67 ++++++++++++++++++++------ 7 files changed, 129 insertions(+), 39 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 5f8806e04..280251dd5 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -1012,6 +1012,7 @@ Widget showNotes(WidgetRef ref, List notes) { return OverflowBar( children: [ IconButton(onPressed: () => onLockRecent(ref, context, currentHeight), tooltip: "Lock recently mined notes", icon: Icon(Icons.table_rows)), + IconButton(onPressed: () => onToggleAll(ref, context), tooltip: "Toggle all notes", icon: Icon(Icons.sync_alt)), IconButton(onPressed: () => onUnlockAll(ref, context), tooltip: "Unlock all notes", icon: Icon(Icons.select_all)), ], ); @@ -1058,6 +1059,16 @@ void onUnlockAll(WidgetRef ref, BuildContext context) async { } } +void onToggleAll(WidgetRef ref, BuildContext context) async { + final c = coinContext.coin; + final confirmed = await confirmDialog(context, title: "Toggle All", message: "Do you want to toggle the lock state of every note?"); + if (confirmed) { + await toggleAllNotes(c: c); + final selectedAccount = ref.read(selectedAccountProvider).requireValue!; + ref.invalidate(accountProvider(selectedAccount.id)); + } +} + void toggleLock(WidgetRef ref, BuildContext context, int id, bool locked) async { final c = coinContext.coin; await lockNote(id: id, locked: locked, c: c); diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index 18c854e5d..d13212c6a 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -160,6 +160,9 @@ Future lockRecentNotes( Future unlockAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); +Future toggleAllNotes({required Coin c}) => + RustLib.instance.api.crateApiAccountToggleAllNotes(c: c); + Future maxSpendable({required Coin c}) => RustLib.instance.api.crateApiAccountMaxSpendable(c: c); diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 603bf6f4c..b2a31a56e 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -94,7 +94,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 607482081; + int get rustContentHash => 587892255; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -560,6 +560,8 @@ abstract class RustLibApi extends BaseApi { TxPlan crateApiPayToPlan({required PcztPackage package, required Coin c}); + Future crateApiAccountToggleAllNotes({required Coin c}); + void crateApiOpenaliasTryValidateZcashAddress( {required String address, required Coin c}); @@ -5171,6 +5173,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["package", "c"], ); + @override + Future crateApiAccountToggleAllNotes({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 158, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountToggleAllNotesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => + const TaskConstMeta( + debugName: "toggle_all_notes", + argNames: ["c"], + ); + @override void crateApiOpenaliasTryValidateZcashAddress( {required String address, required Coin c}) { @@ -5181,7 +5210,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158)!; + funcId: 159)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5207,7 +5236,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159, port: port_); + funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5233,7 +5262,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + funcId: 161, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5259,7 +5288,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5285,7 +5314,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5311,7 +5340,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5341,7 +5370,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164)!; + funcId: 165)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5367,7 +5396,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); + funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5394,7 +5423,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); + funcId: 167, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5423,7 +5452,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); + funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5459,7 +5488,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5491,7 +5520,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + funcId: 170, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5518,7 +5547,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170)!; + funcId: 171)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5547,7 +5576,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171)!; + funcId: 172)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 9a9a0bbe0..92d8e543d 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -298,7 +298,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -421,14 +421,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -608,7 +604,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = "zkool"; + PROVISIONING_PROFILE_SPECIFIER = zkool; SWIFT_VERSION = 5.0; }; name = Profile; @@ -791,7 +787,7 @@ "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = cc.methyl.zkool; - PROVISIONING_PROFILE_SPECIFIER = "zkool"; + PROVISIONING_PROFILE_SPECIFIER = zkool; SWIFT_VERSION = 5.0; }; name = Release; @@ -858,7 +854,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index 7b8d2489c..126ddbbe8 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -737,6 +737,12 @@ pub async fn unlock_all_notes(c: &Coin) -> Result<()> { crate::db::unlock_all_notes(&mut connection, c.account).await } +#[cfg_attr(feature = "flutter", frb)] +pub async fn toggle_all_notes(c: &Coin) -> Result<()> { + let mut connection = c.get_connection().await?; + crate::db::toggle_all_notes(&mut connection, c.account).await +} + #[cfg_attr(feature = "flutter", frb)] pub async fn max_spendable(c: &Coin) -> Result { let mut connection = c.get_connection().await?; diff --git a/rust/src/db.rs b/rust/src/db.rs index 535329e3d..40a3e0d76 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -2070,6 +2070,14 @@ pub async fn lock_recent_notes( Ok(()) } +pub async fn toggle_all_notes(connection: &mut SqliteConnection, account: u32) -> Result<()> { + sqlx::query("UPDATE notes SET locked = NOT locked WHERE account = ?1") + .bind(account) + .execute(connection) + .await?; + Ok(()) +} + pub async fn unlock_all_notes(connection: &mut SqliteConnection, account: u32) -> Result<()> { sqlx::query("UPDATE notes SET locked = FALSE WHERE account = ?1") .bind(account) diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 44f7c8180..f86bec495 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -41,7 +41,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 607482081; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 587892255; // Section: executor @@ -6155,6 +6155,42 @@ fn wire__crate__api__pay__to_plan_impl( }, ) } +fn wire__crate__api__account__toggle_all_notes_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "toggle_all_notes", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::account::toggle_all_notes(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__openalias__try_validate_zcash_address_impl( ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -8867,18 +8903,19 @@ fn pde_ffi_dispatcher_primary_impl( 154 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), 155 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), 156 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 159 => { + 158 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 160 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 160 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 161 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 162 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__transaction__update_historical_prices_impl( + 161 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 162 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 164 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, @@ -8918,16 +8955,16 @@ fn pde_ffi_dispatcher_sync_impl( 144 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), 145 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), 157 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 158 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 159 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 164 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 170 => { + 165 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 171 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 171 => { + 172 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), From 531e4d8d77a9736eaebed9cb404c31db0673ce7d Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 21:45:35 +0200 Subject: [PATCH 036/189] feat: add dust filter toggle for notes (hide ZEC notes <= 5000 zats) --- lib/pages/account.dart | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 280251dd5..7961ce787 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -55,6 +55,7 @@ class AccountViewPageState extends ConsumerState with SingleTic // Tx search final _txSearchController = TextEditingController(); String _txSearchQuery = ''; + bool _showDustNotes = true; @override void initState() { @@ -411,7 +412,7 @@ class AccountViewPageState extends ConsumerState with SingleTic ref.invalidate( accountProvider(selectedAccount.id)); }), - showNotes(ref, account.notes), + showNotes(ref, account.notes, _showDustNotes, () => setState(() => _showDustNotes = !_showDustNotes)), _showZsaHoldings(context, account.zsas), ], )); @@ -1002,11 +1003,15 @@ Widget showMemos(BuildContext context, List memos, VoidCallback onMemoChan ); } -Widget showNotes(WidgetRef ref, List notes) { +Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback onToggleDust) { final t = Theme.of(navigatorKey.currentContext!); final currentHeight = ref.read(currentHeightProvider).value; + final dustThreshold = BigInt.from(5000); + final filtered = showDust + ? notes + : notes.where((n) => n.idAsset != null || n.value > dustThreshold).toList(); return ListView.builder( - itemCount: notes.length + 1, + itemCount: filtered.length + 1, itemBuilder: (context, index) { if (index == 0) return OverflowBar( @@ -1014,11 +1019,16 @@ Widget showNotes(WidgetRef ref, List notes) { IconButton(onPressed: () => onLockRecent(ref, context, currentHeight), tooltip: "Lock recently mined notes", icon: Icon(Icons.table_rows)), IconButton(onPressed: () => onToggleAll(ref, context), tooltip: "Toggle all notes", icon: Icon(Icons.sync_alt)), IconButton(onPressed: () => onUnlockAll(ref, context), tooltip: "Unlock all notes", icon: Icon(Icons.select_all)), + IconButton( + onPressed: onToggleDust, + tooltip: showDust ? "Hide dust notes" : "Show dust notes", + icon: Icon(showDust ? Icons.filter_alt_off : Icons.filter_alt), + ), ], ); final noteIndex = index - 1; - final note = notes[noteIndex]; + final note = filtered[noteIndex]; return ListTile( key: ValueKey(note.id), onTap: () => toggleLock(ref, context, note.id, !note.locked), From b785872644a2c683ff0c1260cba122dcd87c7d6c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 21:52:10 +0200 Subject: [PATCH 037/189] feat: add group by pool toggle for notes view --- lib/pages/account.dart | 72 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 7961ce787..ae0f55a63 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -56,6 +56,7 @@ class AccountViewPageState extends ConsumerState with SingleTic final _txSearchController = TextEditingController(); String _txSearchQuery = ''; bool _showDustNotes = true; + bool _groupByPool = false; @override void initState() { @@ -412,7 +413,7 @@ class AccountViewPageState extends ConsumerState with SingleTic ref.invalidate( accountProvider(selectedAccount.id)); }), - showNotes(ref, account.notes, _showDustNotes, () => setState(() => _showDustNotes = !_showDustNotes)), + showNotes(ref, account.notes, _showDustNotes, () => setState(() => _showDustNotes = !_showDustNotes), _groupByPool, () => setState(() => _groupByPool = !_groupByPool)), _showZsaHoldings(context, account.zsas), ], )); @@ -1003,15 +1004,36 @@ Widget showMemos(BuildContext context, List memos, VoidCallback onMemoChan ); } -Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback onToggleDust) { +Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback onToggleDust, bool groupByPool, VoidCallback onToggleGroup) { final t = Theme.of(navigatorKey.currentContext!); final currentHeight = ref.read(currentHeightProvider).value; final dustThreshold = BigInt.from(5000); final filtered = showDust ? notes : notes.where((n) => n.idAsset != null || n.value > dustThreshold).toList(); + + // Build grouped items: header + its notes + List<({int pool, List poolNotes})> groups = []; + if (groupByPool) { + final grouped = >{}; + for (final n in filtered) { + grouped.putIfAbsent(n.pool, () => []).add(n); + } + // Sort pools in display order: Transparent, Sapling, Orchard, Ironwood + final poolOrder = [0, 1, 2, 3]; + groups = poolOrder + .where((p) => grouped.containsKey(p)) + .map((p) => (pool: p, poolNotes: grouped[p]!)) + .toList(); + } + + // Flattened item count: toolbar + (header + notes per group) or all notes flat + final totalItems = groupByPool + ? 1 + groups.fold(0, (sum, g) => sum + 1 + g.poolNotes.length) + : filtered.length + 1; + return ListView.builder( - itemCount: filtered.length + 1, + itemCount: totalItems, itemBuilder: (context, index) { if (index == 0) return OverflowBar( @@ -1024,9 +1046,53 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback tooltip: showDust ? "Hide dust notes" : "Show dust notes", icon: Icon(showDust ? Icons.filter_alt_off : Icons.filter_alt), ), + IconButton( + onPressed: onToggleGroup, + tooltip: groupByPool ? "Ungroup notes" : "Group by pool", + icon: Icon(groupByPool ? Icons.dashboard : Icons.view_list), + ), ], ); + if (groupByPool) { + // Walk the grouped structure + int offset = 1; + for (final g in groups) { + // Header + if (offset == index) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), + child: Text( + poolToString(g.pool), + style: t.textTheme.titleSmall?.copyWith( + fontWeight: FontWeight.bold, + color: t.colorScheme.primary, + ), + ), + ); + } + offset++; + // Notes in this group + if (index < offset + g.poolNotes.length) { + final note = g.poolNotes[index - offset]; + return ListTile( + key: ValueKey(note.id), + dense: true, + onTap: () => toggleLock(ref, context, note.id, !note.locked), + leading: Text("${note.height}"), + title: Text(poolToString(note.pool)), + trailing: note.idAsset != null + ? Text("${note.value} ${note.assetDisplay}", softWrap: false) + : zatToText(note.value, selectable: false), + textColor: note.locked ? t.disabledColor : null, + ); + } + offset += g.poolNotes.length; + } + // Shouldn't reach here + return const SizedBox.shrink(); + } + final noteIndex = index - 1; final note = filtered[noteIndex]; return ListTile( From 3e63ea7d022c401a762e456020a854a2944b1aa1 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 22:03:18 +0200 Subject: [PATCH 038/189] feat: add lock/unlock all button per pool section header --- lib/pages/account.dart | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index ae0f55a63..da9532e10 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -1060,14 +1060,27 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback for (final g in groups) { // Header if (offset == index) { + final allLocked = g.poolNotes.every((n) => n.locked); return Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), - child: Text( - poolToString(g.pool), - style: t.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.bold, - color: t.colorScheme.primary, - ), + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + children: [ + Expanded( + child: Text( + poolToString(g.pool), + style: t.textTheme.titleSmall?.copyWith( + fontWeight: FontWeight.bold, + color: t.colorScheme.primary, + ), + ), + ), + IconButton( + onPressed: () => onTogglePoolNotes(ref, context, g.poolNotes), + tooltip: allLocked ? "Unlock all in pool" : "Lock all in pool", + icon: Icon(allLocked ? Icons.lock_open : Icons.lock_outline), + visualDensity: VisualDensity.compact, + ), + ], ), ); } @@ -1145,6 +1158,17 @@ void onToggleAll(WidgetRef ref, BuildContext context) async { } } +void onTogglePoolNotes(WidgetRef ref, BuildContext context, List poolNotes) async { + final allLocked = poolNotes.every((n) => n.locked); + final target = !allLocked; + final c = coinContext.coin; + for (final note in poolNotes) { + await lockNote(id: note.id, locked: target, c: c); + } + final selectedAccount = ref.read(selectedAccountProvider).requireValue!; + ref.invalidate(accountProvider(selectedAccount.id)); +} + void toggleLock(WidgetRef ref, BuildContext context, int id, bool locked) async { final c = coinContext.coin; await lockNote(id: id, locked: locked, c: c); From d025a9459f11c7d5808807ac1f9e99f5e96f0413 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 22:36:37 +0200 Subject: [PATCH 039/189] feat: skip migration step when no new blocks since last broadcast --- lib/pages/tx.dart | 15 +++++--- lib/src/rust/api/migrate.dart | 2 +- rust/src/api/migrate.rs | 66 +++++++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 25 deletions(-) diff --git a/lib/pages/tx.dart b/lib/pages/tx.dart index 3b1491c50..4e656fcd5 100644 --- a/lib/pages/tx.dart +++ b/lib/pages/tx.dart @@ -321,10 +321,13 @@ String poolToString(int pool) { } SliverList showTxPlan(BuildContext context, TxPlan txPlan) { + final hasInputs = txPlan.inputs.isNotEmpty; + final hasOutputs = txPlan.outputs.isNotEmpty; + final separatorCount = (hasInputs && hasOutputs) ? 1 : 0; return SliverList.builder( - itemCount: txPlan.inputs.length + txPlan.outputs.length, + itemCount: txPlan.inputs.length + txPlan.outputs.length + separatorCount, itemBuilder: (context, index) { - if (index < txPlan.inputs.length) { + if (hasInputs && index < txPlan.inputs.length) { final input = txPlan.inputs[index]; final isZsa = input.assetName != "ZEC"; return ListTile( @@ -339,12 +342,14 @@ SliverList showTxPlan(BuildContext context, TxPlan txPlan) { if (isZsa) input.assetName, ].join(" · ")), ); + } else if (separatorCount == 1 && index == txPlan.inputs.length) { + return const Divider(height: 24, thickness: 1, indent: 16, endIndent: 16); } else { - final index2 = index - txPlan.inputs.length; - final output = txPlan.outputs[index2]; + final outputIndex = index - txPlan.inputs.length - separatorCount; + final output = txPlan.outputs[outputIndex]; final isZsa = output.assetName != "ZEC"; return ListTile( - leading: Text("Output ${index2 + 1}"), + leading: Text("Output ${outputIndex + 1}"), title: Text("Address: ${output.address}"), trailing: isZsa ? Text(output.amount.toString(), style: TextStyle(color: Colors.purple, fontWeight: FontWeight.bold)) diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index d4f004885..6e6195bf7 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -9,7 +9,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'migrate.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `do_step` +// These functions are ignored because they are not marked as `pub`: `compute_migration_status`, `do_step_status_only`, `do_step` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index 286cb38ff..bdaea6a52 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -75,26 +75,53 @@ pub async fn run_migration( let mut acc_split = 0u64; let mut acc_migrate = 0u64; + let mut last_action_height: Option = None; + let mut last_phase = String::new(); + let mut last_sd_count = 0u32; + let mut last_non_sd_count = 0u32; + let mut last_iw_count = 0u32; + let mut last_progress = 0.0; + let mut last_work = String::new(); loop { - let (event, status) = do_step(c, acc_split, acc_migrate).await?; + let skip = match last_action_height { + Some(h) => client.latest_height().await? <= h, + None => false, + }; - // Accumulate fees from broadcast events. - match &event { - crate::migrate::MigrationEvent::SplitComplete { fee } => acc_split += fee, - crate::migrate::MigrationEvent::MigrateComplete { fee } => acc_migrate += fee, - _ => {} - } + if !skip { + let (event, status) = do_step(c, acc_split, acc_migrate).await?; + + // Track latest counts for the waiting display. + last_phase = status.phase.clone(); + last_sd_count = status.sd_notes_count; + last_non_sd_count = status.non_sd_notes_count; + last_iw_count = status.ironwood_sd_count; + last_progress = status.progress; + last_work = status.work_summary.clone(); - let is_complete = matches!(event, crate::migrate::MigrationEvent::Complete); + // Accumulate fees from broadcast events. + match &event { + crate::migrate::MigrationEvent::SplitComplete { fee } => { + acc_split += fee; + last_action_height = Some(client.latest_height().await?); + } + crate::migrate::MigrationEvent::MigrateComplete { fee } => { + acc_migrate += fee; + last_action_height = Some(client.latest_height().await?); + } + _ => {} + } - sink.add(status.clone()).ok(); + if matches!(event, crate::migrate::MigrationEvent::Complete) { + sink.add(status).ok(); + break; + } - if is_complete { - break; + sink.add(status).ok(); } - // Exponential delay between steps. + // Exponential delay between steps (shared by skip and normal paths). let mean = mean_delay_ms as f64; let u = (OsRng.next_u32() as f64 + 1.0) / (u32::MAX as f64 + 2.0); let delay_ms = ((-mean * u.ln()) as u64).min(mean_delay_ms * 4); @@ -105,18 +132,19 @@ pub async fn run_migration( delay_ms, mean_delay_ms, u ); - // Notify UI of the delay before sleeping, preserving phase + counts. + // Notify UI of the delay before sleeping, preserving the last + // phase/counts so the progress display doesn't blank out. sink.add(MigrationStatus { - phase: status.phase.clone(), + phase: last_phase.clone(), split_fees: acc_split, migrate_fees: acc_migrate, total_fees: acc_split + acc_migrate, - sd_notes_count: status.sd_notes_count, - non_sd_notes_count: status.non_sd_notes_count, - ironwood_sd_count: status.ironwood_sd_count, - progress: status.progress, + sd_notes_count: last_sd_count, + non_sd_notes_count: last_non_sd_count, + ironwood_sd_count: last_iw_count, + progress: last_progress, next_action: format!("Waiting {}s...", delay_secs), - work_summary: status.work_summary.clone(), + work_summary: last_work.clone(), }) .ok(); From 70ea752775874faeeb42280b9f4f4583a449ca35 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Wed, 29 Jul 2026 22:59:01 +0200 Subject: [PATCH 040/189] chore: remove unused imports and variables --- lib/pages/accounts.dart | 1 - lib/pages/currency.dart | 1 - lib/pages/migrate.dart | 1 - lib/widgets/theme.dart | 1 - 4 files changed, 4 deletions(-) diff --git a/lib/pages/accounts.dart b/lib/pages/accounts.dart index aa033b4a5..0138afb6a 100644 --- a/lib/pages/accounts.dart +++ b/lib/pages/accounts.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; diff --git a/lib/pages/currency.dart b/lib/pages/currency.dart index 68375ff15..586d44ec4 100644 --- a/lib/pages/currency.dart +++ b/lib/pages/currency.dart @@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; -import 'package:zkool/main.dart'; import 'package:zkool/src/rust/api/network.dart'; import 'package:zkool/src/rust/api/transaction.dart'; import 'package:zkool/store.dart'; diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 1950cead2..2b939ebbb 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -5,7 +5,6 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; -import 'package:zkool/main.dart'; import 'package:zkool/src/rust/api/migrate.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; diff --git a/lib/widgets/theme.dart b/lib/widgets/theme.dart index e10921c73..da219b758 100644 --- a/lib/widgets/theme.dart +++ b/lib/widgets/theme.dart @@ -183,7 +183,6 @@ class AccountCard extends StatelessWidget { @override Widget build(BuildContext context) { final tt = Theme.of(context).textTheme; - final cs = Theme.of(context).colorScheme; return Padding( padding: const EdgeInsets.all(16), child: Row( From 20707e04520f4cb0f1f710497e8a3cac29a9be54 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 01:01:18 +0200 Subject: [PATCH 041/189] chore: bump zebra and zkool versions in CI --- .github/actions/zebra/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/zebra/action.yml b/.github/actions/zebra/action.yml index 7e48953e2..3e7a85dd9 100644 --- a/.github/actions/zebra/action.yml +++ b/.github/actions/zebra/action.yml @@ -17,7 +17,7 @@ runs: with: path: | ./tools/bin - key: ${{ runner.os }}-zebra-lwd-6.0.0-rc.0 + key: ${{ runner.os }}-zebra-lwd-6.2.1 - name: Install zebra & zaino if: steps.cache-zebra.outputs.cache-hit != 'true' @@ -25,7 +25,7 @@ runs: run: | sudo apt update && sudo apt install -y libclang-dev clang rm -rf ./tools - cargo install --git https://github.com/ZcashFoundation/zebra --tag v6.0.0-rc.0 --features=internal-miner --root ./tools zebrad + cargo install --git https://github.com/ZcashFoundation/zebra --tag v6.2.1 --features=internal-miner --root ./tools zebrad git clone https://github.com/zecrocks/lightwalletd.git cd lightwalletd git checkout 9b69519c57785e04e92a16365483f869dd878700 @@ -34,14 +34,14 @@ runs: - name: Install zkool if: steps.cache-zebra.outputs.cache-hit != 'true' shell: bash - run: cargo install --git https://github.com/hhanh00/zkool2 --tag zkool-v6.24.0-rc.21 --features=graphql --root ./tools --force --bin zkool_graphql + run: cargo install --git https://github.com/hhanh00/zkool2 --tag zkool-v6.25.1 --features=graphql --root ./tools --force --bin zkool_graphql - name: Save cache if: steps.cache-zebra.outputs.cache-hit != 'true' uses: actions/cache/save@v5 with: path: ./tools/bin - key: ${{ runner.os }}-zebra-lwd-6.0.0-rc.0 + key: ${{ runner.os }}-zebra-lwd-6.2.1 - name: Install config if: github.repository != 'hhanh00/zkool2' From 11fe1665bb30410e003b4be890dbd3505cbb8e78 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 02:21:03 +0200 Subject: [PATCH 042/189] fix: add cancellation support for note migration --- lib/pages/migrate.dart | 39 +- lib/src/rust/api/migrate.dart | 22 +- lib/src/rust/frb_generated.dart | 596 ++++++++++++++++++--------- lib/src/rust/frb_generated.io.dart | 81 ++++ lib/src/rust/frb_generated.web.dart | 69 ++++ rust/src/api/migrate.rs | 120 ++++-- rust/src/frb_generated.rs | 609 ++++++++++++++++++---------- 7 files changed, 1083 insertions(+), 453 deletions(-) diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 2b939ebbb..5b0d0c7b8 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -36,6 +36,38 @@ class _MigratePageState extends State "~1h between steps", ]; + Stream _runCancellableMigration({ + required BigInt meanDelayMs, + }) { + final migration = NoteMigration(); + final source = migration.run( + c: coinContext.coin, + meanDelayMs: meanDelayMs, + ); + StreamSubscription? sourceSubscription; + late final StreamController controller; + + controller = StreamController( + onListen: () { + sourceSubscription = source.listen( + controller.add, + onError: controller.addError, + onDone: controller.close, + ); + }, + onPause: () => sourceSubscription?.pause(), + onResume: () => sourceSubscription?.resume(), + onCancel: () async { + await Future.wait([ + migration.cancel(), + if (sourceSubscription != null) sourceSubscription!.cancel(), + ]); + }, + ); + + return controller.stream; + } + @override void initState() { super.initState(); @@ -45,12 +77,12 @@ class _MigratePageState extends State void _startMigration() { try { _sub?.cancel(); - final c = coinContext.coin; final meanDelayMs = BigInt.from(_speedMeanMs[_speedIndex.round()]); - final stream = runMigration(c: c, meanDelayMs: meanDelayMs); + final stream = _runCancellableMigration(meanDelayMs: meanDelayMs); _sub = stream.listen( (status) { + if (!mounted) return; setState(() => _status = status); if (status.nextAction.startsWith('Waiting')) { @@ -366,7 +398,8 @@ class _MigratePageState extends State phase == 'migrating' ? "Orchard: ${status.sdNotesCount} SD | Ironwood: ${status.ironwoodSdCount} SD" : "SD: ${status.sdNotesCount} | Non-SD: ${status.nonSdNotesCount}", - style: tt.bodyLarge), + style: tt.bodyLarge, + ), ], ), ), diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index 6e6195bf7..424c45381 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -9,27 +9,27 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'migrate.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `compute_migration_status`, `do_step_status_only`, `do_step` +// These functions are ignored because they are not marked as `pub`: `do_step`, `run_migration` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). Future stepMigration({required Coin c}) => RustLib.instance.api.crateApiMigrateStepMigration(c: c); -/// Run migration to completion, streaming MigrationStatus to Flutter. -/// -/// `mean_delay_ms` controls the mean wait time (in milliseconds) of the -/// exponential random delay between migration steps. Longer delays make -/// it harder for an observer to correlate the transactions. -Stream runMigration( - {required Coin c, required BigInt meanDelayMs}) => - RustLib.instance.api - .crateApiMigrateRunMigration(c: c, meanDelayMs: meanDelayMs); - /// Stub kept for FRB generated-code compatibility. Future getMigrationStatus({required Coin c}) => RustLib.instance.api.crateApiMigrateGetMigrationStatus(c: c); +// Rust type: RustOpaqueMoi> +abstract class NoteMigration implements RustOpaqueInterface { + Future cancel(); + + factory NoteMigration() => + RustLib.instance.api.crateApiMigrateNoteMigrationNew(); + + Stream run({required Coin c, required BigInt meanDelayMs}); +} + @freezed sealed class MigrationEvent with _$MigrationEvent { const MigrationEvent._(); diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index b2a31a56e..e9b24589b 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -94,7 +94,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 587892255; + int get rustContentHash => -492919685; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -149,6 +149,16 @@ abstract class RustLibApi extends BaseApi { Stream crateApiMempoolMempoolRun( {required Mempool that, required Coin c}); + Future crateApiMigrateNoteMigrationCancel( + {required NoteMigration that}); + + NoteMigration crateApiMigrateNoteMigrationNew(); + + Stream crateApiMigrateNoteMigrationRun( + {required NoteMigration that, + required Coin c, + required BigInt meanDelayMs}); + Future crateApiSweepTransparentScannerCancel( {required TransparentScanner that}); @@ -494,9 +504,6 @@ abstract class RustLibApi extends BaseApi { Future crateApiSyncRewindSync( {required int height, required int account, required Coin c}); - Stream crateApiMigrateRunMigration( - {required Coin c, required BigInt meanDelayMs}); - Future crateApiPaySend( {required int height, required List data, required Coin c}); @@ -616,6 +623,15 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_NoteMigration; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_NoteMigration; + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner; @@ -955,6 +971,99 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["that", "mempoolSink", "c"], ); + @override + Future crateApiMigrateNoteMigrationCancel( + {required NoteMigration that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 10, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationCancelConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => + const TaskConstMeta( + debugName: "NoteMigration_cancel", + argNames: ["that"], + ); + + @override + NoteMigration crateApiMigrateNoteMigrationNew() { + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => + const TaskConstMeta( + debugName: "NoteMigration_new", + argNames: [], + ); + + @override + Stream crateApiMigrateNoteMigrationRun( + {required NoteMigration that, + required Coin c, + required BigInt meanDelayMs}) { + final sink = RustStreamSink(); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + sse_encode_StreamSink_migration_status_Sse(sink, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_u_64(meanDelayMs, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 12, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateNoteMigrationRunConstMeta, + argValues: [that, sink, c, meanDelayMs], + apiImpl: this, + ), + ), + ); + return sink.stream; + } + + TaskConstMeta get kCrateApiMigrateNoteMigrationRunConstMeta => + const TaskConstMeta( + debugName: "NoteMigration_run", + argNames: ["that", "sink", "c", "meanDelayMs"], + ); + @override Future crateApiSweepTransparentScannerCancel( {required TransparentScanner that}) { @@ -965,7 +1074,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 10, port: port_); + funcId: 13, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -991,7 +1100,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 11, port: port_); + funcId: 14, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -1030,7 +1139,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(gapLimit, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 12, port: port_); + funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1059,7 +1168,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 13, port: port_); + funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pool_balance, @@ -1088,7 +1197,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(txBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 14, port: port_); + funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1115,7 +1224,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_recipient(recipients, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 15, port: port_); + funcId: 18, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1143,7 +1252,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 16, port: port_); + funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1169,7 +1278,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 17, port: port_); + funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1194,7 +1303,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 18, port: port_); + funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1227,7 +1336,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 19, port: port_); + funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1251,7 +1360,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23)!; }, codec: SseCodec( decodeSuccessData: sse_decode_sapling_params_status, @@ -1278,7 +1387,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 21, port: port_); + funcId: 24, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1304,7 +1413,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 22, port: port_); + funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1329,7 +1438,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1358,7 +1467,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(dbFilepath, serializer); sse_encode_opt_String(password, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 24, port: port_); + funcId: 27, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1387,7 +1496,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_32(account, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 25, port: port_); + funcId: 28, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1415,7 +1524,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_8(serverType, serializer); sse_encode_String(url, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1441,7 +1550,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_String(proxy, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1469,7 +1578,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_bool(useTor, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 28, port: port_); + funcId: 31, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1502,7 +1611,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 29, port: port_); + funcId: 32, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_contact, @@ -1531,7 +1640,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 30, port: port_); + funcId: 33, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -1560,7 +1669,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 31, port: port_); + funcId: 34, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_folder, @@ -1587,7 +1696,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(packet, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 32, port: port_); + funcId: 35, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, @@ -1615,7 +1724,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 33, port: port_); + funcId: 36, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1644,7 +1753,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 34, port: port_); + funcId: 37, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1673,7 +1782,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 35, port: port_); + funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1702,7 +1811,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 36, port: port_); + funcId: 39, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1732,7 +1841,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_dkg_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 37, port: port_); + funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1763,7 +1872,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_signing_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 38, port: port_); + funcId: 41, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1790,7 +1899,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 39, port: port_); + funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1817,7 +1926,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_signing_event(a, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 40, port: port_); + funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1845,7 +1954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(path, serializer); sse_encode_box_autoadd_raptor_q_params(params, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 41, port: port_); + funcId: 44, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_list_prim_u_8_strict, @@ -1870,7 +1979,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 42, port: port_); + funcId: 45, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1899,7 +2008,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(passphrase, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 43, port: port_); + funcId: 46, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -1926,7 +2035,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 44, port: port_); + funcId: 47, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1954,7 +2063,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 45, port: port_); + funcId: 48, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -1984,7 +2093,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(aggregate, serializer); sse_encode_u_8(poolFilter, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 46, port: port_); + funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2015,7 +2124,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 47, port: port_); + funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_u_32_f_64, @@ -2045,7 +2154,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 48, port: port_); + funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_string_f_64_bool, @@ -2073,7 +2182,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 49, port: port_); + funcId: 52, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2102,7 +2211,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 50, port: port_); + funcId: 53, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2131,7 +2240,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(currency, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 51, port: port_); + funcId: 54, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2160,7 +2269,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 52, port: port_); + funcId: 55, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact_match, @@ -2186,7 +2295,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 53, port: port_); + funcId: 56, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_frost_sign_params, @@ -2213,7 +2322,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 54, port: port_); + funcId: 57, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2240,7 +2349,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 55, port: port_); + funcId: 58, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2265,7 +2374,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 59)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2294,7 +2403,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 57, port: port_); + funcId: 60, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2323,7 +2432,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 58, port: port_); + funcId: 61, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2350,7 +2459,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 59, port: port_); + funcId: 62, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, @@ -2379,7 +2488,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 60, port: port_); + funcId: 63, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2408,7 +2517,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 61, port: port_); + funcId: 64, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_seed, @@ -2438,7 +2547,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(pools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 62, port: port_); + funcId: 65, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2467,7 +2576,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 63, port: port_); + funcId: 66, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2496,7 +2605,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 64, port: port_); + funcId: 67, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -2523,7 +2632,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); + funcId: 68, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2550,7 +2659,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); + funcId: 69, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -2576,7 +2685,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); + funcId: 70, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2608,7 +2717,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); + funcId: 71, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -2637,7 +2746,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 69, port: port_); + funcId: 72, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2664,7 +2773,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73)!; }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2692,7 +2801,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 71, port: port_); + funcId: 74, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2719,7 +2828,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); + funcId: 75, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -2746,7 +2855,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 73, port: port_); + funcId: 76, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2774,7 +2883,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 74, port: port_); + funcId: 77, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2799,7 +2908,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!; }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2826,7 +2935,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 76, port: port_); + funcId: 79, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2852,7 +2961,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); + funcId: 80, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2880,7 +2989,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 78, port: port_); + funcId: 81, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -2907,7 +3016,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 79, port: port_); + funcId: 82, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2934,7 +3043,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); + funcId: 83, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2960,7 +3069,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); + funcId: 84, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2990,7 +3099,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); + funcId: 85, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3019,7 +3128,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 83, port: port_); + funcId: 86, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3045,7 +3154,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); + funcId: 87, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3070,7 +3179,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); + funcId: 88, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3096,7 +3205,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); + funcId: 89, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3122,7 +3231,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); + funcId: 90, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3148,7 +3257,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 88, port: port_); + funcId: 91, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3172,7 +3281,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 92)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3205,7 +3314,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 90, port: port_); + funcId: 93, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3233,7 +3342,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( append, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); + funcId: 94, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -3262,7 +3371,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 92, port: port_); + funcId: 95, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -3289,7 +3398,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 93, port: port_); + funcId: 96, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3316,7 +3425,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); + funcId: 97, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3343,7 +3452,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3368,7 +3477,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3394,7 +3503,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 100)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3420,7 +3530,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 101)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3445,7 +3556,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 102)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3473,7 +3585,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 100)!; + funcId: 103)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3500,7 +3612,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 101, port: port_); + funcId: 104, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3539,7 +3651,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 102, port: port_); + funcId: 105, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3581,7 +3693,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 103, port: port_); + funcId: 106, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -3608,7 +3720,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 104, port: port_); + funcId: 107, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -3635,7 +3747,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105, port: port_); + funcId: 108, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3663,7 +3775,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106, port: port_); + funcId: 109, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -3689,7 +3801,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107, port: port_); + funcId: 110, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3715,7 +3827,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108, port: port_); + funcId: 111, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -3741,7 +3853,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109, port: port_); + funcId: 112, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -3767,7 +3879,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); + funcId: 113, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -3793,7 +3905,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); + funcId: 114, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -3819,7 +3931,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); + funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -3846,7 +3958,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); + funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -3875,7 +3987,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); + funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3904,7 +4016,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3931,7 +4043,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -3960,7 +4072,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + funcId: 120, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -3986,7 +4098,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4014,7 +4126,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4041,7 +4153,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120)!; + funcId: 123)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -4072,7 +4184,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); + funcId: 124, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4103,7 +4215,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4131,7 +4243,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); + funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4160,7 +4272,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + funcId: 127, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4186,7 +4298,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -4212,7 +4324,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + funcId: 129, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4241,7 +4353,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127)!; + funcId: 130)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4270,7 +4382,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128, port: port_); + funcId: 131, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4299,7 +4411,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); + funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4327,7 +4439,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); + funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4357,7 +4469,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + funcId: 134, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4387,7 +4499,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4414,7 +4526,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + funcId: 136, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4441,7 +4553,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); + funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4469,7 +4581,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); + funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4497,7 +4609,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); + funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4525,7 +4637,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4555,7 +4667,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + funcId: 141, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4573,40 +4685,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["height", "account", "c"], ); - @override - Stream crateApiMigrateRunMigration( - {required Coin c, required BigInt meanDelayMs}) { - final sink = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_migration_status_Sse(sink, serializer); - sse_encode_box_autoadd_coin(c, serializer); - sse_encode_u_64(meanDelayMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateRunMigrationConstMeta, - argValues: [sink, c, meanDelayMs], - apiImpl: this, - ), - ), - ); - return sink.stream; - } - - TaskConstMeta get kCrateApiMigrateRunMigrationConstMeta => - const TaskConstMeta( - debugName: "run_migration", - argNames: ["sink", "c", "meanDelayMs"], - ); - @override Future crateApiPaySend( {required int height, required List data, required Coin c}) { @@ -4618,7 +4696,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4647,7 +4725,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); + funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4676,7 +4754,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + funcId: 144, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4713,7 +4791,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); + funcId: 145, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4739,7 +4817,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144)!; + funcId: 146)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4766,7 +4844,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145)!; + funcId: 147)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4796,7 +4874,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146, port: port_); + funcId: 148, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4826,7 +4904,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147, port: port_); + funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4856,7 +4934,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4886,7 +4964,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4913,7 +4991,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + funcId: 152, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4941,7 +5019,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); + funcId: 153, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4973,7 +5051,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152, port: port_); + funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5004,7 +5082,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); + funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5030,7 +5108,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5066,7 +5144,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + funcId: 157, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5108,7 +5186,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + funcId: 158, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -5155,7 +5233,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157)!; + funcId: 159)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5181,7 +5259,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); + funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5210,7 +5288,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159)!; + funcId: 161)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5236,7 +5314,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5262,7 +5340,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5288,7 +5366,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5314,7 +5392,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + funcId: 165, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5340,7 +5418,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); + funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5370,7 +5448,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165)!; + funcId: 167)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5396,7 +5474,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); + funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5423,7 +5501,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); + funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5452,7 +5530,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + funcId: 170, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5488,7 +5566,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + funcId: 171, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5520,7 +5598,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); + funcId: 172, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5547,7 +5625,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171)!; + funcId: 173)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5576,7 +5654,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172)!; + funcId: 174)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5645,6 +5723,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { get rust_arc_decrement_strong_count_Mempool => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_NoteMigration => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_NoteMigration => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner => wire .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @@ -5675,6 +5761,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return MempoolImpl.frbInternalDcoDecode(raw as List); } + @protected + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return NoteMigrationImpl.frbInternalDcoDecode(raw as List); + } + @protected TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -5707,6 +5801,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return DartVaultImpl.frbInternalDcoDecode(raw as List); } + @protected + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return NoteMigrationImpl.frbInternalDcoDecode(raw as List); + } + @protected TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -5745,6 +5847,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return MempoolImpl.frbInternalDcoDecode(raw as List); } + @protected + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return NoteMigrationImpl.frbInternalDcoDecode(raw as List); + } + @protected TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -7202,6 +7312,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -7238,6 +7357,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -7272,6 +7400,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -9012,6 +9149,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { (self as MempoolImpl).frbInternalSseEncode(move: true), serializer); } + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: true), + serializer); + } + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -9050,6 +9197,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { (self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); } + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: false), + serializer); + } + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -9098,6 +9255,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { (self as MempoolImpl).frbInternalSseEncode(move: null), serializer); } + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: null), + serializer); + } + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -10627,6 +10794,35 @@ class MempoolImpl extends RustOpaque implements Mempool { RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); } +@sealed +class NoteMigrationImpl extends RustOpaque implements NoteMigration { + // Not to be used by end users + NoteMigrationImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_NoteMigration, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigration, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigrationPtr, + ); + + Future cancel() => + RustLib.instance.api.crateApiMigrateNoteMigrationCancel( + that: this, + ); + + Stream run({required Coin c, required BigInt meanDelayMs}) => + RustLib.instance.api.crateApiMigrateNoteMigrationRun( + that: this, c: c, meanDelayMs: meanDelayMs); +} + @sealed class TransparentScannerImpl extends RustOpaque implements TransparentScanner { // Not to be used by end users diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index ed3adf788..54fd0b567 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -47,6 +47,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; @@ -64,6 +68,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( dynamic raw); + @protected + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -84,6 +93,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( dynamic raw); + @protected + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -107,6 +121,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( dynamic raw); + @protected + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -556,6 +575,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -576,6 +600,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -594,6 +623,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1064,6 +1098,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( Mempool self, SseSerializer serializer); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1084,6 +1123,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( DartVault self, SseSerializer serializer); + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1107,6 +1151,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( Mempool self, SseSerializer serializer); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1670,6 +1719,38 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction)>(); + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr = + _lookup)>>( + 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration'); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr + .asFunction)>(); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr = + _lookup)>>( + 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration'); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr + .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer ptr, diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index d84b08de5..85135bd8a 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -49,6 +49,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @@ -66,6 +70,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( dynamic raw); + @protected + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -86,6 +95,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( dynamic raw); + @protected + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -109,6 +123,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( dynamic raw); + @protected + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); + @protected TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -558,6 +577,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -578,6 +602,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -596,6 +625,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( SseDeserializer deserializer); + @protected + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); + @protected TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1066,6 +1100,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( Mempool self, SseSerializer serializer); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1086,6 +1125,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( DartVault self, SseSerializer serializer); + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1109,6 +1153,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( Mempool self, SseSerializer serializer); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1623,6 +1672,18 @@ class RustLibWire implements BaseWire { .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( int ptr) => wasmModule @@ -1658,6 +1719,14 @@ extension type RustLibWasmModule._(JSObject _) implements JSObject { rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr); + + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( int ptr); diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index bdaea6a52..1630c870f 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use tokio_util::sync::CancellationToken; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; @@ -32,6 +33,40 @@ pub enum MigrationEvent { Error { message: String }, } +#[cfg_attr(feature = "flutter", frb(opaque))] +pub struct NoteMigration { + cancellation_token: CancellationToken, +} + +impl NoteMigration { + #[cfg_attr(feature = "flutter", frb(sync))] + pub fn new() -> Self { + Self { + cancellation_token: CancellationToken::new(), + } + } + + #[cfg(feature = "flutter")] + pub async fn run( + &self, + sink: StreamSink, + c: &Coin, + mean_delay_ms: u64, + ) -> Result<()> { + run_migration( + sink, + c, + mean_delay_ms, + self.cancellation_token.clone(), + ) + .await + } + + pub fn cancel(&self) { + self.cancellation_token.cancel(); + } +} + /// Single-shot step (kept for FRB generated-code compatibility). #[cfg_attr(feature = "flutter", frb)] pub async fn step_migration(c: &Coin) -> Result { @@ -49,11 +84,12 @@ pub async fn step_migration(c: &Coin) -> Result { /// `mean_delay_ms` controls the mean wait time (in milliseconds) of the /// exponential random delay between migration steps. Longer delays make /// it harder for an observer to correlate the transactions. -#[cfg_attr(feature = "flutter", frb)] -pub async fn run_migration( +#[cfg(feature = "flutter")] +async fn run_migration( sink: StreamSink, c: &Coin, mean_delay_ms: u64, + cancellation_token: CancellationToken, ) -> Result<()> { use rand_core::{OsRng, RngCore}; use zcash_protocol::consensus::{BlockHeight, NetworkUpgrade, Parameters}; @@ -84,41 +120,54 @@ pub async fn run_migration( let mut last_work = String::new(); loop { - let skip = match last_action_height { - Some(h) => client.latest_height().await? <= h, - None => false, - }; + let complete = tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + tracing::info!("Note migration cancelled"); + break; + } + result = async { + let skip = match last_action_height { + Some(h) => client.latest_height().await? <= h, + None => false, + }; - if !skip { - let (event, status) = do_step(c, acc_split, acc_migrate).await?; - - // Track latest counts for the waiting display. - last_phase = status.phase.clone(); - last_sd_count = status.sd_notes_count; - last_non_sd_count = status.non_sd_notes_count; - last_iw_count = status.ironwood_sd_count; - last_progress = status.progress; - last_work = status.work_summary.clone(); - - // Accumulate fees from broadcast events. - match &event { - crate::migrate::MigrationEvent::SplitComplete { fee } => { - acc_split += fee; - last_action_height = Some(client.latest_height().await?); + if skip { + return Ok::(false); } - crate::migrate::MigrationEvent::MigrateComplete { fee } => { - acc_migrate += fee; - last_action_height = Some(client.latest_height().await?); + + let (event, status) = do_step(c, acc_split, acc_migrate).await?; + + // Track latest counts for the waiting display. + last_phase = status.phase.clone(); + last_sd_count = status.sd_notes_count; + last_non_sd_count = status.non_sd_notes_count; + last_iw_count = status.ironwood_sd_count; + last_progress = status.progress; + last_work = status.work_summary.clone(); + + // Accumulate fees from broadcast events. + match &event { + crate::migrate::MigrationEvent::SplitComplete { fee } => { + acc_split += fee; + last_action_height = Some(client.latest_height().await?); + } + crate::migrate::MigrationEvent::MigrateComplete { fee } => { + acc_migrate += fee; + last_action_height = Some(client.latest_height().await?); + } + _ => {} } - _ => {} - } - if matches!(event, crate::migrate::MigrationEvent::Complete) { + let complete = + matches!(event, crate::migrate::MigrationEvent::Complete); sink.add(status).ok(); - break; - } + Ok(complete) + } => result?, + }; - sink.add(status).ok(); + if complete { + break; } // Exponential delay between steps (shared by skip and normal paths). @@ -148,7 +197,14 @@ pub async fn run_migration( }) .ok(); - tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; + tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + tracing::info!("Note migration cancelled"); + break; + } + _ = tokio::time::sleep(std::time::Duration::from_millis(delay_ms)) => {} + } } Ok(()) diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index f86bec495..2614287cd 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -27,6 +27,7 @@ // Section: imports use crate::api::mempool::*; +use crate::api::migrate::*; use crate::api::sweep::*; use crate::api::vault::*; use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; @@ -41,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 587892255; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -492919685; // Section: executor @@ -564,6 +565,153 @@ fn wire__crate__api__mempool__Mempool_run_impl( }, ) } +fn wire__crate__api__migrate__NoteMigration_cancel_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "NoteMigration_cancel", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::migrate::NoteMigration::cancel(&*api_that_guard); + })?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__migrate__NoteMigration_new_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "NoteMigration_new", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + transform_result_sse::<_, ()>((move || { + let output_ok = Result::<_, ()>::Ok(crate::api::migrate::NoteMigration::new())?; + Ok(output_ok) + })()) + }, + ) +} +fn wire__crate__api__migrate__NoteMigration_run_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "NoteMigration_run", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_sink = >::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + let api_mean_delay_ms = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::migrate::NoteMigration::run( + &*api_that_guard, + api_sink, + &api_c, + api_mean_delay_ms, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__sweep__TransparentScanner_cancel_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5388,49 +5536,6 @@ fn wire__crate__api__sync__rewind_sync_impl( }, ) } -fn wire__crate__api__migrate__run_migration_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "run_migration", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_sink = >::sse_decode(&mut deserializer); - let api_c = ::sse_decode(&mut deserializer); - let api_mean_delay_ms = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || async move { - let output_ok = - crate::api::migrate::run_migration(api_sink, &api_c, api_mean_delay_ms) - .await?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} fn wire__crate__api__pay__send_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -6730,6 +6835,9 @@ flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); @@ -6764,6 +6872,16 @@ impl SseDecode for Mempool { } } +impl SseDecode for NoteMigration { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + impl SseDecode for TransparentScanner { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -6800,6 +6918,16 @@ impl SseDecode for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + impl SseDecode for RustOpaqueMoi> { @@ -8649,273 +8777,276 @@ fn pde_ffi_dispatcher_primary_impl( 6 => wire__crate__api__vault__DartVault_test_impl(port, ptr, rust_vec_len, data_len), 7 => wire__crate__api__mempool__Mempool_cancel_impl(port, ptr, rust_vec_len, data_len), 9 => wire__crate__api__mempool__Mempool_run_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__api__sweep__TransparentScanner_cancel_impl( + 10 => { + wire__crate__api__migrate__NoteMigration_cancel_impl(port, ptr, rust_vec_len, data_len) + } + 12 => wire__crate__api__migrate__NoteMigration_run_impl(port, ptr, rust_vec_len, data_len), + 13 => wire__crate__api__sweep__TransparentScanner_cancel_impl( port, ptr, rust_vec_len, data_len, ), - 11 => { + 14 => { wire__crate__api__sweep__TransparentScanner_new_impl(port, ptr, rust_vec_len, data_len) } - 12 => { + 15 => { wire__crate__api__sweep__TransparentScanner_run_impl(port, ptr, rust_vec_len, data_len) } - 13 => wire__crate__api__sync__balance_impl(port, ptr, rust_vec_len, data_len), - 14 => wire__crate__api__pay__broadcast_transaction_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__pay__build_puri_impl(port, ptr, rust_vec_len, data_len), - 16 => wire__crate__api__sync__cache_block_time_impl(port, ptr, rust_vec_len, data_len), - 17 => wire__crate__api__frost__cancel_dkg_impl(port, ptr, rust_vec_len, data_len), - 18 => wire__crate__api__sync__cancel_sync_impl(port, ptr, rust_vec_len, data_len), - 19 => wire__crate__api__db__change_db_password_impl(port, ptr, rust_vec_len, data_len), - 21 => wire__crate__api__coin__close_pool_impl(port, ptr, rust_vec_len, data_len), - 22 => wire__crate__api__coin__coin_get_name_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__coin__coin_open_database_impl(port, ptr, rust_vec_len, data_len), - 25 => wire__crate__api__coin__coin_set_account_impl(port, ptr, rust_vec_len, data_len), - 28 => wire__crate__api__coin__coin_set_use_tor_impl(port, ptr, rust_vec_len, data_len), - 29 => wire__crate__api__contacts__create_contact_impl(port, ptr, rust_vec_len, data_len), - 30 => { + 16 => wire__crate__api__sync__balance_impl(port, ptr, rust_vec_len, data_len), + 17 => wire__crate__api__pay__broadcast_transaction_impl(port, ptr, rust_vec_len, data_len), + 18 => wire__crate__api__pay__build_puri_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__sync__cache_block_time_impl(port, ptr, rust_vec_len, data_len), + 20 => wire__crate__api__frost__cancel_dkg_impl(port, ptr, rust_vec_len, data_len), + 21 => wire__crate__api__sync__cancel_sync_impl(port, ptr, rust_vec_len, data_len), + 22 => wire__crate__api__db__change_db_password_impl(port, ptr, rust_vec_len, data_len), + 24 => wire__crate__api__coin__close_pool_impl(port, ptr, rust_vec_len, data_len), + 25 => wire__crate__api__coin__coin_get_name_impl(port, ptr, rust_vec_len, data_len), + 27 => wire__crate__api__coin__coin_open_database_impl(port, ptr, rust_vec_len, data_len), + 28 => wire__crate__api__coin__coin_set_account_impl(port, ptr, rust_vec_len, data_len), + 31 => wire__crate__api__coin__coin_set_use_tor_impl(port, ptr, rust_vec_len, data_len), + 32 => wire__crate__api__contacts__create_contact_impl(port, ptr, rust_vec_len, data_len), + 33 => { wire__crate__api__account__create_new_category_impl(port, ptr, rust_vec_len, data_len) } - 31 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), - 32 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), - 33 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), - 34 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), - 35 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), - 36 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), - 37 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), - 38 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), - 39 => wire__crate__api__sapling__download_sapling_params_impl( + 34 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), + 35 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), + 36 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), + 37 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), + 38 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), + 39 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), + 40 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), + 42 => wire__crate__api__sapling__download_sapling_params_impl( port, ptr, rust_vec_len, data_len, ), - 40 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), - 41 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), - 44 => wire__crate__api__contacts__export_contacts_vcard_impl( + 43 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), + 44 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), + 45 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), + 46 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__contacts__export_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 45 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), - 46 => wire__crate__api__account__fetch_address_tx_count_impl( + 48 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__crate__api__account__fetch_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 47 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), - 48 => wire__crate__api__transaction__fetch_category_amounts_impl( + 50 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__transaction__fetch_category_amounts_impl( port, ptr, rust_vec_len, data_len, ), - 49 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( + 52 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 50 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), - 51 => wire__crate__api__transaction__fill_missing_tx_prices_impl( + 53 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__transaction__fill_missing_tx_prices_impl( port, ptr, rust_vec_len, data_len, ), - 52 => wire__crate__api__contacts__find_contacts_for_address_impl( + 55 => wire__crate__api__contacts__find_contacts_for_address_impl( port, ptr, rust_vec_len, data_len, ), - 53 => wire__crate__api__frost__frost_sign_params_default_impl( + 56 => wire__crate__api__frost__frost_sign_params_default_impl( port, ptr, rust_vec_len, data_len, ), - 54 => wire__crate__api__account__generate_next_change_address_impl( + 57 => wire__crate__api__account__generate_next_change_address_impl( port, ptr, rust_vec_len, data_len, ), - 55 => { + 58 => { wire__crate__api__account__generate_next_dindex_impl(port, ptr, rust_vec_len, data_len) } - 57 => { + 60 => { wire__crate__api__account__get_account_addresses_impl(port, ptr, rust_vec_len, data_len) } - 58 => wire__crate__api__account__get_account_fingerprint_impl( + 61 => wire__crate__api__account__get_account_fingerprint_impl( port, ptr, rust_vec_len, data_len, ), - 59 => wire__crate__api__account__get_account_frost_params_impl( + 62 => wire__crate__api__account__get_account_frost_params_impl( port, ptr, rust_vec_len, data_len, ), - 60 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), - 61 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), - 62 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), - 63 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), - 64 => { + 63 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), + 64 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), + 65 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), + 66 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), + 67 => { wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) } - 65 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), - 66 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), - 67 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 68 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 69 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), - 71 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), - 72 => { + 68 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), + 69 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), + 70 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 71 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 72 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), + 75 => { wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) } - 73 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), - 74 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), - 76 => wire__crate__api__network__get_supported_vs_currencies_impl( + 76 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), + 77 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), + 79 => wire__crate__api__network__get_supported_vs_currencies_impl( port, ptr, rust_vec_len, data_len, ), - 77 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), - 78 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), - 79 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 80 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 81 => wire__crate__api__account__has_transparent_pub_key_impl( + 80 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), + 81 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), + 82 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 83 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 84 => wire__crate__api__account__has_transparent_pub_key_impl( port, ptr, rust_vec_len, data_len, ), - 82 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), - 83 => wire__crate__api__contacts__import_contacts_vcard_impl( + 85 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), + 86 => wire__crate__api__contacts__import_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 84 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), - 85 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), - 86 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 87 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 88 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), - 90 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), - 92 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), - 93 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), - 94 => { + 87 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), + 88 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 90 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), + 93 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), + 94 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), + 95 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), + 96 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), + 97 => { wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) } - 101 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 102 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 103 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 104 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 105 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 106 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 107 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 108 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 109 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 110 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 104 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 105 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 106 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 107 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 108 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 109 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 110 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 114 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 115 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 121 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 128 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 129 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 135 => { + 124 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 129 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 138 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 136 => wire__crate__api__openalias__resolve_openalias_all_impl( + 139 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 137 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 140 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 138 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 139 => wire__crate__api__migrate__run_migration_impl(port, ptr, rust_vec_len, data_len), - 140 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 141 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 146 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 147 => { + 141 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 149 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 148 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 150 => wire__crate__api__account__show_ledger_sapling_address_impl( + 150 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 151 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 152 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 151 => wire__crate__api__account__show_ledger_transparent_address_impl( + 153 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 152 => wire__crate__api__account__sign_ledger_transaction_impl( + 154 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 153 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 154 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 155 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 160 => { + 155 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 160 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 162 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 161 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 162 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__transaction__update_historical_prices_impl( + 163 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 164 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 172 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, @@ -8934,37 +9065,38 @@ fn pde_ffi_dispatcher_sync_impl( // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), - 20 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), - 23 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), - 26 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), - 27 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), - 56 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), - 70 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), - 75 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), - 89 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), - 95 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), - 96 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), - 97 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), - 98 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 99 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 100 => { + 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), + 23 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), + 26 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), + 29 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), + 30 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), + 59 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), + 73 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), + 78 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), + 92 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), + 98 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), + 99 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), + 100 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), + 101 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), + 102 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 103 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 120 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 127 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 144 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 145 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 157 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 159 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 123 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 130 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 146 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 147 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 159 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 161 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 165 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 171 => { + 167 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 173 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 172 => { + 174 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -9003,6 +9135,21 @@ impl flutter_rust_bridge::IntoIntoDart> for Mempool { } } +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for NoteMigration { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -10273,6 +10420,13 @@ impl SseEncode for Mempool { } } +impl SseEncode for NoteMigration { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + impl SseEncode for TransparentScanner { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -10307,6 +10461,17 @@ impl SseEncode for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + impl SseEncode for RustOpaqueMoi> { @@ -11679,6 +11844,7 @@ mod io { use super::*; use crate::api::mempool::*; + use crate::api::migrate::*; use crate::api::sweep::*; use crate::api::vault::*; use flutter_rust_bridge::for_generated::byteorder::{ @@ -11719,6 +11885,20 @@ mod io { MoiArc::>::decrement_strong_count(ptr as _); } + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[unsafe(no_mangle)] pub extern "C" fn frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ptr: *const std::ffi::c_void, @@ -11746,6 +11926,7 @@ mod web { use super::*; use crate::api::mempool::*; + use crate::api::migrate::*; use crate::api::sweep::*; use crate::api::vault::*; use flutter_rust_bridge::for_generated::byteorder::{ @@ -11788,6 +11969,20 @@ mod web { MoiArc::>::decrement_strong_count(ptr as _); } + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ptr: *const std::ffi::c_void, From 961a8a8bd905d8d0051bffffe90c5655f504ff56 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 02:35:34 +0200 Subject: [PATCH 043/189] fix: confirm before leaving active migration --- lib/pages/migrate.dart | 173 +++++++++++++++++++++++++++++++---------- 1 file changed, 134 insertions(+), 39 deletions(-) diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 5b0d0c7b8..e6defce43 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -25,6 +25,7 @@ class _MigratePageState extends State int _countdownSecs = 0; bool _started = false; bool _didShowCompleteDialog = false; + bool _handlingLeave = false; double _speedIndex = 1; // default: Fast (60s) static const _speedLabels = ["Very Fast", "Fast", "Medium", "Slow"]; @@ -171,19 +172,61 @@ class _MigratePageState extends State } if (status == null) { - return Scaffold( - appBar: AppBar(title: const Text("Note Migration")), - body: _started - ? const Center(child: CircularProgressIndicator()) - : ListView( - padding: const EdgeInsets.all(16), - children: [ - Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + return _withLeaveGuard( + context, + confirmLeave: _started, + child: Scaffold( + appBar: AppBar( + leading: BackButton( + onPressed: () => _requestLeave( + context, + confirmLeave: _started, + ), + ), + title: const Text("Note Migration"), + ), + body: _started + ? Center( + child: Card( + margin: const EdgeInsets.all(24), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 420), + child: const Padding( + padding: EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircularProgressIndicator(), + Gap(20), + Text( + "Preparing Migration", + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + Gap(8), + Text( + "Syncing your wallet and scanning Orchard notes " + "before the first migration step. This may take " + "a moment.", + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ), + ) + : ListView( + padding: const EdgeInsets.all(16), + children: [ + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Text("Orchard to Ironwood Migration", style: Theme.of(context).textTheme.headlineSmall), const Gap(12), @@ -274,20 +317,21 @@ class _MigratePageState extends State ), ), const Gap(16), - FilledButton.icon( - onPressed: () { - setState(() => _started = true); - _startMigration(); - }, - icon: const Icon(Icons.play_arrow), - label: const Text("Start Migration"), - ), - ], + FilledButton.icon( + onPressed: () { + setState(() => _started = true); + _startMigration(); + }, + icon: const Icon(Icons.play_arrow), + label: const Text("Start Migration"), + ), + ], + ), ), ), - ), - ], - ), + ], + ), + ), ); } @@ -297,21 +341,34 @@ class _MigratePageState extends State final waiting = status.nextAction.startsWith('Waiting'); final isComplete = phase == 'complete'; final isActive = phase == 'splitting' || phase == 'migrating' || waiting; + final confirmLeave = _started && !isComplete; - return Scaffold( - appBar: AppBar( - title: const Text("Note Migration"), - actions: [ - IconButton( - tooltip: "Close", - onPressed: () => GoRouter.of(context).pop(), - icon: const Icon(Icons.close), + return _withLeaveGuard( + context, + confirmLeave: confirmLeave, + child: Scaffold( + appBar: AppBar( + leading: BackButton( + onPressed: () => _requestLeave( + context, + confirmLeave: confirmLeave, + ), ), - ], - ), - body: ListView( - padding: const EdgeInsets.all(16), - children: [ + title: const Text("Note Migration"), + actions: [ + IconButton( + tooltip: "Close", + onPressed: () => _requestLeave( + context, + confirmLeave: confirmLeave, + ), + icon: const Icon(Icons.close), + ), + ], + ), + body: ListView( + padding: const EdgeInsets.all(16), + children: [ // Phase indicator Card( child: Padding( @@ -432,11 +489,49 @@ class _MigratePageState extends State onPressed: () => GoRouter.of(context).pop(), child: const Text("Done"), ), - ], + ], + ), ), ); } + Widget _withLeaveGuard( + BuildContext context, { + required bool confirmLeave, + required Widget child, + }) { + return PopScope( + canPop: !confirmLeave, + onPopInvokedWithResult: (didPop, _) async { + if (didPop) return; + await _requestLeave(context, confirmLeave: confirmLeave); + }, + child: child, + ); + } + + Future _requestLeave( + BuildContext context, { + required bool confirmLeave, + }) async { + if (_handlingLeave) return; + _handlingLeave = true; + try { + if (confirmLeave && !await _confirmLeave(context)) return; + if (context.mounted) GoRouter.of(context).pop(); + } finally { + _handlingLeave = false; + } + } + + Future _confirmLeave(BuildContext context) async { + return confirmDialog( + context, + title: "Migration in Progress", + message: "The migration is still running. Are you sure you want to leave?", + ); + } + Widget _feeRow(String label, BigInt zats, {bool bold = false}) { final zec = zats.toDouble() / zatsPerZec; return Padding( From 09ac4256ed26ef836177e5535a8f1763c667bbd1 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 10:24:41 +0200 Subject: [PATCH 044/189] fix: address review comments --- rust/src/account.rs | 16 +++++++-- rust/src/api/issuance.rs | 3 +- rust/src/api/pay.rs | 4 ++- rust/src/frost/protocol.rs | 1 + rust/src/graphql/query.rs | 1 + rust/src/migrate/mod.rs | 72 +++++++++++++++++++++++++++++++++----- rust/src/pay/plan.rs | 12 ++++++- 7 files changed, 95 insertions(+), 14 deletions(-) diff --git a/rust/src/account.rs b/rust/src/account.rs index 450347af8..d0a3669e9 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -577,11 +577,12 @@ pub async fn get_orchard_vk( pub async fn get_orchard_note( connection: &mut SqliteConnection, id: u32, - height: u32, + witness_height: u32, ovk: &orchard::keys::FullViewingKey, eo: &FragmentAuthPath, ero: &AuthPath, note_version: NoteVersion, + rewind_to_position: Option, ) -> Result<(orchard::Note, orchard::tree::MerklePath)> { let (scope, position, diversifier, value, rcm, rho, witness, asset_base) = sqlx::query( "SELECT scope, position, diversifier, value, rcm, rho, witness, @@ -592,7 +593,7 @@ pub async fn get_orchard_note( WHERE id_note = ? AND w.height = ?", ) .bind(id) - .bind(height) + .bind(witness_height) .map(|row: SqliteRow| { let scope: Option = row.get(0); let position: u32 = row.get(1); @@ -611,6 +612,17 @@ pub async fn get_orchard_note( let scope = scope.unwrap_or(0); let scope = scope.orchard_scope(); let (witness, _) = bincode::decode_from_slice::(&witness, legacy()).unwrap(); + let witness = match rewind_to_position { + Some(position) => { + anyhow::ensure!( + witness.position <= position, + "Note position {} is after anchor edge position {position}", + witness.position, + ); + witness.rewind(position) + } + None => witness, + }; let rho = Rho::from_bytes(&rho.try_into().unwrap()).unwrap(); let diversifer = orchard::keys::Diversifier::from_bytes(diversifier.try_into().unwrap()); diff --git a/rust/src/api/issuance.rs b/rust/src/api/issuance.rs index fc7350d9f..d36436897 100644 --- a/rust/src/api/issuance.rs +++ b/rust/src/api/issuance.rs @@ -125,7 +125,8 @@ pub async fn issue_asset( None, // category Some(&issuance_info), false, // migration - None, // preselected + None, // preselected + None, // anchor_height ) .await?; diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index b4ef61a7e..f5aae9459 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -38,6 +38,7 @@ pub async fn prepare(recipients: &[Recipient], options: PaymentOptions, c: &Coin None, // issuance — normal sends have no issuance false, // migration — only used by note migration None, // preselected + None, // anchor_height ) .await } @@ -68,7 +69,8 @@ pub async fn prepare_migration( None, // category None, // issuance true, // migration - None, // preselected + None, // preselected + None, // anchor_height ) .await } diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index ad6ab6f91..ad9efd92e 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -482,6 +482,7 @@ pub async fn publish( None, false, // migration None, // preselected + None, // anchor_height ) .await .context("plan_transaction in DKG publish")?; diff --git a/rust/src/graphql/query.rs b/rust/src/graphql/query.rs index 22ff39b5a..21f32455c 100644 --- a/rust/src/graphql/query.rs +++ b/rust/src/graphql/query.rs @@ -389,6 +389,7 @@ pub async fn prepare_tx( None, false, // migration None, // preselected + None, // anchor_height ) .await?; Ok(pczt) diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 30f713b5a..64b9a514f 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -27,6 +27,9 @@ pub const MIN_SD: u64 = 100 * COST_PER_ACTION; /// Caps transaction size to avoid oversized bundles that nodes reject. const MAX_SPLIT_INPUTS: usize = 50; +/// Migration anchors are rounded down to this block interval. +pub const ANCHOR_BUCKET_SIZE: u32 = 144; + /// Fee padding embedded in each standard denomination. /// Covers Orchard input + change (2 actions in sum mode) and Ironwood /// output (2 actions, padded) = 4 × COST_PER_ACTION = 20,000 zats. @@ -108,8 +111,10 @@ pub struct MigrationStatus { /// Notes grouped by pool and ZEC/ZSA. struct OrchardZecNote { id: u32, + height: u32, value: u64, cmx: Option>, + has_checkpoint: bool, } /// Fetch unspent Orchard ZEC notes with their cmx values. @@ -120,23 +125,34 @@ struct OrchardZecNote { async fn fetch_unspent_orchard_notes_with_cmx( connection: &mut SqliteConnection, account: u32, + checkpoint_height: u32, ) -> Result> { sqlx::query( - "SELECT a.id_note, a.value, a.cmx + "SELECT a.id_note, a.height, a.value, a.cmx, + EXISTS ( + SELECT 1 + FROM witnesses w + WHERE w.account = a.account + AND w.note = a.id_note + AND w.height = ?1 + ) FROM notes a LEFT JOIN spends b ON a.id_note = b.id_note WHERE b.id_note IS NULL - AND a.account = ? + AND a.account = ?2 AND a.pool = 2 AND a.id_asset IS NULL AND a.locked = 0", ) + .bind(checkpoint_height) .bind(account) .map(|row| { OrchardZecNote { id: row.get(0), - value: row.get::(1) as u64, - cmx: row.get(2), + height: row.get(1), + value: row.get::(2) as u64, + cmx: row.get(3), + has_checkpoint: row.get(4), } }) .fetch_all(connection) @@ -144,6 +160,10 @@ async fn fetch_unspent_orchard_notes_with_cmx( .map_err(Into::into) } +fn anchor_bucket_height(height: u32) -> u32 { + height - height % ANCHOR_BUCKET_SIZE +} + /// Run one migration step. Fully idempotent — re-scans notes on every call. pub async fn step( network: &Network, @@ -152,6 +172,8 @@ pub async fn step( account: u32, ) -> Result { let height = client.latest_height().await?; + let checkpoint_height = + crate::sync::get_db_height(&mut *connection, account).await?.height; // Get the wallet's own Orchard/Ironwood address let hw = get_account_hw(&mut *connection, account).await?; @@ -159,8 +181,12 @@ pub async fn step( get_account_full_address(network, &mut *connection, account, 0, hw).await?; // Fetch all unspent Orchard ZEC notes with cmx. - let orchard_zec = - fetch_unspent_orchard_notes_with_cmx(&mut *connection, account).await?; + let orchard_zec = fetch_unspent_orchard_notes_with_cmx( + &mut *connection, + account, + checkpoint_height, + ) + .await?; info!( "Migration step: {} Orchard ZEC notes found", @@ -294,6 +320,7 @@ pub async fn step( None, true, // migration Some(&preselected), + None, // anchor_height ) .await?; @@ -323,8 +350,25 @@ pub async fn step( */ // ── Migrating phase ── + let anchor_height = anchor_bucket_height(checkpoint_height); + + // A witness can only be rewound to an anchor whose tree already + // contains the note. The latest checkpoint must also contain the note + // so its witness is available for Witness::rewind(). + let mut sorted_sd: Vec<&OrchardZecNote> = sd_notes + .iter() + .copied() + .filter(|n| n.height <= anchor_height && n.has_checkpoint) + .collect(); + if sorted_sd.is_empty() { + info!( + "Migration waiting: no SD note can be rewound from checkpoint {} to anchor {}", + checkpoint_height, anchor_height, + ); + return Ok(MigrationEvent::NothingToDo); + } + // Sort by cmx for deterministic random order - let mut sorted_sd: Vec<&&OrchardZecNote> = sd_notes.iter().collect(); sorted_sd.sort_by(|a, b| { let a_cmx = a.cmx.as_deref().unwrap_or(&[]); let b_cmx = b.cmx.as_deref().unwrap_or(&[]); @@ -346,8 +390,8 @@ pub async fn step( }]; info!( - "Migration: note id={} value={} → Ironwood amount={}", - note.id, note.value, ironwood_amount, + "Migration: note id={} value={} → Ironwood amount={}, anchor={} (checkpoint={})", + note.id, note.value, ironwood_amount, anchor_height, checkpoint_height, ); let preselected: Vec = vec![note.id]; @@ -366,6 +410,7 @@ pub async fn step( None, true, // migration — O→I Some(&preselected), + Some(anchor_height), ) .await?; @@ -403,6 +448,15 @@ mod tests { assert!(!is_sd(1_010_000)); } + #[test] + fn test_anchor_bucket_height() { + assert_eq!(anchor_bucket_height(0), 0); + assert_eq!(anchor_bucket_height(143), 0); + assert_eq!(anchor_bucket_height(144), 144); + assert_eq!(anchor_bucket_height(145), 144); + assert_eq!(anchor_bucket_height(288), 288); + } + #[test] fn test_decompose_below_min_denom() { // Below d_min (120_000). diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 36efafe24..32554ecac 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -237,6 +237,7 @@ pub async fn plan_transaction( issuance: Option<&IssuanceInfo>, migration: bool, preselected: Option<&[u32]>, + anchor_height: Option, ) -> Result { let mut input_pools = fetch_unspent_notes_by_pool(connection, account).await?; let height = client.latest_height().await?; @@ -588,7 +589,14 @@ pub async fn plan_transaction( // ── Fetch tree states and anchors ──────────────────────────────────── let h = crate::sync::get_db_height(connection, account).await?; - let (ts, to, ti) = crate::sync::get_tree_state(network, client, h.height).await?; + let anchor_height = anchor_height.unwrap_or(h.height); + anyhow::ensure!( + anchor_height <= h.height, + "Anchor height {anchor_height} is ahead of checkpoint {}", + h.height, + ); + let (ts, to, ti) = + crate::sync::get_tree_state(network, client, anchor_height).await?; let es = ts.to_edge(&SaplingHasher::default()); let eo = to.to_edge(&OrchardHasher::default()); let ei = ti.to_edge(&OrchardHasher::default()); @@ -761,6 +769,7 @@ pub async fn plan_transaction( &eo, &ero, orchard_note_version, + (anchor_height < h.height).then_some(eo.1), ) .await?; @@ -783,6 +792,7 @@ pub async fn plan_transaction( &ei, &ero, orchard::NoteVersion::V3, + (anchor_height < h.height).then_some(ei.1), ) .await?; From e448ff4c02886559bdb9fefb62a3ebae6888237b Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 11:14:27 +0200 Subject: [PATCH 045/189] feat: improve migration flow --- lib/pages/migrate.dart | 11 +- rust/src/api/migrate.rs | 328 +++++++++++++++++++++++++--------------- rust/src/migrate/mod.rs | 34 +++++ 3 files changed, 253 insertions(+), 120 deletions(-) diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index e6defce43..59c5edaf3 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -23,6 +23,7 @@ class _MigratePageState extends State MigrationStatus? _status; Timer? _countdown; int _countdownSecs = 0; + bool _hasCountdown = false; bool _started = false; bool _didShowCompleteDialog = false; bool _handlingLeave = false; @@ -91,6 +92,7 @@ class _MigratePageState extends State final m = RegExp(r'Waiting (\d+)s').firstMatch(status.nextAction); if (m != null) { + _hasCountdown = true; _countdownSecs = int.parse(m.group(1)!); _countdown?.cancel(); _countdown = Timer.periodic( @@ -101,6 +103,10 @@ class _MigratePageState extends State } }, ); + } else { + _hasCountdown = false; + _countdown?.cancel(); + _countdown = null; } ScaffoldMessenger.of(context).showSnackBar( @@ -110,6 +116,7 @@ class _MigratePageState extends State ), ); } else { + _hasCountdown = false; _countdown?.cancel(); _countdown = null; } @@ -402,7 +409,9 @@ class _MigratePageState extends State const Gap(4), Text( waiting - ? "Waiting ${_countdownSecs}s..." + ? _hasCountdown + ? "Waiting ${_countdownSecs}s..." + : status.nextAction : phase == 'splitting' ? "Phase 1: Splitting into standard denominations" : phase == 'migrating' diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index 1630c870f..e474eb7a6 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -70,7 +70,7 @@ impl NoteMigration { /// Single-shot step (kept for FRB generated-code compatibility). #[cfg_attr(feature = "flutter", frb)] pub async fn step_migration(c: &Coin) -> Result { - let (event, _status) = do_step(c, 0, 0).await?; + let (event, _status) = do_step(c, 0, 0, true, true).await?; Ok(match event { crate::migrate::MigrationEvent::SplitComplete { fee } => MigrationEvent::SplitComplete { fee }, crate::migrate::MigrationEvent::MigrateComplete { fee } => MigrationEvent::MigrateComplete { fee }, @@ -82,8 +82,9 @@ pub async fn step_migration(c: &Coin) -> Result { /// Run migration to completion, streaming MigrationStatus to Flutter. /// /// `mean_delay_ms` controls the mean wait time (in milliseconds) of the -/// exponential random delay between migration steps. Longer delays make -/// it harder for an observer to correlate the transactions. +/// exponential random delay before migration steps. O→I steps additionally +/// wait for the next anchor bucket boundary before syncing, preparing, and +/// broadcasting. #[cfg(feature = "flutter")] async fn run_migration( sink: StreamSink, @@ -112,65 +113,16 @@ async fn run_migration( let mut acc_split = 0u64; let mut acc_migrate = 0u64; let mut last_action_height: Option = None; - let mut last_phase = String::new(); - let mut last_sd_count = 0u32; - let mut last_non_sd_count = 0u32; - let mut last_iw_count = 0u32; - let mut last_progress = 0.0; - let mut last_work = String::new(); + let mut status = current_migration_status(c, acc_split, acc_migrate).await?; + sink.add(status.clone()).ok(); loop { - let complete = tokio::select! { - biased; - _ = cancellation_token.cancelled() => { - tracing::info!("Note migration cancelled"); - break; - } - result = async { - let skip = match last_action_height { - Some(h) => client.latest_height().await? <= h, - None => false, - }; - - if skip { - return Ok::(false); - } - - let (event, status) = do_step(c, acc_split, acc_migrate).await?; - - // Track latest counts for the waiting display. - last_phase = status.phase.clone(); - last_sd_count = status.sd_notes_count; - last_non_sd_count = status.non_sd_notes_count; - last_iw_count = status.ironwood_sd_count; - last_progress = status.progress; - last_work = status.work_summary.clone(); - - // Accumulate fees from broadcast events. - match &event { - crate::migrate::MigrationEvent::SplitComplete { fee } => { - acc_split += fee; - last_action_height = Some(client.latest_height().await?); - } - crate::migrate::MigrationEvent::MigrateComplete { fee } => { - acc_migrate += fee; - last_action_height = Some(client.latest_height().await?); - } - _ => {} - } - - let complete = - matches!(event, crate::migrate::MigrationEvent::Complete); - sink.add(status).ok(); - Ok(complete) - } => result?, - }; - - if complete { + if status.phase == "complete" { break; } - // Exponential delay between steps (shared by skip and normal paths). + // Delay before doing any migration-specific network activity. This + // also applies to the first transaction. let mean = mean_delay_ms as f64; let u = (OsRng.next_u32() as f64 + 1.0) / (u32::MAX as f64 + 2.0); let delay_ms = ((-mean * u.ln()) as u64).min(mean_delay_ms * 4); @@ -181,30 +133,82 @@ async fn run_migration( delay_ms, mean_delay_ms, u ); - // Notify UI of the delay before sleeping, preserving the last - // phase/counts so the progress display doesn't blank out. - sink.add(MigrationStatus { - phase: last_phase.clone(), - split_fees: acc_split, - migrate_fees: acc_migrate, - total_fees: acc_split + acc_migrate, - sd_notes_count: last_sd_count, - non_sd_notes_count: last_non_sd_count, - ironwood_sd_count: last_iw_count, - progress: last_progress, - next_action: format!("Waiting {}s...", delay_secs), - work_summary: last_work.clone(), - }) - .ok(); - - tokio::select! { + status.next_action = format!("Waiting {}s...", delay_secs); + sink.add(status.clone()).ok(); + + let cancelled = tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + tracing::info!("Note migration cancelled"); + true + } + _ = tokio::time::sleep(std::time::Duration::from_millis(delay_ms)) => false, + }; + if cancelled { + break; + } + + if let Some(height) = last_action_height { + if client.latest_height().await? <= height { + continue; + } + } + + // O→I transactions are prepared only when the wallet checkpoint and + // the current anchor are the same shared bucket boundary. Until then, + // only query the tip height; do not fetch or synchronize tree state. + let align_to_boundary = status.phase == "migrating"; + if align_to_boundary { + let reached_boundary = tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + tracing::info!("Note migration cancelled"); + false + } + result = wait_for_anchor_boundary(&sink, c, &mut client, &status) => { + result?; + true + } + }; + if !reached_boundary { + break; + } + } + + let (event, next_status) = tokio::select! { biased; _ = cancellation_token.cancelled() => { tracing::info!("Note migration cancelled"); break; } - _ = tokio::time::sleep(std::time::Duration::from_millis(delay_ms)) => {} + result = do_step( + c, + acc_split, + acc_migrate, + align_to_boundary, + !align_to_boundary, + ) => result?, + }; + + match event { + crate::migrate::MigrationEvent::SplitComplete { fee } => { + acc_split += fee; + last_action_height = Some(client.latest_height().await?); + } + crate::migrate::MigrationEvent::MigrateComplete { fee } => { + acc_migrate += fee; + last_action_height = Some(client.latest_height().await?); + } + _ => {} } + + status = MigrationStatus { + split_fees: acc_split, + migrate_fees: acc_migrate, + total_fees: acc_split + acc_migrate, + ..next_status + }; + sink.add(status.clone()).ok(); } Ok(()) @@ -233,49 +237,42 @@ async fn do_step( c: &Coin, acc_split: u64, acc_migrate: u64, + allow_migrate: bool, + sync_before: bool, ) -> Result<(crate::migrate::MigrationEvent, MigrationStatus)> { let network = c.network(); let mut connection = c.get_connection().await?; let mut client = c.client().await?; - let current_height = client.latest_height().await?; - let _ = crate::sync::synchronize_impl( - (), - vec![c.account], - current_height, - 100_000, - 10_000, - 10_000, - false, - c, - ) - .await; - - let event = crate::migrate::step(&network, &mut connection, &mut client, c.account) - .await - .map_err(|e| anyhow::anyhow!("step: {e}"))?; - - let needs_sync = matches!( - event, - crate::migrate::MigrationEvent::SplitComplete { .. } - | crate::migrate::MigrationEvent::MigrateComplete { .. } - ); - if needs_sync { - let height = client.latest_height().await?; - let _ = crate::sync::synchronize_impl( - (), - vec![c.account], - height, - 100_000, - 10_000, - 10_000, - false, - c, - ) - .await; + if sync_before { + let current_height = client.latest_height().await?; + let _ = synchronize_to(c, current_height).await; } - // Re-read for updated counts after potential broadcast + sync. + let before = current_migration_status(c, acc_split, acc_migrate).await?; + let event = if before.phase == "complete" { + crate::migrate::MigrationEvent::Complete + } else if before.phase == "migrating" && !allow_migrate { + // A normal sync may finish the splitting phase at a non-boundary + // height. Return to the runner so it can delay and align the O→I + // transaction instead of broadcasting it immediately. + crate::migrate::MigrationEvent::NothingToDo + } else { + crate::migrate::step(&network, &mut connection, &mut client, c.account) + .await + .map_err(|e| anyhow::anyhow!("step: {e}"))? + }; + + let status = current_migration_status(c, acc_split, acc_migrate).await?; + Ok((event, status)) +} + +async fn current_migration_status( + c: &Coin, + acc_split: u64, + acc_migrate: u64, +) -> Result { + let mut connection = c.get_connection().await?; let all_notes = crate::pay::plan::fetch_unspent_notes_grouped_by_pool(&mut connection, c.account).await?; let orchard_zec: Vec<&crate::pay::InputNote> = all_notes .iter() @@ -287,8 +284,8 @@ async fn do_step( .filter(|n| !crate::migrate::is_sd(n.amount)) .map(|n| n.amount) .collect(); - let non_sd_total: u64 = non_sd_vals.iter().sum(); - let effective_non_sd = if non_sd_total >= crate::migrate::MIN_SD { + let has_split = crate::migrate::has_split_transaction(non_sd_vals.clone()); + let effective_non_sd = if has_split { non_sd_vals.len() as u32 } else { 0 @@ -301,10 +298,8 @@ async fn do_step( .count() as u32; let total_sd = sd_count + ironwood_sd; - // Determine phase from current (post-sync) counts. - let phase = match &event { - crate::migrate::MigrationEvent::Complete => "complete", - _ if effective_non_sd > 0 => "splitting", + let phase = match () { + _ if has_split => "splitting", _ if sd_count > 0 => "migrating", _ => "complete", }; @@ -319,7 +314,7 @@ async fn do_step( _ => 1.0, }; - Ok((event, MigrationStatus { + Ok(MigrationStatus { phase: phase.to_string(), split_fees: acc_split, migrate_fees: acc_migrate, @@ -330,5 +325,100 @@ async fn do_step( progress, next_action: String::new(), work_summary: format!("SD: {}, non-SD: {}", sd_count, effective_non_sd), - })) + }) +} + +async fn synchronize_to(c: &Coin, height: u32) -> Result { + crate::sync::synchronize_impl( + (), + vec![c.account], + height, + 100_000, + 10_000, + 10_000, + false, + c, + ) + .await +} + +/// Poll only the network height until the next shared anchor boundary. Tree +/// state is synchronized exactly once, while that boundary is the current tip. +#[cfg(feature = "flutter")] +async fn wait_for_anchor_boundary( + sink: &StreamSink, + c: &Coin, + client: &mut crate::Client, + status: &MigrationStatus, +) -> Result<()> { + const HEIGHT_POLL_INTERVAL: std::time::Duration = + std::time::Duration::from_secs(10); + + let observed_height = client.latest_height().await?; + let db_height = wallet_height(c).await?; + let mut boundary = + crate::migrate::next_anchor_bucket_height(observed_height.max(db_height)); + + let mut waiting = status.clone(); + waiting.next_action = format!("Waiting for anchor block {}...", boundary); + sink.add(waiting).ok(); + + loop { + let tip = client.latest_height().await?; + if tip > boundary { + // If height polling missed the boundary, do not fetch its + // historical tree state. Wait for a boundary that is observed as + // the current tip. + boundary = crate::migrate::next_anchor_bucket_height( + tip.saturating_add(1), + ); + let mut waiting = status.clone(); + waiting.next_action = format!("Waiting for anchor block {}...", boundary); + sink.add(waiting).ok(); + continue; + } + + if tip == boundary { + tracing::info!( + "Migration anchor boundary reached: tip={}, boundary={}", + tip, + boundary, + ); + synchronize_to(c, boundary).await?; + let synced_height = wallet_height(c).await?; + if synced_height == boundary { + return Ok(()); + } + + if synced_height > boundary { + // Another sync advanced the wallet while we were waiting. + // Move to a future boundary instead of preparing from a + // checkpoint that no longer represents the current tip. + boundary = crate::migrate::next_anchor_bucket_height( + tip.max(synced_height).saturating_add(1), + ); + let mut waiting = status.clone(); + waiting.next_action = + format!("Waiting for anchor block {}...", boundary); + sink.add(waiting).ok(); + continue; + } + + tracing::warn!( + "Migration boundary sync did not advance: wallet={}, boundary={}", + synced_height, + boundary, + ); + } + + tokio::time::sleep(HEIGHT_POLL_INTERVAL).await; + } +} + +#[cfg(feature = "flutter")] +async fn wallet_height(c: &Coin) -> Result { + let mut connection = c.get_connection().await?; + Ok(crate::sync::get_db_height(&mut connection, c.account) + .await? + .height) } diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 64b9a514f..469da0244 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -85,6 +85,14 @@ pub fn is_sd(value: u64) -> bool { value > SD_FEE_PAD && is_iw_sd(value - SD_FEE_PAD) } +/// Whether the next migration action can split the currently known non-SD +/// notes. This mirrors the input cap and ordering used by `step`. +pub(crate) fn has_split_transaction(mut values: Vec) -> bool { + values.sort_unstable_by(|a, b| b.cmp(a)); + values.truncate(MAX_SPLIT_INPUTS); + values.into_iter().sum::() >= MIN_SD +} + /// Result of a migration step. pub enum MigrationEvent { /// A split transaction was broadcast. @@ -164,6 +172,16 @@ fn anchor_bucket_height(height: u32) -> u32 { height - height % ANCHOR_BUCKET_SIZE } +/// Return the first migration anchor boundary at or above `height`. +pub(crate) fn next_anchor_bucket_height(height: u32) -> u32 { + let remainder = height % ANCHOR_BUCKET_SIZE; + if remainder == 0 { + height + } else { + height.saturating_add(ANCHOR_BUCKET_SIZE - remainder) + } +} + /// Run one migration step. Fully idempotent — re-scans notes on every call. pub async fn step( network: &Network, @@ -457,6 +475,22 @@ mod tests { assert_eq!(anchor_bucket_height(288), 288); } + #[test] + fn test_next_anchor_bucket_height() { + assert_eq!(next_anchor_bucket_height(0), 0); + assert_eq!(next_anchor_bucket_height(1), 144); + assert_eq!(next_anchor_bucket_height(143), 144); + assert_eq!(next_anchor_bucket_height(144), 144); + assert_eq!(next_anchor_bucket_height(145), 288); + } + + #[test] + fn test_has_split_transaction_applies_input_cap() { + assert!(has_split_transaction(vec![MIN_SD])); + assert!(!has_split_transaction(vec![MIN_SD - 1])); + assert!(!has_split_transaction(vec![MIN_SD / 100; 100])); + } + #[test] fn test_decompose_below_min_denom() { // Below d_min (120_000). From 412c1fa32c529d7f5ad110b6cffae4b6d640f9ed Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 11:21:10 +0200 Subject: [PATCH 046/189] chore: code reformatting only --- example/py/mining.py | 93 +- example/py/zkool_py_example.py | 4 +- example/zkool-mcp/main.py | 2 +- lib/main.dart | 56 +- lib/pages/account.dart | 42 +- lib/pages/contact_editor.dart | 145 +- lib/pages/db.dart | 16 +- lib/pages/migrate.dart | 357 ++- lib/pages/plugin_manager.dart | 28 +- lib/pages/receive.dart | 39 +- lib/pages/send.dart | 4 +- lib/pages/tx.dart | 15 +- lib/pages/tx_view.dart | 18 +- lib/settings.dart | 22 +- lib/src/rust/api/account.dart | 238 +- lib/src/rust/api/account.freezed.dart | 827 +----- lib/src/rust/api/coin.dart | 25 +- lib/src/rust/api/coin.freezed.dart | 69 +- lib/src/rust/api/contacts.dart | 40 +- lib/src/rust/api/contacts.freezed.dart | 65 +- lib/src/rust/api/db.dart | 39 +- lib/src/rust/api/frost.dart | 108 +- lib/src/rust/api/frost.freezed.dart | 324 +-- lib/src/rust/api/init.dart | 6 +- lib/src/rust/api/init.freezed.dart | 17 +- lib/src/rust/api/issuance.dart | 8 +- lib/src/rust/api/key.dart | 22 +- lib/src/rust/api/mempool.dart | 19 +- lib/src/rust/api/mempool.freezed.dart | 43 +- lib/src/rust/api/migrate.dart | 9 +- lib/src/rust/api/migrate.freezed.dart | 69 +- lib/src/rust/api/network.dart | 32 +- lib/src/rust/api/network.freezed.dart | 149 +- lib/src/rust/api/openalias.dart | 29 +- lib/src/rust/api/pay.dart | 82 +- lib/src/rust/api/pay.freezed.dart | 174 +- lib/src/rust/api/plugin.dart | 21 +- lib/src/rust/api/plugin.freezed.dart | 200 +- lib/src/rust/api/raptor.dart | 16 +- lib/src/rust/api/sapling.dart | 11 +- lib/src/rust/api/sweep.dart | 6 +- lib/src/rust/api/sync.dart | 30 +- lib/src/rust/api/transaction.dart | 44 +- lib/src/rust/api/vault.dart | 29 +- lib/src/rust/api/zsa.dart | 14 +- lib/src/rust/api/zsa.freezed.dart | 122 +- lib/src/rust/frb_generated.dart | 2557 +++++------------ lib/src/rust/frb_generated.io.dart | 465 +-- lib/src/rust/frb_generated.web.dart | 534 ++-- lib/src/rust/io.dart | 7 +- lib/src/rust/pay.dart | 26 +- lib/src/rust/pay/error.freezed.dart | 54 +- lib/store.dart | 7 +- lib/store.freezed.dart | 781 ++--- lib/store.g.dart | 291 +- lib/widgets/contact_picker.dart | 27 +- lib/widgets/plugin_memo_view.dart | 12 +- lib/widgets/vault_account_picker.dart | 32 +- linux/runner/main.cc | 2 +- linux/runner/my_application.cc | 57 +- linux/runner/my_application.h | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 10 +- protos/compact_formats.proto | 99 +- protos/service.proto | 216 +- rust/src/account.rs | 30 +- rust/src/api/account.rs | 174 +- rust/src/api/coin.rs | 59 +- rust/src/api/contacts.rs | 6 +- rust/src/api/db.rs | 10 +- rust/src/api/frost.rs | 2 +- rust/src/api/issuance.rs | 19 +- rust/src/api/key.rs | 22 +- rust/src/api/mempool.rs | 4 +- rust/src/api/migrate.rs | 63 +- rust/src/api/mod.rs | 10 +- rust/src/api/openalias.rs | 5 +- rust/src/api/pay.rs | 36 +- rust/src/api/plugin.rs | 2 +- rust/src/api/raptor.rs | 16 +- rust/src/api/sapling.rs | 33 +- rust/src/api/sync.rs | 2 - rust/src/api/transaction.rs | 21 +- rust/src/api/vault.rs | 24 +- rust/src/contacts.rs | 32 +- rust/src/db.rs | 69 +- rust/src/frost/dkg.rs | 344 ++- rust/src/frost/mod.rs | 2 +- rust/src/frost/protocol.rs | 151 +- rust/src/frost/sign.rs | 70 +- rust/src/graphql-cli.rs | 28 +- rust/src/graphql/data.rs | 7 +- rust/src/graphql/mod.rs | 19 +- rust/src/graphql/mutation.rs | 107 +- rust/src/graphql/query.rs | 55 +- rust/src/graphql/subs.rs | 2 +- rust/src/io.rs | 37 +- rust/src/keys.rs | 5 +- rust/src/ledger/builder.rs | 49 +- rust/src/ledger/fvk.rs | 31 +- rust/src/ledger/mock.rs | 16 +- rust/src/ledger/mod.rs | 7 +- rust/src/ledger/nano.rs | 9 +- rust/src/ledger/tests.rs | 8 +- rust/src/ledger/transport.rs | 14 +- rust/src/lib.rs | 10 +- rust/src/lwd.rs | 663 ++--- rust/src/memo.rs | 50 +- rust/src/mempool.rs | 7 +- rust/src/migrate/mod.rs | 260 +- rust/src/net/lwd.rs | 14 +- rust/src/net/mod.rs | 5 +- rust/src/net/zebra.rs | 66 +- rust/src/openalias.rs | 43 +- rust/src/pay/fee.rs | 6 +- rust/src/pay/mod.rs | 5 +- rust/src/pay/plan.rs | 127 +- rust/src/pay/pool.rs | 8 +- rust/src/pay/select.rs | 117 +- rust/src/pay/solve.rs | 350 ++- rust/src/plugin/db.rs | 2 +- rust/src/plugin/mod.rs | 17 +- rust/src/plugin/rhai_api.rs | 17 +- rust/src/recover.rs | 21 +- rust/src/sync.rs | 62 +- rust/src/vault/crypto.rs | 157 +- rust/src/vault/dart.rs | 8 +- rust/src/warp/decrypter.rs | 55 +- rust/src/warp/sync.rs | 12 +- rust/src/warp/sync/shielded.rs | 23 +- rust/src/warp/sync/shielded/orchard.rs | 28 +- rust/src/warp/sync/shielded/sapling.rs | 2 +- rust/tests/parse_shield_tx.rs | 8 +- rust/tests/zsa_transfer_test.rs | 287 +- tests/tests/conftest.py | 4 +- tests/tests/dkg.py | 9 +- tests/tests/test_account_management.py | 33 +- tests/tests/test_dkg.py | 44 +- tests/tests/test_frost.py | 10 +- tests/tests/test_jwt.py | 128 +- tests/tests/test_reorg.py | 42 +- tests/tests/test_subscriptions.py | 77 +- tests/tests/test_transactions.py | 66 +- tests/tests/test_tx_details.py | 38 +- tests/tests/test_zebra_wallet.py | 2 +- tests/tests/utils.py | 12 +- windows/runner/flutter_window.cpp | 12 +- windows/runner/flutter_window.h | 10 +- windows/runner/main.cpp | 3 +- windows/runner/resource.h | 10 +- windows/runner/utils.cpp | 16 +- windows/runner/utils.h | 4 +- windows/runner/win32_window.cpp | 136 +- windows/runner/win32_window.h | 18 +- 153 files changed, 5482 insertions(+), 8131 deletions(-) diff --git a/example/py/mining.py b/example/py/mining.py index 860a230fc..f0ccc804e 100644 --- a/example/py/mining.py +++ b/example/py/mining.py @@ -4,71 +4,116 @@ import os import time -transport = gql.transport.aiohttp.AIOHTTPTransport(url="http://localhost:8000/graphql", timeout=60) -client = gql.Client(transport=transport, execute_timeout = 60) +transport = gql.transport.aiohttp.AIOHTTPTransport( + url="http://localhost:8000/graphql", timeout=60 +) +client = gql.Client(transport=transport, execute_timeout=60) from decimal import Decimal MATURITY_THRESHOLD = 100 MAX_NOTES = 10 + def run(miner_seed: str, seed: str, to_address: str): height = client.execute(gql.gql("query { currentHeight }"))["currentHeight"] print(f"Height: {height}") - miner = client.execute(gql.gql(""" + miner = client.execute( + gql.gql(""" mutation CreateAccount($account: NewAccount!) { createAccount(newAccount: $account) - }"""), variable_values = {"account": {"name": "miner", "key": miner_seed, "aindex": 0, "birth": 1, "useInternal": False}})["createAccount"] + }"""), + variable_values={ + "account": { + "name": "miner", + "key": miner_seed, + "aindex": 0, + "birth": 1, + "useInternal": False, + } + }, + )["createAccount"] print(f"Miner id: {miner}") - wallet = client.execute(gql.gql(""" + wallet = client.execute( + gql.gql(""" mutation CreateAccount($account: NewAccount!) { createAccount(newAccount: $account) - }"""), variable_values = {"account": {"name": "wallet", "key": seed, "aindex": 0, "birth": 1, "useInternal": False}})["createAccount"] + }"""), + variable_values={ + "account": { + "name": "wallet", + "key": seed, + "aindex": 0, + "birth": 1, + "useInternal": False, + } + }, + )["createAccount"] print(f"Wallet id: {wallet}") - client.execute(gql.gql(""" + client.execute( + gql.gql(""" mutation Synchronize($ids: [Int!]!) { synchronize(idAccounts: $ids) } - """), variable_values = {"ids": [miner, wallet]}) + """), + variable_values={"ids": [miner, wallet]}, + ) - all_notes = client.execute(gql.gql(""" + all_notes = client.execute( + gql.gql(""" query NotesByAccount($id: Int!) { notesByAccount(idAccount: $id) { id height value } } - """), variable_values = {"id": miner})["notesByAccount"] + """), + variable_values={"id": miner}, + )["notesByAccount"] - notes = [n for n in all_notes if n["height"] < height - MATURITY_THRESHOLD][:MAX_NOTES] + notes = [n for n in all_notes if n["height"] < height - MATURITY_THRESHOLD][ + :MAX_NOTES + ] if not notes: raise RuntimeError("No sufficiently mature notes found.") print(f"Selected {len(notes)} mature note(s)") total = sum(Decimal(n["value"]) for n in notes) print(total) - txid = client.execute(gql.gql(""" + txid = client.execute( + gql.gql(""" mutation Pay($id: Int!, $payment: Payment!) { pay(idAccount: $id, payment: $payment) } - """), variable_values = {"id": miner, "payment": { - "recipients": [{"address": to_address, "amount": str(total)}], - "recipientPaysFee": True, - "confirmations": MATURITY_THRESHOLD, - }})["pay"] + """), + variable_values={ + "id": miner, + "payment": { + "recipients": [{"address": to_address, "amount": str(total)}], + "recipientPaysFee": True, + "confirmations": MATURITY_THRESHOLD, + }, + }, + )["pay"] print(f"Done. txid: {txid}") time.sleep(30) - client.execute(gql.gql(""" + client.execute( + gql.gql(""" mutation Synchronize($id: Int!) { synchronizeAccount(idAccount: $id) } - """), variable_values = {"id": wallet}) + """), + variable_values={"id": wallet}, + ) - balance = client.execute(gql.gql(""" + balance = client.execute( + gql.gql(""" query GetBalance($id: Int!) { balanceByAccount(idAccount: $id) { orchard }} - """), variable_values = {"id": wallet})["balanceByAccount"] + """), + variable_values={"id": wallet}, + )["balanceByAccount"] print(balance) - orchard = float(balance['orchard']) + orchard = float(balance["orchard"]) assert orchard > 0, f"Expected positive orchard balance, got {orchard}" -run(os.environ["MINER_SEED"], os.environ["SEED"], - os.environ["DESTINATION_ADDRESS"]) + +run(os.environ["MINER_SEED"], os.environ["SEED"], os.environ["DESTINATION_ADDRESS"]) diff --git a/example/py/zkool_py_example.py b/example/py/zkool_py_example.py index 7c0f6dba7..1edd75ad0 100644 --- a/example/py/zkool_py_example.py +++ b/example/py/zkool_py_example.py @@ -23,7 +23,5 @@ ua } }""") -result = client.execute(getAddressReq, variable_values = { - "idAccount": idAccount -}) +result = client.execute(getAddressReq, variable_values={"idAccount": idAccount}) print(result["addressByAccount"]["ua"]) diff --git a/example/zkool-mcp/main.py b/example/zkool-mcp/main.py index 5ea19dffc..599affed6 100644 --- a/example/zkool-mcp/main.py +++ b/example/zkool-mcp/main.py @@ -5,7 +5,7 @@ server = GraphQLMCP.from_remote_url( url="http://localhost:8000/graphql", name="Zcash", - headers={} # Optional: auth headers + headers={}, # Optional: auth headers ) app = server.http_app() diff --git a/lib/main.dart b/lib/main.dart index 2950db5a3..46db5cf04 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -40,36 +40,36 @@ Future main() async { ), child: ToastificationWrapper( child: Consumer(builder: (context, ref, _) { - final settings = ref.watch(appSettingsProvider).value; - final scheme = settings?.let((s) { - try { - return FlexScheme.values.byName(s.paletteName); - } catch (_) { - return FlexScheme.blue; - } - }) ?? - FlexScheme.blue; - final theme = FlexThemeData.light(scheme: scheme).copyWith(useMaterial3: true); - final darkTheme = FlexThemeData.dark(scheme: scheme).copyWith(useMaterial3: true); - return MaterialApp.router( - key: appKey, - routerConfig: r, - builder: (context, child) => SafeArea( - top: false, - left: false, - right: false, - child: child!, - ), - themeMode: settings?.darkMode == true ? ThemeMode.dark : ThemeMode.light, - theme: theme, - darkTheme: darkTheme, - debugShowCheckedModeBanner: false, - ); - }), + final settings = ref.watch(appSettingsProvider).value; + final scheme = settings?.let((s) { + try { + return FlexScheme.values.byName(s.paletteName); + } catch (_) { + return FlexScheme.blue; + } + }) ?? + FlexScheme.blue; + final theme = FlexThemeData.light(scheme: scheme).copyWith(useMaterial3: true); + final darkTheme = FlexThemeData.dark(scheme: scheme).copyWith(useMaterial3: true); + return MaterialApp.router( + key: appKey, + routerConfig: r, + builder: (context, child) => SafeArea( + top: false, + left: false, + right: false, + child: child!, + ), + themeMode: settings?.darkMode == true ? ThemeMode.dark : ThemeMode.light, + theme: theme, + darkTheme: darkTheme, + debugShowCheckedModeBanner: false, + ); + }), + ), ), ), - ), -); + ); } class PinLock extends ConsumerStatefulWidget { diff --git a/lib/pages/account.dart b/lib/pages/account.dart index da9532e10..53b02c2aa 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -233,9 +233,7 @@ class AccountViewPageState extends ConsumerState with SingleTic case "update_fx": onUpdateAllTxPrices(); case "toggle_tx_view": - ref.read(appSettingsProvider.notifier) - .setTransactionViewMode( - !(ref.read(appSettingsProvider).value?.transactionTableMode ?? false)); + ref.read(appSettingsProvider.notifier).setTransactionViewMode(!(ref.read(appSettingsProvider).value?.transactionTableMode ?? false)); case "charts": GoRouter.of(context).push("/chart"); case "migration": @@ -277,9 +275,7 @@ class AccountViewPageState extends ConsumerState with SingleTic ), PopupMenuItem( value: "toggle_tx_view", - child: Text((ref.read(appSettingsProvider).value?.transactionTableMode ?? false) - ? "View: List" - : "View: Table"), + child: Text((ref.read(appSettingsProvider).value?.transactionTableMode ?? false) ? "View: List" : "View: Table"), ), if (!Platform.isLinux) const PopupMenuItem( @@ -408,12 +404,11 @@ class AccountViewPageState extends ConsumerState with SingleTic ], ), showMemos(context, account.memos, () { - final selectedAccount = - ref.read(selectedAccountProvider).requireValue!; - ref.invalidate( - accountProvider(selectedAccount.id)); + final selectedAccount = ref.read(selectedAccountProvider).requireValue!; + ref.invalidate(accountProvider(selectedAccount.id)); }), - showNotes(ref, account.notes, _showDustNotes, () => setState(() => _showDustNotes = !_showDustNotes), _groupByPool, () => setState(() => _groupByPool = !_groupByPool)), + showNotes(ref, account.notes, _showDustNotes, () => setState(() => _showDustNotes = !_showDustNotes), _groupByPool, + () => setState(() => _groupByPool = !_groupByPool)), _showZsaHoldings(context, account.zsas), ], )); @@ -989,9 +984,7 @@ Uint8List trimTrailingZeros(Uint8List bytes) { Widget showMemos(BuildContext context, List memos, VoidCallback onMemoChanged) { // Use a key derived from the memo list content to force rebuild when memos update, // since SearchableList only reads initialList once. - final memoKey = memos.isEmpty - ? 'empty' - : '${memos.first.id}_${memos.last.id}_${memos.length}'; + final memoKey = memos.isEmpty ? 'empty' : '${memos.first.id}_${memos.last.id}_${memos.length}'; return SearchableList( key: ValueKey(memoKey), initialList: memos, @@ -1008,9 +1001,7 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback final t = Theme.of(navigatorKey.currentContext!); final currentHeight = ref.read(currentHeightProvider).value; final dustThreshold = BigInt.from(5000); - final filtered = showDust - ? notes - : notes.where((n) => n.idAsset != null || n.value > dustThreshold).toList(); + final filtered = showDust ? notes : notes.where((n) => n.idAsset != null || n.value > dustThreshold).toList(); // Build grouped items: header + its notes List<({int pool, List poolNotes})> groups = []; @@ -1021,16 +1012,11 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback } // Sort pools in display order: Transparent, Sapling, Orchard, Ironwood final poolOrder = [0, 1, 2, 3]; - groups = poolOrder - .where((p) => grouped.containsKey(p)) - .map((p) => (pool: p, poolNotes: grouped[p]!)) - .toList(); + groups = poolOrder.where((p) => grouped.containsKey(p)).map((p) => (pool: p, poolNotes: grouped[p]!)).toList(); } // Flattened item count: toolbar + (header + notes per group) or all notes flat - final totalItems = groupByPool - ? 1 + groups.fold(0, (sum, g) => sum + 1 + g.poolNotes.length) - : filtered.length + 1; + final totalItems = groupByPool ? 1 + groups.fold(0, (sum, g) => sum + 1 + g.poolNotes.length) : filtered.length + 1; return ListView.builder( itemCount: totalItems, @@ -1094,9 +1080,7 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback onTap: () => toggleLock(ref, context, note.id, !note.locked), leading: Text("${note.height}"), title: Text(poolToString(note.pool)), - trailing: note.idAsset != null - ? Text("${note.value} ${note.assetDisplay}", softWrap: false) - : zatToText(note.value, selectable: false), + trailing: note.idAsset != null ? Text("${note.value} ${note.assetDisplay}", softWrap: false) : zatToText(note.value, selectable: false), textColor: note.locked ? t.disabledColor : null, ); } @@ -1113,9 +1097,7 @@ Widget showNotes(WidgetRef ref, List notes, bool showDust, VoidCallback onTap: () => toggleLock(ref, context, note.id, !note.locked), leading: Text("${note.height}"), title: Text(poolToString(note.pool)), - trailing: note.idAsset != null - ? Text("${note.value} ${note.assetDisplay}", softWrap: false) - : zatToText(note.value, selectable: false), + trailing: note.idAsset != null ? Text("${note.value} ${note.assetDisplay}", softWrap: false) : zatToText(note.value, selectable: false), textColor: note.locked ? t.disabledColor : null, ); }, diff --git a/lib/pages/contact_editor.dart b/lib/pages/contact_editor.dart index a5235cd32..206a454d0 100644 --- a/lib/pages/contact_editor.dart +++ b/lib/pages/contact_editor.dart @@ -30,7 +30,6 @@ class ContactEditPageState extends ConsumerState { late var c = coinContext.coin; var _addresses = ['']; - bool get isEditing => widget.contact != null; @override @@ -53,90 +52,88 @@ class ContactEditPageState extends ConsumerState { onSaveAndPop(); }, child: Scaffold( - appBar: AppBar( - title: Text(isEditing ? "Edit Contact" : "New Contact"), - actions: [ - IconButton(onPressed: onImport, tooltip: "Import from vCard", icon: Icon(Icons.download)), - IconButton(onPressed: onImportFromContacts, tooltip: "Import from Contacts", icon: Icon(Icons.contacts)), - IconButton(onPressed: onExport, tooltip: "Export as vCard", icon: Icon(Icons.upload_file)), - if (isEditing) IconButton(onPressed: onDelete, tooltip: "Delete contact", icon: Icon(Icons.delete)), - ], - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: FormBuilder( - key: _formKey, - child: Column( - children: [ - Gap(16), - Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - FormBuilderTextField( - name: "name", - decoration: const InputDecoration( - labelText: "Name", - prefixIcon: Icon(Icons.person_outline), + appBar: AppBar( + title: Text(isEditing ? "Edit Contact" : "New Contact"), + actions: [ + IconButton(onPressed: onImport, tooltip: "Import from vCard", icon: Icon(Icons.download)), + IconButton(onPressed: onImportFromContacts, tooltip: "Import from Contacts", icon: Icon(Icons.contacts)), + IconButton(onPressed: onExport, tooltip: "Export as vCard", icon: Icon(Icons.upload_file)), + if (isEditing) IconButton(onPressed: onDelete, tooltip: "Delete contact", icon: Icon(Icons.delete)), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: FormBuilder( + key: _formKey, + child: Column( + children: [ + Gap(16), + Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + FormBuilderTextField( + name: "name", + decoration: const InputDecoration( + labelText: "Name", + prefixIcon: Icon(Icons.person_outline), + ), + initialValue: widget.contact?.name ?? '', + validator: (v) => (v == null || v.trim().isEmpty) ? 'Name is required' : null, ), - initialValue: widget.contact?.name ?? '', - validator: (v) => - (v == null || v.trim().isEmpty) ? 'Name is required' : null, - ), - ], + ], + ), ), ), - ), - Gap(12), - Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Addresses", - style: Theme.of(context).textTheme.titleMedium), - IconButton( - icon: Icon(Icons.dns_outlined), - tooltip: "Import from OpenAlias", - onPressed: () => onImportOpenalias(), - ), - ], - ), - Gap(8), - ..._buildAddressFields(), - ], + Gap(12), + Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Addresses", style: Theme.of(context).textTheme.titleMedium), + IconButton( + icon: Icon(Icons.dns_outlined), + tooltip: "Import from OpenAlias", + onPressed: () => onImportOpenalias(), + ), + ], + ), + Gap(8), + ..._buildAddressFields(), + ], + ), ), ), - ), - Gap(12), - Card( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - FormBuilderTextField( - name: "notes", - decoration: const InputDecoration( - labelText: "Notes", - prefixIcon: Icon(Icons.notes), + Gap(12), + Card( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + FormBuilderTextField( + name: "notes", + decoration: const InputDecoration( + labelText: "Notes", + prefixIcon: Icon(Icons.notes), + ), + initialValue: widget.contact?.notes ?? '', + maxLines: 3, ), - initialValue: widget.contact?.notes ?? '', - maxLines: 3, - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), ), ), - ), ); } diff --git a/lib/pages/db.dart b/lib/pages/db.dart index 83ecda9f7..64020916a 100644 --- a/lib/pages/db.dart +++ b/lib/pages/db.dart @@ -74,13 +74,11 @@ class DatabaseManagerState extends ConsumerState { setState(() => dbNames[index] = (dbName.$1, v ?? false)); }, ), - title: Text(dbName.$1, - style: isLastOpened - ? TextStyle(fontWeight: FontWeight.bold) - : null,), - trailing: isLastOpened - ? Icon(Icons.check, color: Theme.of(context).colorScheme.primary) - : null, + title: Text( + dbName.$1, + style: isLastOpened ? TextStyle(fontWeight: FontWeight.bold) : null, + ), + trailing: isLastOpened ? Icon(Icons.check, color: Theme.of(context).colorScheme.primary) : null, onTap: () => onSelect(dbName.$1), ); }, @@ -104,9 +102,7 @@ class DatabaseManagerState extends ConsumerState { if (!mounted) return; - final message = accountsInfo != null - ? 'Open database "$dbName"?\nAccounts: $accountsInfo' - : 'Open database "$dbName"?'; + final message = accountsInfo != null ? 'Open database "$dbName"?\nAccounts: $accountsInfo' : 'Open database "$dbName"?'; final confirmed = await confirmDialog(context, title: "Open Database", message: message); if (!mounted) return; diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 59c5edaf3..e993c0410 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -17,8 +17,7 @@ class MigratePage extends StatefulWidget { State createState() => _MigratePageState(); } -class _MigratePageState extends State - with WidgetsBindingObserver { +class _MigratePageState extends State with WidgetsBindingObserver { StreamSubscription? _sub; MigrationStatus? _status; Timer? _countdown; @@ -79,8 +78,7 @@ class _MigratePageState extends State void _startMigration() { try { _sub?.cancel(); - final meanDelayMs = - BigInt.from(_speedMeanMs[_speedIndex.round()]); + final meanDelayMs = BigInt.from(_speedMeanMs[_speedIndex.round()]); final stream = _runCancellableMigration(meanDelayMs: meanDelayMs); _sub = stream.listen( (status) { @@ -89,8 +87,7 @@ class _MigratePageState extends State if (status.nextAction.startsWith('Waiting')) { // Parse total seconds and start countdown - final m = - RegExp(r'Waiting (\d+)s').firstMatch(status.nextAction); + final m = RegExp(r'Waiting (\d+)s').firstMatch(status.nextAction); if (m != null) { _hasCountdown = true; _countdownSecs = int.parse(m.group(1)!); @@ -123,8 +120,7 @@ class _MigratePageState extends State }, onError: (e) { if (!mounted) return; - final message = - e is AnyhowException ? e.message : e.toString(); + final message = e is AnyhowException ? e.message : e.toString(); showException(context, message); }, ); @@ -162,8 +158,7 @@ class _MigratePageState extends State context: context, builder: (_) => AlertDialog( title: const Text("Migration Complete"), - content: const Text( - "All notes have been migrated to Ironwood."), + content: const Text("All notes have been migrated to Ironwood."), actions: [ TextButton( onPressed: () { @@ -234,96 +229,77 @@ class _MigratePageState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Orchard to Ironwood Migration", - style: Theme.of(context).textTheme.headlineSmall), - const Gap(12), - const Text( - "This process migrates your Orchard notes to Ironwood " - "in two phases:\n\n" - "1. Splitting — non-standard notes are split into " - "standard denominations that can be migrated " - "efficiently.\n\n" - "2. Migrating — standard-denomination notes are " - "moved one-by-one to Ironwood.\n\n" - "The migration runs automatically in the background " - "with random delays between steps. You can close " - "this page at any time and resume later.\n\n" - "Fees apply to each transaction.", - ), - const Gap(16), - // Speed selector - Text("Migration Speed", - style: Theme.of(context).textTheme.titleMedium), - const Gap(8), - Row( - children: [ - Expanded( - child: Slider( - value: _speedIndex, - min: 0, - max: 3, - divisions: 3, - label: _speedLabels[_speedIndex.round()], - onChanged: (v) => - setState(() => _speedIndex = v), + Text("Orchard to Ironwood Migration", style: Theme.of(context).textTheme.headlineSmall), + const Gap(12), + const Text( + "This process migrates your Orchard notes to Ironwood " + "in two phases:\n\n" + "1. Splitting — non-standard notes are split into " + "standard denominations that can be migrated " + "efficiently.\n\n" + "2. Migrating — standard-denomination notes are " + "moved one-by-one to Ironwood.\n\n" + "The migration runs automatically in the background " + "with random delays between steps. You can close " + "this page at any time and resume later.\n\n" + "Fees apply to each transaction.", + ), + const Gap(16), + // Speed selector + Text("Migration Speed", style: Theme.of(context).textTheme.titleMedium), + const Gap(8), + Row( + children: [ + Expanded( + child: Slider( + value: _speedIndex, + min: 0, + max: 3, + divisions: 3, + label: _speedLabels[_speedIndex.round()], + onChanged: (v) => setState(() => _speedIndex = v), + ), ), - ), - SizedBox( - width: 80, - child: Text( - _speedLabels[_speedIndex.round()], - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(fontWeight: FontWeight.bold), + SizedBox( + width: 80, + child: Text( + _speedLabels[_speedIndex.round()], + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.bold), + ), ), - ), - ], - ), - Text( - _speedDescriptions[_speedIndex.round()], - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - const Gap(12), - // Privacy note - Card( - color: Theme.of(context) - .colorScheme - .surfaceContainerHighest, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(Icons.shield_outlined, - size: 20, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant), - const Gap(8), - Expanded( - child: Text( - "Faster migration creates transactions closer " - "together, making it easier for an observer " - "to correlate them as part of the same " - "migration. Slower speeds spread " - "transactions out over time, improving " - "privacy.", - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant), + ], + ), + Text( + _speedDescriptions[_speedIndex.round()], + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + const Gap(12), + // Privacy note + Card( + color: Theme.of(context).colorScheme.surfaceContainerHighest, + child: Padding( + padding: const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(Icons.shield_outlined, size: 20, color: Theme.of(context).colorScheme.onSurfaceVariant), + const Gap(8), + Expanded( + child: Text( + "Faster migration creates transactions closer " + "together, making it easier for an observer " + "to correlate them as part of the same " + "migration. Slower speeds spread " + "transactions out over time, improving " + "privacy.", + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant), + ), ), - ), - ], + ], + ), ), ), - ), - const Gap(16), + const Gap(16), FilledButton.icon( onPressed: () { setState(() => _started = true); @@ -376,128 +352,123 @@ class _MigratePageState extends State body: ListView( padding: const EdgeInsets.all(16), children: [ - // Phase indicator - Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Icon( - isComplete - ? Icons.check_circle - : isActive - ? Icons.sync - : Icons.schedule, - size: 48, - color: isComplete - ? Colors.green - : isActive - ? t.colorScheme.primary - : Colors.grey, - ), - const Gap(8), - Text( - isComplete - ? "Migration Complete" - : waiting - ? "Waiting..." - : isActive - ? "Migrating to Ironwood" - : "Ready to Migrate", - style: tt.headlineSmall, - ), - const Gap(4), - Text( - waiting - ? _hasCountdown - ? "Waiting ${_countdownSecs}s..." - : status.nextAction - : phase == 'splitting' - ? "Phase 1: Splitting into standard denominations" - : phase == 'migrating' - ? "Phase 2: Migrating notes to Ironwood" - : phase == 'complete' - ? "All notes have been migrated" - : "Start the migration to move your funds", - style: tt.bodyMedium?.copyWith( - color: t.colorScheme.onSurfaceVariant), - ), - ], - ), - ), - ), - const Gap(16), - - // Progress - if (isActive || isComplete) ...[ + // Phase indicator Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Progress", style: tt.titleMedium), + Icon( + isComplete + ? Icons.check_circle + : isActive + ? Icons.sync + : Icons.schedule, + size: 48, + color: isComplete + ? Colors.green + : isActive + ? t.colorScheme.primary + : Colors.grey, + ), const Gap(8), - LinearProgressIndicator(value: status.progress), + Text( + isComplete + ? "Migration Complete" + : waiting + ? "Waiting..." + : isActive + ? "Migrating to Ironwood" + : "Ready to Migrate", + style: tt.headlineSmall, + ), + const Gap(4), + Text( + waiting + ? _hasCountdown + ? "Waiting ${_countdownSecs}s..." + : status.nextAction + : phase == 'splitting' + ? "Phase 1: Splitting into standard denominations" + : phase == 'migrating' + ? "Phase 2: Migrating notes to Ironwood" + : phase == 'complete' + ? "All notes have been migrated" + : "Start the migration to move your funds", + style: tt.bodyMedium?.copyWith(color: t.colorScheme.onSurfaceVariant), + ), ], ), ), ), const Gap(16), - ], - // Note counts — phase-dependent - if (isActive || isComplete) ...[ + // Progress + if (isActive || isComplete) ...[ + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Progress", style: tt.titleMedium), + const Gap(8), + LinearProgressIndicator(value: status.progress), + ], + ), + ), + ), + const Gap(16), + ], + + // Note counts — phase-dependent + if (isActive || isComplete) ...[ + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(phase == 'migrating' ? "Migration Progress" : "Orchard Notes", style: tt.titleMedium), + const Gap(8), + Text( + phase == 'migrating' + ? "Orchard: ${status.sdNotesCount} SD | Ironwood: ${status.ironwoodSdCount} SD" + : "SD: ${status.sdNotesCount} | Non-SD: ${status.nonSdNotesCount}", + style: tt.bodyLarge, + ), + ], + ), + ), + ), + const Gap(16), + ], + + // Fee summary Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - phase == 'migrating' - ? "Migration Progress" - : "Orchard Notes", - style: tt.titleMedium), + Text("Fees", style: tt.titleMedium), const Gap(8), - Text( - phase == 'migrating' - ? "Orchard: ${status.sdNotesCount} SD | Ironwood: ${status.ironwoodSdCount} SD" - : "SD: ${status.sdNotesCount} | Non-SD: ${status.nonSdNotesCount}", - style: tt.bodyLarge, - ), + _feeRow("Split fees", status.splitFees), + _feeRow("Migration fees", status.migrateFees), + const Divider(), + _feeRow("Total", status.totalFees, bold: true), ], ), ), ), const Gap(16), - ], - // Fee summary - Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Fees", style: tt.titleMedium), - const Gap(8), - _feeRow("Split fees", status.splitFees), - _feeRow("Migration fees", status.migrateFees), - const Divider(), - _feeRow("Total", status.totalFees, bold: true), - ], + // Actions + if (isComplete) + FilledButton( + onPressed: () => GoRouter.of(context).pop(), + child: const Text("Done"), ), - ), - ), - const Gap(16), - - // Actions - if (isComplete) - FilledButton( - onPressed: () => GoRouter.of(context).pop(), - child: const Text("Done"), - ), ], ), ), @@ -548,9 +519,7 @@ class _MigratePageState extends State child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(label, - style: TextStyle( - fontWeight: bold ? FontWeight.bold : FontWeight.normal)), + Text(label, style: TextStyle(fontWeight: bold ? FontWeight.bold : FontWeight.normal)), Text( zec.toStringAsFixed(8), style: TextStyle( diff --git a/lib/pages/plugin_manager.dart b/lib/pages/plugin_manager.dart index 26d84c97a..78ebf8837 100644 --- a/lib/pages/plugin_manager.dart +++ b/lib/pages/plugin_manager.dart @@ -25,9 +25,7 @@ class _PluginManagerPageState extends ConsumerState { return Scaffold( appBar: AppBar( title: Text( - _selectedIds.isEmpty - ? 'Plugin Manager' - : '${_selectedIds.length} selected', + _selectedIds.isEmpty ? 'Plugin Manager' : '${_selectedIds.length} selected', ), actions: [ if (_selectedIds.isEmpty) @@ -116,8 +114,7 @@ class _PluginManagerPageState extends ConsumerState { final confirmed = await confirmDialog( context, title: 'Remove Plugins', - message: - 'Remove $count selected plugin${count > 1 ? 's' : ''}? This cannot be undone.', + message: 'Remove $count selected plugin${count > 1 ? 's' : ''}? This cannot be undone.', ); if (!confirmed) return; @@ -170,10 +167,7 @@ class _PluginListTile extends ConsumerWidget { Text('v${plugin.version}'), if (plugin.memoPrefixes.length > 1) Text( - plugin.memoPrefixes - .skip(1) - .map((p) => _prefixAscii([p])) - .join(', '), + plugin.memoPrefixes.skip(1).map((p) => _prefixAscii([p])).join(', '), style: TextStyle( fontSize: 12, fontFamily: 'monospace', @@ -191,26 +185,20 @@ class _PluginListTile extends ConsumerWidget { ) : prefixLabel != null ? CircleAvatar( - backgroundColor: plugin.enabled - ? t.colorScheme.primaryContainer - : t.disabledColor.withAlpha(40), + backgroundColor: plugin.enabled ? t.colorScheme.primaryContainer : t.disabledColor.withAlpha(40), child: Text( prefixLabel, style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold, fontFamily: 'monospace', - color: plugin.enabled - ? t.colorScheme.onPrimaryContainer - : t.disabledColor, + color: plugin.enabled ? t.colorScheme.onPrimaryContainer : t.disabledColor, ), ), ) : Icon( plugin.enabled ? Icons.extension : Icons.extension_off, - color: plugin.enabled - ? t.colorScheme.primary - : t.disabledColor, + color: plugin.enabled ? t.colorScheme.primary : t.disabledColor, ), ), trailing: Switch( @@ -233,8 +221,6 @@ String? _prefixAscii(List prefixes) { final ascii = String.fromCharCodes(bytes); return ascii.length > 4 ? ascii.substring(0, 4) : ascii; } catch (_) { - return prefixes.first.length > 4 - ? prefixes.first.substring(0, 4) - : prefixes.first; + return prefixes.first.length > 4 ? prefixes.first.substring(0, 4) : prefixes.first; } } diff --git a/lib/pages/receive.dart b/lib/pages/receive.dart index 1fd78459a..ce26ec724 100644 --- a/lib/pages/receive.dart +++ b/lib/pages/receive.dart @@ -259,23 +259,28 @@ class _AddressesPageState extends ConsumerState { } ButtonStyle get _segmentedStyle => SegmentedButton.styleFrom( - backgroundColor: Colors.grey[200], - foregroundColor: Colors.red, - selectedForegroundColor: Colors.white, - selectedBackgroundColor: Colors.green, - ); + backgroundColor: Colors.grey[200], + foregroundColor: Colors.red, + selectedForegroundColor: Colors.white, + selectedBackgroundColor: Colors.green, + ); List _filtered() => _txCounts.where((tx) { - switch (_scopeFilter) { - case 1: if (tx.scope != 0) return false; - case 2: if (tx.scope != 1) return false; - } - switch (_usageFilter) { - case 1: return tx.txCount > 0; - case 2: return tx.txCount == 0; - default: return true; - } - }).toList(); + switch (_scopeFilter) { + case 1: + if (tx.scope != 0) return false; + case 2: + if (tx.scope != 1) return false; + } + switch (_usageFilter) { + case 1: + return tx.txCount > 0; + case 2: + return tx.txCount == 0; + default: + return true; + } + }).toList(); @override Widget build(BuildContext context) { @@ -368,9 +373,7 @@ class _AddressesPageState extends ConsumerState { itemBuilder: (context, index) { final tx = filtered[index]; final lastUsed = tx.time > 0 ? timeToString(tx.time) : "Never"; - final trimmed = tx.address.length > 20 - ? '${tx.address.substring(0, 10)}...${tx.address.substring(tx.address.length - 8)}' - : tx.address; + final trimmed = tx.address.length > 20 ? '${tx.address.substring(0, 10)}...${tx.address.substring(tx.address.length - 8)}' : tx.address; return ListTile( leading: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/pages/send.dart b/lib/pages/send.dart index d778e93ce..87a32eb11 100644 --- a/lib/pages/send.dart +++ b/lib/pages/send.dart @@ -106,9 +106,7 @@ class SendPageState extends ConsumerState { .mapIndexed( (i, r) => ListTile( title: Text(r.address), - subtitle: r.assetBase.every((b) => b == 0) - ? zatToText(r.amount, selectable: false) - : Text("${r.amount} ${r.assetName!}"), + subtitle: r.assetBase.every((b) => b == 0) ? zatToText(r.amount, selectable: false) : Text("${r.amount} ${r.assetName!}"), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () { diff --git a/lib/pages/tx.dart b/lib/pages/tx.dart index 4e656fcd5..3cc2236d3 100644 --- a/lib/pages/tx.dart +++ b/lib/pages/tx.dart @@ -111,9 +111,12 @@ class TxPageState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(_sendStep, - style: t.bodyMedium - ?.copyWith(fontWeight: FontWeight.w600,),), + Text( + _sendStep, + style: t.bodyMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + ), Text( "Tx will be sent in the background if this page is closed", style: t.bodySmall, @@ -125,8 +128,7 @@ class TxPageState extends ConsumerState { ), Divider(height: 24), ], - if (success) - Text("Tx Sent Successfully", style: t.titleSmall), + if (success) Text("Tx Sent Successfully", style: t.titleSmall), Text("Fee: ${zatToString(txPlan.fee)}"), Gap(8), if (txId != null) @@ -138,8 +140,7 @@ class TxPageState extends ConsumerState { ), ), ), - if (!success) - showTxPlan(context, txPlan), + if (!success) showTxPlan(context, txPlan), ], ), ), diff --git a/lib/pages/tx_view.dart b/lib/pages/tx_view.dart index c880aca20..065976829 100644 --- a/lib/pages/tx_view.dart +++ b/lib/pages/tx_view.dart @@ -63,9 +63,7 @@ class TxViewPageState extends ConsumerState { } void _startMemoEditing(TxAccount txd) { - final firstTextMemo = txd.memos - .map((m) => m.memo) - .firstWhere((m) => m != null && m.isNotEmpty, orElse: () => null); + final firstTextMemo = txd.memos.map((m) => m.memo).firstWhere((m) => m != null && m.isNotEmpty, orElse: () => null); _memoController.text = txd.userMemo ?? firstTextMemo ?? ''; _memoController.selection = TextSelection.fromPosition( TextPosition(offset: _memoController.text.length), @@ -83,9 +81,7 @@ class TxViewPageState extends ConsumerState { final newText = _memoController.text.trim(); // Compute the effective memo before editing - final firstTextMemo = txd.memos - .map((m) => m.memo) - .firstWhere((m) => m != null && m.isNotEmpty, orElse: () => null); + final firstTextMemo = txd.memos.map((m) => m.memo).firstWhere((m) => m != null && m.isNotEmpty, orElse: () => null); final oldText = txd.userMemo ?? firstTextMemo ?? ''; setState(() {}); @@ -149,14 +145,8 @@ class TxViewPageState extends ConsumerState { List show(TxAccount txd) { final t = Theme.of(context).textTheme; // ZEC totals (idAsset == null) - final zecSpent = txd.spends - .where((n) => n.idAsset == null) - .map((n) => n.value) - .fold(BigInt.zero, (a, b) => a + b); - final zecReceived = txd.notes - .where((n) => n.idAsset == null) - .map((n) => n.value) - .fold(BigInt.zero, (a, b) => a + b); + final zecSpent = txd.spends.where((n) => n.idAsset == null).map((n) => n.value).fold(BigInt.zero, (a, b) => a + b); + final zecReceived = txd.notes.where((n) => n.idAsset == null).map((n) => n.value).fold(BigInt.zero, (a, b) => a + b); // ZSA totals grouped by assetDisplay final zsaSpent = {}; diff --git a/lib/settings.dart b/lib/settings.dart index 70c7cfc68..de55519a2 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -370,8 +370,7 @@ class SettingsFormState extends ConsumerState { Text("Downloaded", style: TextStyle(color: Colors.green)), ]) else ...[ - Text("Not Downloaded", - style: TextStyle(color: Colors.orange.shade700)), + Text("Not Downloaded", style: TextStyle(color: Colors.orange.shade700)), Gap(8), if (saplingDownloading) SizedBox( @@ -875,9 +874,9 @@ class SettingsFormState extends ConsumerState { } if (mounted) { await ref.read(vaultProvider.notifier).registerDevice( - password: masterPassword!, - prf: prf, - ); + password: masterPassword!, + prf: prf, + ); } } catch (e) { logger.w("[Recover] passkey registration failed: $e"); @@ -904,7 +903,7 @@ class SettingsFormState extends ConsumerState { await showException( context, "The local database must be empty before compressing the vault. " - "Please delete all accounts first.", + "Please delete all accounts first.", ); } return; @@ -924,12 +923,8 @@ class SettingsFormState extends ConsumerState { List recovered; AwesomeDialog? compressLoading = showLoadingDialog(context, "Downloading vault..."); try { - vaultBytes = await ref - .read(vaultProvider.notifier) - .downloadVaultBytes(); - recovered = await ref - .read(vaultProvider.notifier) - .recoverVault(vaultBytes: vaultBytes, masterPassword: password); + vaultBytes = await ref.read(vaultProvider.notifier).downloadVaultBytes(); + recovered = await ref.read(vaultProvider.notifier).recoverVault(vaultBytes: vaultBytes, masterPassword: password); compressLoading.dismiss(); } catch (e) { compressLoading.dismiss(); @@ -969,8 +964,7 @@ class SettingsFormState extends ConsumerState { final switchAccount = await confirmDialog( context, title: "Switch Google Account?", - message: - "Do you want to create the new vault on a different Google account?", + message: "Do you want to create the new vault on a different Google account?", ); if (!mounted) return; diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index d13212c6a..79a6fefa1 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -14,171 +14,107 @@ part 'account.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `get_ledger` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt` -Future getAccountPools({required int account, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountPools(account: account, c: c); +Future getAccountPools({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountPools(account: account, c: c); -Future getAccountUfvk( - {required int account, required int pools, required Coin c}) => - RustLib.instance.api - .crateApiAccountGetAccountUfvk(account: account, pools: pools, c: c); +Future getAccountUfvk({required int account, required int pools, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountUfvk(account: account, pools: pools, c: c); -Future getAccountSeed({required int account, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountSeed(account: account, c: c); +Future getAccountSeed({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountSeed(account: account, c: c); -Future getAccountFingerprint( - {required int account, required Coin c}) => - RustLib.instance.api - .crateApiAccountGetAccountFingerprint(account: account, c: c); +Future getAccountFingerprint({required int account, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountFingerprint(account: account, c: c); -String uaFromUfvk({required String ufvk, int? di, required Coin c}) => - RustLib.instance.api.crateApiAccountUaFromUfvk(ufvk: ufvk, di: di, c: c); +String uaFromUfvk({required String ufvk, int? di, required Coin c}) => RustLib.instance.api.crateApiAccountUaFromUfvk(ufvk: ufvk, di: di, c: c); -Receivers receiversFromUa({required String ua, required Coin c}) => - RustLib.instance.api.crateApiAccountReceiversFromUa(ua: ua, c: c); +Receivers receiversFromUa({required String ua, required Coin c}) => RustLib.instance.api.crateApiAccountReceiversFromUa(ua: ua, c: c); -Future> listAccounts({required Coin c}) => - RustLib.instance.api.crateApiAccountListAccounts(c: c); +Future> listAccounts({required Coin c}) => RustLib.instance.api.crateApiAccountListAccounts(c: c); -Future updateAccount({required AccountUpdate update, required Coin c}) => - RustLib.instance.api.crateApiAccountUpdateAccount(update: update, c: c); +Future updateAccount({required AccountUpdate update, required Coin c}) => RustLib.instance.api.crateApiAccountUpdateAccount(update: update, c: c); -Future deleteAccount({required int account, required Coin c}) => - RustLib.instance.api.crateApiAccountDeleteAccount(account: account, c: c); +Future deleteAccount({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteAccount(account: account, c: c); -Future reorderAccount( - {required int oldPosition, - required int newPosition, - required Coin c}) => - RustLib.instance.api.crateApiAccountReorderAccount( - oldPosition: oldPosition, newPosition: newPosition, c: c); +Future reorderAccount({required int oldPosition, required int newPosition, required Coin c}) => + RustLib.instance.api.crateApiAccountReorderAccount(oldPosition: oldPosition, newPosition: newPosition, c: c); -Future newAccount({required NewAccount na, required Coin c}) => - RustLib.instance.api.crateApiAccountNewAccount(na: na, c: c); +Future newAccount({required NewAccount na, required Coin c}) => RustLib.instance.api.crateApiAccountNewAccount(na: na, c: c); -Future hasTransparentPubKey({required Coin c}) => - RustLib.instance.api.crateApiAccountHasTransparentPubKey(c: c); +Future hasTransparentPubKey({required Coin c}) => RustLib.instance.api.crateApiAccountHasTransparentPubKey(c: c); -Future generateNextDindex({required Coin c}) => - RustLib.instance.api.crateApiAccountGenerateNextDindex(c: c); +Future generateNextDindex({required Coin c}) => RustLib.instance.api.crateApiAccountGenerateNextDindex(c: c); -Future generateNextChangeAddress({required Coin c}) => - RustLib.instance.api.crateApiAccountGenerateNextChangeAddress(c: c); +Future generateNextChangeAddress({required Coin c}) => RustLib.instance.api.crateApiAccountGenerateNextChangeAddress(c: c); -Future resetSync({required int id, required Coin c}) => - RustLib.instance.api.crateApiAccountResetSync(id: id, c: c); +Future resetSync({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountResetSync(id: id, c: c); -Future removeAccount({required int accountId, required Coin c}) => - RustLib.instance.api - .crateApiAccountRemoveAccount(accountId: accountId, c: c); +Future removeAccount({required int accountId, required Coin c}) => RustLib.instance.api.crateApiAccountRemoveAccount(accountId: accountId, c: c); -Future> listTxHistory({required Coin c}) => - RustLib.instance.api.crateApiAccountListTxHistory(c: c); +Future> listTxHistory({required Coin c}) => RustLib.instance.api.crateApiAccountListTxHistory(c: c); -Future> listMemos({required Coin c}) => - RustLib.instance.api.crateApiAccountListMemos(c: c); +Future> listMemos({required Coin c}) => RustLib.instance.api.crateApiAccountListMemos(c: c); -Future getAddresses({required int uaPools, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAddresses(uaPools: uaPools, c: c); +Future getAddresses({required int uaPools, required Coin c}) => RustLib.instance.api.crateApiAccountGetAddresses(uaPools: uaPools, c: c); -Future getAccountAddresses( - {required int account, required int uaPools, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountAddresses( - account: account, uaPools: uaPools, c: c); +Future getAccountAddresses({required int account, required int uaPools, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountAddresses(account: account, uaPools: uaPools, c: c); -Future getTxDetails({required int idTx, required Coin c}) => - RustLib.instance.api.crateApiAccountGetTxDetails(idTx: idTx, c: c); +Future getTxDetails({required int idTx, required Coin c}) => RustLib.instance.api.crateApiAccountGetTxDetails(idTx: idTx, c: c); -Future> listNotes({required Coin c}) => - RustLib.instance.api.crateApiAccountListNotes(c: c); +Future> listNotes({required Coin c}) => RustLib.instance.api.crateApiAccountListNotes(c: c); -Future lockNote( - {required int id, required bool locked, required Coin c}) => - RustLib.instance.api.crateApiAccountLockNote(id: id, locked: locked, c: c); +Future lockNote({required int id, required bool locked, required Coin c}) => RustLib.instance.api.crateApiAccountLockNote(id: id, locked: locked, c: c); -Future> fetchTransparentAddressTxCount( - {required Coin c}) => - RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); +Future> fetchTransparentAddressTxCount({required Coin c}) => RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); -Future> fetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}) => - RustLib.instance.api.crateApiAccountFetchAddressTxCount( - c: c, aggregate: aggregate, poolFilter: poolFilter); +Future> fetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}) => + RustLib.instance.api.crateApiAccountFetchAddressTxCount(c: c, aggregate: aggregate, poolFilter: poolFilter); -Future exportAccount( - {required int id, required String passphrase, required Coin c}) => - RustLib.instance.api - .crateApiAccountExportAccount(id: id, passphrase: passphrase, c: c); +Future exportAccount({required int id, required String passphrase, required Coin c}) => + RustLib.instance.api.crateApiAccountExportAccount(id: id, passphrase: passphrase, c: c); -Future importAccount( - {required String passphrase, - required List data, - required Coin c}) => - RustLib.instance.api - .crateApiAccountImportAccount(passphrase: passphrase, data: data, c: c); +Future importAccount({required String passphrase, required List data, required Coin c}) => + RustLib.instance.api.crateApiAccountImportAccount(passphrase: passphrase, data: data, c: c); -Future printKeys({required int id, required Coin c}) => - RustLib.instance.api.crateApiAccountPrintKeys(id: id, c: c); +Future printKeys({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountPrintKeys(id: id, c: c); -Future getAccountFrostParams({required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountFrostParams(c: c); +Future getAccountFrostParams({required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountFrostParams(c: c); -Future> listFolders({required Coin c}) => - RustLib.instance.api.crateApiAccountListFolders(c: c); +Future> listFolders({required Coin c}) => RustLib.instance.api.crateApiAccountListFolders(c: c); -Future createNewFolder({required String name, required Coin c}) => - RustLib.instance.api.crateApiAccountCreateNewFolder(name: name, c: c); +Future createNewFolder({required String name, required Coin c}) => RustLib.instance.api.crateApiAccountCreateNewFolder(name: name, c: c); -Future renameFolder( - {required int id, required String name, required Coin c}) => +Future renameFolder({required int id, required String name, required Coin c}) => RustLib.instance.api.crateApiAccountRenameFolder(id: id, name: name, c: c); -Future deleteFolders({required List ids, required Coin c}) => - RustLib.instance.api.crateApiAccountDeleteFolders(ids: ids, c: c); +Future deleteFolders({required List ids, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteFolders(ids: ids, c: c); -Future> listCategories({required Coin c}) => - RustLib.instance.api.crateApiAccountListCategories(c: c); +Future> listCategories({required Coin c}) => RustLib.instance.api.crateApiAccountListCategories(c: c); -Future createNewCategory({required Category category, required Coin c}) => - RustLib.instance.api - .crateApiAccountCreateNewCategory(category: category, c: c); +Future createNewCategory({required Category category, required Coin c}) => RustLib.instance.api.crateApiAccountCreateNewCategory(category: category, c: c); -Future renameCategory({required Category category, required Coin c}) => - RustLib.instance.api - .crateApiAccountRenameCategory(category: category, c: c); +Future renameCategory({required Category category, required Coin c}) => RustLib.instance.api.crateApiAccountRenameCategory(category: category, c: c); -Future deleteCategories({required List ids, required Coin c}) => - RustLib.instance.api.crateApiAccountDeleteCategories(ids: ids, c: c); +Future deleteCategories({required List ids, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteCategories(ids: ids, c: c); -Future getExportedData({required int type, required Coin c}) => - RustLib.instance.api.crateApiAccountGetExportedData(type: type, c: c); +Future getExportedData({required int type, required Coin c}) => RustLib.instance.api.crateApiAccountGetExportedData(type: type, c: c); -Future lockRecentNotes( - {required int height, required int threshold, required Coin c}) => - RustLib.instance.api.crateApiAccountLockRecentNotes( - height: height, threshold: threshold, c: c); +Future lockRecentNotes({required int height, required int threshold, required Coin c}) => + RustLib.instance.api.crateApiAccountLockRecentNotes(height: height, threshold: threshold, c: c); -Future unlockAllNotes({required Coin c}) => - RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); +Future unlockAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); -Future toggleAllNotes({required Coin c}) => - RustLib.instance.api.crateApiAccountToggleAllNotes(c: c); +Future toggleAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountToggleAllNotes(c: c); -Future maxSpendable({required Coin c}) => - RustLib.instance.api.crateApiAccountMaxSpendable(c: c); +Future maxSpendable({required Coin c}) => RustLib.instance.api.crateApiAccountMaxSpendable(c: c); -Future showLedgerSaplingAddress({required Coin c}) => - RustLib.instance.api.crateApiAccountShowLedgerSaplingAddress(c: c); +Future showLedgerSaplingAddress({required Coin c}) => RustLib.instance.api.crateApiAccountShowLedgerSaplingAddress(c: c); -Future showLedgerTransparentAddress({required Coin c}) => - RustLib.instance.api.crateApiAccountShowLedgerTransparentAddress(c: c); +Future showLedgerTransparentAddress({required Coin c}) => RustLib.instance.api.crateApiAccountShowLedgerTransparentAddress(c: c); -Stream signLedgerTransaction( - {required PcztPackage package, required Coin c}) => - RustLib.instance.api - .crateApiAccountSignLedgerTransaction(package: package, c: c); +Stream signLedgerTransaction({required PcztPackage package, required Coin c}) => + RustLib.instance.api.crateApiAccountSignLedgerTransaction(package: package, c: c); -Future dummyExport({required SigningEvent a}) => - RustLib.instance.api.crateApiAccountDummyExport(a: a); +Future dummyExport({required SigningEvent a}) => RustLib.instance.api.crateApiAccountDummyExport(a: a); @freezed sealed class Account with _$Account { @@ -236,12 +172,7 @@ class Addresses { }); @override - int get hashCode => - taddr.hashCode ^ - saddr.hashCode ^ - oaddr.hashCode ^ - ua.hashCode ^ - diversifierIndex.hashCode; + int get hashCode => taddr.hashCode ^ saddr.hashCode ^ oaddr.hashCode ^ ua.hashCode ^ diversifierIndex.hashCode; @override bool operator ==(Object other) => @@ -327,20 +258,14 @@ class Receivers { this.oaddr, }); - static Future default_() => - RustLib.instance.api.crateApiAccountReceiversDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountReceiversDefault(); @override int get hashCode => taddr.hashCode ^ saddr.hashCode ^ oaddr.hashCode; @override bool operator ==(Object other) => - identical(this, other) || - other is Receivers && - runtimeType == other.runtimeType && - taddr == other.taddr && - saddr == other.saddr && - oaddr == other.oaddr; + identical(this, other) || other is Receivers && runtimeType == other.runtimeType && taddr == other.taddr && saddr == other.saddr && oaddr == other.oaddr; } @freezed @@ -372,14 +297,7 @@ class TAddressTxCount { }); @override - int get hashCode => - pool.hashCode ^ - address.hashCode ^ - scope.hashCode ^ - dindex.hashCode ^ - amount.hashCode ^ - txCount.hashCode ^ - time.hashCode; + int get hashCode => pool.hashCode ^ address.hashCode ^ scope.hashCode ^ dindex.hashCode ^ amount.hashCode ^ txCount.hashCode ^ time.hashCode; @override bool operator ==(Object other) => @@ -444,8 +362,7 @@ class TxAccount { this.userMemo, }); - static Future default_() => - RustLib.instance.api.crateApiAccountTxAccountDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountTxAccountDefault(); @override int get hashCode => @@ -496,16 +413,10 @@ class TxMemo { required this.memoBytes, }); - static Future default_() => - RustLib.instance.api.crateApiAccountTxMemoDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountTxMemoDefault(); @override - int get hashCode => - note.hashCode ^ - output.hashCode ^ - pool.hashCode ^ - memo.hashCode ^ - memoBytes.hashCode; + int get hashCode => note.hashCode ^ output.hashCode ^ pool.hashCode ^ memo.hashCode ^ memoBytes.hashCode; @override bool operator ==(Object other) => @@ -548,8 +459,7 @@ class TxNote { required this.assetDisplay, }); - static Future default_() => - RustLib.instance.api.crateApiAccountTxNoteDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountTxNoteDefault(); @override int get hashCode => @@ -602,17 +512,10 @@ class TxOutput { this.contactName, }); - static Future default_() => - RustLib.instance.api.crateApiAccountTxOutputDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountTxOutputDefault(); @override - int get hashCode => - id.hashCode ^ - pool.hashCode ^ - height.hashCode ^ - value.hashCode ^ - address.hashCode ^ - contactName.hashCode; + int get hashCode => id.hashCode ^ pool.hashCode ^ height.hashCode ^ value.hashCode ^ address.hashCode ^ contactName.hashCode; @override bool operator ==(Object other) => @@ -644,17 +547,10 @@ class TxSpend { required this.assetDisplay, }); - static Future default_() => - RustLib.instance.api.crateApiAccountTxSpendDefault(); + static Future default_() => RustLib.instance.api.crateApiAccountTxSpendDefault(); @override - int get hashCode => - id.hashCode ^ - pool.hashCode ^ - height.hashCode ^ - value.hashCode ^ - idAsset.hashCode ^ - assetDisplay.hashCode; + int get hashCode => id.hashCode ^ pool.hashCode ^ height.hashCode ^ value.hashCode ^ idAsset.hashCode ^ assetDisplay.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/account.freezed.dart b/lib/src/rust/api/account.freezed.dart index 20e59b151..1a4003e5f 100644 --- a/lib/src/rust/api/account.freezed.dart +++ b/lib/src/rust/api/account.freezed.dart @@ -39,8 +39,7 @@ mixin _$Account { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountCopyWith get copyWith => - _$AccountCopyWithImpl(this as Account, _$identity); + $AccountCopyWith get copyWith => _$AccountCopyWithImpl(this as Account, _$identity); @override bool operator ==(Object other) { @@ -51,22 +50,18 @@ mixin _$Account { (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && (identical(other.seed, seed) || other.seed == seed) && - (identical(other.passphrase, passphrase) || - other.passphrase == passphrase) && + (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.dindex, dindex) || other.dindex == dindex) && const DeepCollectionEquality().equals(other.icon, icon) && - (identical(other.useInternal, useInternal) || - other.useInternal == useInternal) && + (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && - (identical(other.position, position) || - other.position == position) && + (identical(other.position, position) || other.position == position) && (identical(other.hidden, hidden) || other.hidden == hidden) && (identical(other.saved, saved) || other.saved == saved) && (identical(other.enabled, enabled) || other.enabled == enabled) && - (identical(other.internal, internal) || - other.internal == internal) && + (identical(other.internal, internal) || other.internal == internal) && (identical(other.hw, hw) || other.hw == hw) && (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && @@ -106,8 +101,7 @@ mixin _$Account { /// @nodoc abstract mixin class $AccountCopyWith<$Res> { - factory $AccountCopyWith(Account value, $Res Function(Account) _then) = - _$AccountCopyWithImpl; + factory $AccountCopyWith(Account value, $Res Function(Account) _then) = _$AccountCopyWithImpl; @useResult $Res call( {int coin, @@ -353,54 +347,16 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult maybeWhen( - TResult Function( - int coin, - int id, - String name, - String? seed, - String? passphrase, - int aindex, - int dindex, - Uint8List? icon, - bool useInternal, - int birth, - Folder folder, - int position, - bool hidden, - bool saved, - bool enabled, - bool internal, - int hw, - int height, - int time, - BigInt balance)? + TResult Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, + Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Account() when $default != null: - return $default( - _that.coin, - _that.id, - _that.name, - _that.seed, - _that.passphrase, - _that.aindex, - _that.dindex, - _that.icon, - _that.useInternal, - _that.birth, - _that.folder, - _that.position, - _that.hidden, - _that.saved, - _that.enabled, - _that.internal, - _that.hw, - _that.height, - _that.time, - _that.balance); + return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, + _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); case _: return orElse(); } @@ -421,53 +377,15 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult when( - TResult Function( - int coin, - int id, - String name, - String? seed, - String? passphrase, - int aindex, - int dindex, - Uint8List? icon, - bool useInternal, - int birth, - Folder folder, - int position, - bool hidden, - bool saved, - bool enabled, - bool internal, - int hw, - int height, - int time, - BigInt balance) + TResult Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, + Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance) $default, ) { final _that = this; switch (_that) { case _Account(): - return $default( - _that.coin, - _that.id, - _that.name, - _that.seed, - _that.passphrase, - _that.aindex, - _that.dindex, - _that.icon, - _that.useInternal, - _that.birth, - _that.folder, - _that.position, - _that.hidden, - _that.saved, - _that.enabled, - _that.internal, - _that.hw, - _that.height, - _that.time, - _that.balance); + return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, + _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); } } @@ -485,53 +403,15 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int coin, - int id, - String name, - String? seed, - String? passphrase, - int aindex, - int dindex, - Uint8List? icon, - bool useInternal, - int birth, - Folder folder, - int position, - bool hidden, - bool saved, - bool enabled, - bool internal, - int hw, - int height, - int time, - BigInt balance)? + TResult? Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, + Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance)? $default, ) { final _that = this; switch (_that) { case _Account() when $default != null: - return $default( - _that.coin, - _that.id, - _that.name, - _that.seed, - _that.passphrase, - _that.aindex, - _that.dindex, - _that.icon, - _that.useInternal, - _that.birth, - _that.folder, - _that.position, - _that.hidden, - _that.saved, - _that.enabled, - _that.internal, - _that.hw, - _that.height, - _that.time, - _that.balance); + return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, + _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); case _: return null; } @@ -609,8 +489,7 @@ class _Account implements Account { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountCopyWith<_Account> get copyWith => - __$AccountCopyWithImpl<_Account>(this, _$identity); + _$AccountCopyWith<_Account> get copyWith => __$AccountCopyWithImpl<_Account>(this, _$identity); @override bool operator ==(Object other) { @@ -621,22 +500,18 @@ class _Account implements Account { (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && (identical(other.seed, seed) || other.seed == seed) && - (identical(other.passphrase, passphrase) || - other.passphrase == passphrase) && + (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.dindex, dindex) || other.dindex == dindex) && const DeepCollectionEquality().equals(other.icon, icon) && - (identical(other.useInternal, useInternal) || - other.useInternal == useInternal) && + (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && - (identical(other.position, position) || - other.position == position) && + (identical(other.position, position) || other.position == position) && (identical(other.hidden, hidden) || other.hidden == hidden) && (identical(other.saved, saved) || other.saved == saved) && (identical(other.enabled, enabled) || other.enabled == enabled) && - (identical(other.internal, internal) || - other.internal == internal) && + (identical(other.internal, internal) || other.internal == internal) && (identical(other.hw, hw) || other.hw == hw) && (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && @@ -676,8 +551,7 @@ class _Account implements Account { /// @nodoc abstract mixin class _$AccountCopyWith<$Res> implements $AccountCopyWith<$Res> { - factory _$AccountCopyWith(_Account value, $Res Function(_Account) _then) = - __$AccountCopyWithImpl; + factory _$AccountCopyWith(_Account value, $Res Function(_Account) _then) = __$AccountCopyWithImpl; @override @useResult $Res call( @@ -849,9 +723,7 @@ mixin _$AccountUpdate { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountUpdateCopyWith get copyWith => - _$AccountUpdateCopyWithImpl( - this as AccountUpdate, _$identity); + $AccountUpdateCopyWith get copyWith => _$AccountUpdateCopyWithImpl(this as AccountUpdate, _$identity); @override bool operator ==(Object other) { @@ -869,16 +741,7 @@ mixin _$AccountUpdate { } @override - int get hashCode => Object.hash( - runtimeType, - coin, - id, - name, - const DeepCollectionEquality().hash(icon), - birth, - folder, - hidden, - enabled); + int get hashCode => Object.hash(runtimeType, coin, id, name, const DeepCollectionEquality().hash(icon), birth, folder, hidden, enabled); @override String toString() { @@ -888,24 +751,13 @@ mixin _$AccountUpdate { /// @nodoc abstract mixin class $AccountUpdateCopyWith<$Res> { - factory $AccountUpdateCopyWith( - AccountUpdate value, $Res Function(AccountUpdate) _then) = - _$AccountUpdateCopyWithImpl; + factory $AccountUpdateCopyWith(AccountUpdate value, $Res Function(AccountUpdate) _then) = _$AccountUpdateCopyWithImpl; @useResult - $Res call( - {int coin, - int id, - String? name, - Uint8List? icon, - int? birth, - int folder, - bool? hidden, - bool? enabled}); + $Res call({int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled}); } /// @nodoc -class _$AccountUpdateCopyWithImpl<$Res> - implements $AccountUpdateCopyWith<$Res> { +class _$AccountUpdateCopyWithImpl<$Res> implements $AccountUpdateCopyWith<$Res> { _$AccountUpdateCopyWithImpl(this._self, this._then); final AccountUpdate _self; @@ -1053,16 +905,13 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult maybeWhen( - TResult Function(int coin, int id, String? name, Uint8List? icon, - int? birth, int folder, bool? hidden, bool? enabled)? - $default, { + TResult Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountUpdate() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.icon, - _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); case _: return orElse(); } @@ -1083,15 +932,12 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult when( - TResult Function(int coin, int id, String? name, Uint8List? icon, - int? birth, int folder, bool? hidden, bool? enabled) - $default, + TResult Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled) $default, ) { final _that = this; switch (_that) { case _AccountUpdate(): - return $default(_that.coin, _that.id, _that.name, _that.icon, - _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); } } @@ -1109,15 +955,12 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int coin, int id, String? name, Uint8List? icon, - int? birth, int folder, bool? hidden, bool? enabled)? - $default, + TResult? Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled)? $default, ) { final _that = this; switch (_that) { case _AccountUpdate() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.icon, - _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); case _: return null; } @@ -1127,15 +970,7 @@ extension AccountUpdatePatterns on AccountUpdate { /// @nodoc class _AccountUpdate implements AccountUpdate { - const _AccountUpdate( - {required this.coin, - required this.id, - this.name, - this.icon, - this.birth, - required this.folder, - this.hidden, - this.enabled}); + const _AccountUpdate({required this.coin, required this.id, this.name, this.icon, this.birth, required this.folder, this.hidden, this.enabled}); @override final int coin; @@ -1159,8 +994,7 @@ class _AccountUpdate implements AccountUpdate { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountUpdateCopyWith<_AccountUpdate> get copyWith => - __$AccountUpdateCopyWithImpl<_AccountUpdate>(this, _$identity); + _$AccountUpdateCopyWith<_AccountUpdate> get copyWith => __$AccountUpdateCopyWithImpl<_AccountUpdate>(this, _$identity); @override bool operator ==(Object other) { @@ -1178,16 +1012,7 @@ class _AccountUpdate implements AccountUpdate { } @override - int get hashCode => Object.hash( - runtimeType, - coin, - id, - name, - const DeepCollectionEquality().hash(icon), - birth, - folder, - hidden, - enabled); + int get hashCode => Object.hash(runtimeType, coin, id, name, const DeepCollectionEquality().hash(icon), birth, folder, hidden, enabled); @override String toString() { @@ -1196,27 +1021,15 @@ class _AccountUpdate implements AccountUpdate { } /// @nodoc -abstract mixin class _$AccountUpdateCopyWith<$Res> - implements $AccountUpdateCopyWith<$Res> { - factory _$AccountUpdateCopyWith( - _AccountUpdate value, $Res Function(_AccountUpdate) _then) = - __$AccountUpdateCopyWithImpl; +abstract mixin class _$AccountUpdateCopyWith<$Res> implements $AccountUpdateCopyWith<$Res> { + factory _$AccountUpdateCopyWith(_AccountUpdate value, $Res Function(_AccountUpdate) _then) = __$AccountUpdateCopyWithImpl; @override @useResult - $Res call( - {int coin, - int id, - String? name, - Uint8List? icon, - int? birth, - int folder, - bool? hidden, - bool? enabled}); + $Res call({int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled}); } /// @nodoc -class __$AccountUpdateCopyWithImpl<$Res> - implements _$AccountUpdateCopyWith<$Res> { +class __$AccountUpdateCopyWithImpl<$Res> implements _$AccountUpdateCopyWith<$Res> { __$AccountUpdateCopyWithImpl(this._self, this._then); final _AccountUpdate _self; @@ -1283,8 +1096,7 @@ mixin _$Category { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $CategoryCopyWith get copyWith => - _$CategoryCopyWithImpl(this as Category, _$identity); + $CategoryCopyWith get copyWith => _$CategoryCopyWithImpl(this as Category, _$identity); @override bool operator ==(Object other) { @@ -1293,8 +1105,7 @@ mixin _$Category { other is Category && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - (identical(other.isIncome, isIncome) || - other.isIncome == isIncome)); + (identical(other.isIncome, isIncome) || other.isIncome == isIncome)); } @override @@ -1308,8 +1119,7 @@ mixin _$Category { /// @nodoc abstract mixin class $CategoryCopyWith<$Res> { - factory $CategoryCopyWith(Category value, $Res Function(Category) _then) = - _$CategoryCopyWithImpl; + factory $CategoryCopyWith(Category value, $Res Function(Category) _then) = _$CategoryCopyWithImpl; @useResult $Res call({int id, String name, bool isIncome}); } @@ -1503,8 +1313,7 @@ extension CategoryPatterns on Category { /// @nodoc class _Category implements Category { - const _Category( - {required this.id, required this.name, required this.isIncome}); + const _Category({required this.id, required this.name, required this.isIncome}); @override final int id; @@ -1518,8 +1327,7 @@ class _Category implements Category { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$CategoryCopyWith<_Category> get copyWith => - __$CategoryCopyWithImpl<_Category>(this, _$identity); + _$CategoryCopyWith<_Category> get copyWith => __$CategoryCopyWithImpl<_Category>(this, _$identity); @override bool operator ==(Object other) { @@ -1528,8 +1336,7 @@ class _Category implements Category { other is _Category && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - (identical(other.isIncome, isIncome) || - other.isIncome == isIncome)); + (identical(other.isIncome, isIncome) || other.isIncome == isIncome)); } @override @@ -1542,10 +1349,8 @@ class _Category implements Category { } /// @nodoc -abstract mixin class _$CategoryCopyWith<$Res> - implements $CategoryCopyWith<$Res> { - factory _$CategoryCopyWith(_Category value, $Res Function(_Category) _then) = - __$CategoryCopyWithImpl; +abstract mixin class _$CategoryCopyWith<$Res> implements $CategoryCopyWith<$Res> { + factory _$CategoryCopyWith(_Category value, $Res Function(_Category) _then) = __$CategoryCopyWithImpl; @override @useResult $Res call({int id, String name, bool isIncome}); @@ -1593,8 +1398,7 @@ mixin _$Folder { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FolderCopyWith get copyWith => - _$FolderCopyWithImpl(this as Folder, _$identity); + $FolderCopyWith get copyWith => _$FolderCopyWithImpl(this as Folder, _$identity); @override bool operator ==(Object other) { @@ -1616,8 +1420,7 @@ mixin _$Folder { /// @nodoc abstract mixin class $FolderCopyWith<$Res> { - factory $FolderCopyWith(Folder value, $Res Function(Folder) _then) = - _$FolderCopyWithImpl; + factory $FolderCopyWith(Folder value, $Res Function(Folder) _then) = _$FolderCopyWithImpl; @useResult $Res call({int id, String name}); } @@ -1818,8 +1621,7 @@ class _Folder implements Folder { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FolderCopyWith<_Folder> get copyWith => - __$FolderCopyWithImpl<_Folder>(this, _$identity); + _$FolderCopyWith<_Folder> get copyWith => __$FolderCopyWithImpl<_Folder>(this, _$identity); @override bool operator ==(Object other) { @@ -1841,8 +1643,7 @@ class _Folder implements Folder { /// @nodoc abstract mixin class _$FolderCopyWith<$Res> implements $FolderCopyWith<$Res> { - factory _$FolderCopyWith(_Folder value, $Res Function(_Folder) _then) = - __$FolderCopyWithImpl; + factory _$FolderCopyWith(_Folder value, $Res Function(_Folder) _then) = __$FolderCopyWithImpl; @override @useResult $Res call({int id, String name}); @@ -1886,8 +1687,7 @@ mixin _$FrostParams { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FrostParamsCopyWith get copyWith => - _$FrostParamsCopyWithImpl(this as FrostParams, _$identity); + $FrostParamsCopyWith get copyWith => _$FrostParamsCopyWithImpl(this as FrostParams, _$identity); @override bool operator ==(Object other) { @@ -1910,9 +1710,7 @@ mixin _$FrostParams { /// @nodoc abstract mixin class $FrostParamsCopyWith<$Res> { - factory $FrostParamsCopyWith( - FrostParams value, $Res Function(FrostParams) _then) = - _$FrostParamsCopyWithImpl; + factory $FrostParamsCopyWith(FrostParams value, $Res Function(FrostParams) _then) = _$FrostParamsCopyWithImpl; @useResult $Res call({int id, int n, int t}); } @@ -2120,8 +1918,7 @@ class _FrostParams implements FrostParams { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FrostParamsCopyWith<_FrostParams> get copyWith => - __$FrostParamsCopyWithImpl<_FrostParams>(this, _$identity); + _$FrostParamsCopyWith<_FrostParams> get copyWith => __$FrostParamsCopyWithImpl<_FrostParams>(this, _$identity); @override bool operator ==(Object other) { @@ -2143,11 +1940,8 @@ class _FrostParams implements FrostParams { } /// @nodoc -abstract mixin class _$FrostParamsCopyWith<$Res> - implements $FrostParamsCopyWith<$Res> { - factory _$FrostParamsCopyWith( - _FrostParams value, $Res Function(_FrostParams) _then) = - __$FrostParamsCopyWithImpl; +abstract mixin class _$FrostParamsCopyWith<$Res> implements $FrostParamsCopyWith<$Res> { + factory _$FrostParamsCopyWith(_FrostParams value, $Res Function(_FrostParams) _then) = __$FrostParamsCopyWithImpl; @override @useResult $Res call({int id, int n, int t}); @@ -2203,8 +1997,7 @@ mixin _$Memo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoCopyWith get copyWith => - _$MemoCopyWithImpl(this as Memo, _$identity); + $MemoCopyWith get copyWith => _$MemoCopyWithImpl(this as Memo, _$identity); @override bool operator ==(Object other) { @@ -2220,23 +2013,11 @@ mixin _$Memo { (identical(other.time, time) || other.time == time) && const DeepCollectionEquality().equals(other.memoBytes, memoBytes) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || - other.isUserMemo == isUserMemo)); + (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - idTx, - idNote, - pool, - height, - vout, - time, - const DeepCollectionEquality().hash(memoBytes), - memo, - isUserMemo); + int get hashCode => Object.hash(runtimeType, id, idTx, idNote, pool, height, vout, time, const DeepCollectionEquality().hash(memoBytes), memo, isUserMemo); @override String toString() { @@ -2246,20 +2027,9 @@ mixin _$Memo { /// @nodoc abstract mixin class $MemoCopyWith<$Res> { - factory $MemoCopyWith(Memo value, $Res Function(Memo) _then) = - _$MemoCopyWithImpl; + factory $MemoCopyWith(Memo value, $Res Function(Memo) _then) = _$MemoCopyWithImpl; @useResult - $Res call( - {int id, - int idTx, - int? idNote, - int pool, - int height, - int vout, - int time, - Uint8List memoBytes, - String? memo, - bool isUserMemo}); + $Res call({int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo}); } /// @nodoc @@ -2421,34 +2191,13 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult maybeWhen( - TResult Function( - int id, - int idTx, - int? idNote, - int pool, - int height, - int vout, - int time, - Uint8List memoBytes, - String? memo, - bool isUserMemo)? - $default, { + TResult Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Memo() when $default != null: - return $default( - _that.id, - _that.idTx, - _that.idNote, - _that.pool, - _that.height, - _that.vout, - _that.time, - _that.memoBytes, - _that.memo, - _that.isUserMemo); + return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); case _: return orElse(); } @@ -2469,33 +2218,12 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult when( - TResult Function( - int id, - int idTx, - int? idNote, - int pool, - int height, - int vout, - int time, - Uint8List memoBytes, - String? memo, - bool isUserMemo) - $default, + TResult Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo) $default, ) { final _that = this; switch (_that) { case _Memo(): - return $default( - _that.id, - _that.idTx, - _that.idNote, - _that.pool, - _that.height, - _that.vout, - _that.time, - _that.memoBytes, - _that.memo, - _that.isUserMemo); + return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); } } @@ -2513,33 +2241,12 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int id, - int idTx, - int? idNote, - int pool, - int height, - int vout, - int time, - Uint8List memoBytes, - String? memo, - bool isUserMemo)? - $default, + TResult? Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo)? $default, ) { final _that = this; switch (_that) { case _Memo() when $default != null: - return $default( - _that.id, - _that.idTx, - _that.idNote, - _that.pool, - _that.height, - _that.vout, - _that.time, - _that.memoBytes, - _that.memo, - _that.isUserMemo); + return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); case _: return null; } @@ -2587,8 +2294,7 @@ class _Memo implements Memo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoCopyWith<_Memo> get copyWith => - __$MemoCopyWithImpl<_Memo>(this, _$identity); + _$MemoCopyWith<_Memo> get copyWith => __$MemoCopyWithImpl<_Memo>(this, _$identity); @override bool operator ==(Object other) { @@ -2604,23 +2310,11 @@ class _Memo implements Memo { (identical(other.time, time) || other.time == time) && const DeepCollectionEquality().equals(other.memoBytes, memoBytes) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || - other.isUserMemo == isUserMemo)); + (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - idTx, - idNote, - pool, - height, - vout, - time, - const DeepCollectionEquality().hash(memoBytes), - memo, - isUserMemo); + int get hashCode => Object.hash(runtimeType, id, idTx, idNote, pool, height, vout, time, const DeepCollectionEquality().hash(memoBytes), memo, isUserMemo); @override String toString() { @@ -2630,21 +2324,10 @@ class _Memo implements Memo { /// @nodoc abstract mixin class _$MemoCopyWith<$Res> implements $MemoCopyWith<$Res> { - factory _$MemoCopyWith(_Memo value, $Res Function(_Memo) _then) = - __$MemoCopyWithImpl; + factory _$MemoCopyWith(_Memo value, $Res Function(_Memo) _then) = __$MemoCopyWithImpl; @override @useResult - $Res call( - {int id, - int idTx, - int? idNote, - int pool, - int height, - int vout, - int time, - Uint8List memoBytes, - String? memo, - bool isUserMemo}); + $Res call({int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo}); } /// @nodoc @@ -2735,8 +2418,7 @@ mixin _$NewAccount { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $NewAccountCopyWith get copyWith => - _$NewAccountCopyWithImpl(this as NewAccount, _$identity); + $NewAccountCopyWith get copyWith => _$NewAccountCopyWithImpl(this as NewAccount, _$identity); @override bool operator ==(Object other) { @@ -2747,37 +2429,20 @@ mixin _$NewAccount { (identical(other.name, name) || other.name == name) && (identical(other.restore, restore) || other.restore == restore) && (identical(other.key, key) || other.key == key) && - (identical(other.passphrase, passphrase) || - other.passphrase == passphrase) && - const DeepCollectionEquality() - .equals(other.fingerprint, fingerprint) && + (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && + const DeepCollectionEquality().equals(other.fingerprint, fingerprint) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && (identical(other.pools, pools) || other.pools == pools) && - (identical(other.useInternal, useInternal) || - other.useInternal == useInternal) && - (identical(other.internal, internal) || - other.internal == internal) && + (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && + (identical(other.internal, internal) || other.internal == internal) && (identical(other.ledger, ledger) || other.ledger == ledger)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(icon), - name, - restore, - key, - passphrase, - const DeepCollectionEquality().hash(fingerprint), - aindex, - birth, - folder, - pools, - useInternal, - internal, - ledger); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(icon), name, restore, key, passphrase, + const DeepCollectionEquality().hash(fingerprint), aindex, birth, folder, pools, useInternal, internal, ledger); @override String toString() { @@ -2787,9 +2452,7 @@ mixin _$NewAccount { /// @nodoc abstract mixin class $NewAccountCopyWith<$Res> { - factory $NewAccountCopyWith( - NewAccount value, $Res Function(NewAccount) _then) = - _$NewAccountCopyWithImpl; + factory $NewAccountCopyWith(NewAccount value, $Res Function(NewAccount) _then) = _$NewAccountCopyWithImpl; @useResult $Res call( {Uint8List? icon, @@ -2981,40 +2644,16 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult maybeWhen( - TResult Function( - Uint8List? icon, - String name, - bool restore, - String key, - String? passphrase, - Uint8List? fingerprint, - int aindex, - int? birth, - String folder, - int? pools, - bool useInternal, - bool internal, - bool ledger)? + TResult Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, + int? pools, bool useInternal, bool internal, bool ledger)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _NewAccount() when $default != null: - return $default( - _that.icon, - _that.name, - _that.restore, - _that.key, - _that.passphrase, - _that.fingerprint, - _that.aindex, - _that.birth, - _that.folder, - _that.pools, - _that.useInternal, - _that.internal, - _that.ledger); + return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, + _that.pools, _that.useInternal, _that.internal, _that.ledger); case _: return orElse(); } @@ -3035,39 +2674,15 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult when( - TResult Function( - Uint8List? icon, - String name, - bool restore, - String key, - String? passphrase, - Uint8List? fingerprint, - int aindex, - int? birth, - String folder, - int? pools, - bool useInternal, - bool internal, - bool ledger) + TResult Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, + int? pools, bool useInternal, bool internal, bool ledger) $default, ) { final _that = this; switch (_that) { case _NewAccount(): - return $default( - _that.icon, - _that.name, - _that.restore, - _that.key, - _that.passphrase, - _that.fingerprint, - _that.aindex, - _that.birth, - _that.folder, - _that.pools, - _that.useInternal, - _that.internal, - _that.ledger); + return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, + _that.pools, _that.useInternal, _that.internal, _that.ledger); } } @@ -3085,39 +2700,15 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Uint8List? icon, - String name, - bool restore, - String key, - String? passphrase, - Uint8List? fingerprint, - int aindex, - int? birth, - String folder, - int? pools, - bool useInternal, - bool internal, - bool ledger)? + TResult? Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, + int? pools, bool useInternal, bool internal, bool ledger)? $default, ) { final _that = this; switch (_that) { case _NewAccount() when $default != null: - return $default( - _that.icon, - _that.name, - _that.restore, - _that.key, - _that.passphrase, - _that.fingerprint, - _that.aindex, - _that.birth, - _that.folder, - _that.pools, - _that.useInternal, - _that.internal, - _that.ledger); + return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, + _that.pools, _that.useInternal, _that.internal, _that.ledger); case _: return null; } @@ -3174,8 +2765,7 @@ class _NewAccount implements NewAccount { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$NewAccountCopyWith<_NewAccount> get copyWith => - __$NewAccountCopyWithImpl<_NewAccount>(this, _$identity); + _$NewAccountCopyWith<_NewAccount> get copyWith => __$NewAccountCopyWithImpl<_NewAccount>(this, _$identity); @override bool operator ==(Object other) { @@ -3186,37 +2776,20 @@ class _NewAccount implements NewAccount { (identical(other.name, name) || other.name == name) && (identical(other.restore, restore) || other.restore == restore) && (identical(other.key, key) || other.key == key) && - (identical(other.passphrase, passphrase) || - other.passphrase == passphrase) && - const DeepCollectionEquality() - .equals(other.fingerprint, fingerprint) && + (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && + const DeepCollectionEquality().equals(other.fingerprint, fingerprint) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && (identical(other.pools, pools) || other.pools == pools) && - (identical(other.useInternal, useInternal) || - other.useInternal == useInternal) && - (identical(other.internal, internal) || - other.internal == internal) && + (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && + (identical(other.internal, internal) || other.internal == internal) && (identical(other.ledger, ledger) || other.ledger == ledger)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(icon), - name, - restore, - key, - passphrase, - const DeepCollectionEquality().hash(fingerprint), - aindex, - birth, - folder, - pools, - useInternal, - internal, - ledger); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(icon), name, restore, key, passphrase, + const DeepCollectionEquality().hash(fingerprint), aindex, birth, folder, pools, useInternal, internal, ledger); @override String toString() { @@ -3225,11 +2798,8 @@ class _NewAccount implements NewAccount { } /// @nodoc -abstract mixin class _$NewAccountCopyWith<$Res> - implements $NewAccountCopyWith<$Res> { - factory _$NewAccountCopyWith( - _NewAccount value, $Res Function(_NewAccount) _then) = - __$NewAccountCopyWithImpl; +abstract mixin class _$NewAccountCopyWith<$Res> implements $NewAccountCopyWith<$Res> { + factory _$NewAccountCopyWith(_NewAccount value, $Res Function(_NewAccount) _then) = __$NewAccountCopyWithImpl; @override @useResult $Res call( @@ -3341,16 +2911,14 @@ mixin _$Seed { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SeedCopyWith get copyWith => - _$SeedCopyWithImpl(this as Seed, _$identity); + $SeedCopyWith get copyWith => _$SeedCopyWithImpl(this as Seed, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is Seed && - (identical(other.mnemonic, mnemonic) || - other.mnemonic == mnemonic) && + (identical(other.mnemonic, mnemonic) || other.mnemonic == mnemonic) && (identical(other.phrase, phrase) || other.phrase == phrase) && (identical(other.aindex, aindex) || other.aindex == aindex)); } @@ -3366,8 +2934,7 @@ mixin _$Seed { /// @nodoc abstract mixin class $SeedCopyWith<$Res> { - factory $SeedCopyWith(Seed value, $Res Function(Seed) _then) = - _$SeedCopyWithImpl; + factory $SeedCopyWith(Seed value, $Res Function(Seed) _then) = _$SeedCopyWithImpl; @useResult $Res call({String mnemonic, String phrase, int aindex}); } @@ -3561,8 +3128,7 @@ extension SeedPatterns on Seed { /// @nodoc class _Seed implements Seed { - const _Seed( - {required this.mnemonic, required this.phrase, required this.aindex}); + const _Seed({required this.mnemonic, required this.phrase, required this.aindex}); @override final String mnemonic; @@ -3576,16 +3142,14 @@ class _Seed implements Seed { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SeedCopyWith<_Seed> get copyWith => - __$SeedCopyWithImpl<_Seed>(this, _$identity); + _$SeedCopyWith<_Seed> get copyWith => __$SeedCopyWithImpl<_Seed>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _Seed && - (identical(other.mnemonic, mnemonic) || - other.mnemonic == mnemonic) && + (identical(other.mnemonic, mnemonic) || other.mnemonic == mnemonic) && (identical(other.phrase, phrase) || other.phrase == phrase) && (identical(other.aindex, aindex) || other.aindex == aindex)); } @@ -3601,8 +3165,7 @@ class _Seed implements Seed { /// @nodoc abstract mixin class _$SeedCopyWith<$Res> implements $SeedCopyWith<$Res> { - factory _$SeedCopyWith(_Seed value, $Res Function(_Seed) _then) = - __$SeedCopyWithImpl; + factory _$SeedCopyWith(_Seed value, $Res Function(_Seed) _then) = __$SeedCopyWithImpl; @override @useResult $Res call({String mnemonic, String phrase, int aindex}); @@ -3675,38 +3238,19 @@ mixin _$Tx { (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && (identical(other.tpe, tpe) || other.tpe == tpe) && - (identical(other.category, category) || - other.category == category) && - (identical(other.zsaValue, zsaValue) || - other.zsaValue == zsaValue) && + (identical(other.category, category) || other.category == category) && + (identical(other.zsaValue, zsaValue) || other.zsaValue == zsaValue) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetDisplay, assetDisplay) || - other.assetDisplay == assetDisplay) && + (identical(other.assetDisplay, assetDisplay) || other.assetDisplay == assetDisplay) && (identical(other.price, price) || other.price == price) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || - other.isUserMemo == isUserMemo) && - (identical(other.contactName, contactName) || - other.contactName == contactName)); + (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo) && + (identical(other.contactName, contactName) || other.contactName == contactName)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - const DeepCollectionEquality().hash(txid), - height, - time, - value, - tpe, - category, - zsaValue, - assetId, - assetDisplay, - price, - memo, - isUserMemo, - contactName); + int get hashCode => Object.hash(runtimeType, id, const DeepCollectionEquality().hash(txid), height, time, value, tpe, category, zsaValue, assetId, + assetDisplay, price, memo, isUserMemo, contactName); @override String toString() { @@ -3914,42 +3458,16 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult maybeWhen( - TResult Function( - int id, - Uint8List txid, - int height, - int time, - PlatformInt64 value, - int? tpe, - String? category, - PlatformInt64 zsaValue, - int? assetId, - String assetDisplay, - double? price, - String? memo, - bool isUserMemo, - String? contactName)? + TResult Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, + String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Tx() when $default != null: - return $default( - _that.id, - _that.txid, - _that.height, - _that.time, - _that.value, - _that.tpe, - _that.category, - _that.zsaValue, - _that.assetId, - _that.assetDisplay, - _that.price, - _that.memo, - _that.isUserMemo, - _that.contactName); + return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, + _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); case _: return orElse(); } @@ -3970,41 +3488,15 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult when( - TResult Function( - int id, - Uint8List txid, - int height, - int time, - PlatformInt64 value, - int? tpe, - String? category, - PlatformInt64 zsaValue, - int? assetId, - String assetDisplay, - double? price, - String? memo, - bool isUserMemo, - String? contactName) + TResult Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, + String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName) $default, ) { final _that = this; switch (_that) { case _Tx(): - return $default( - _that.id, - _that.txid, - _that.height, - _that.time, - _that.value, - _that.tpe, - _that.category, - _that.zsaValue, - _that.assetId, - _that.assetDisplay, - _that.price, - _that.memo, - _that.isUserMemo, - _that.contactName); + return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, + _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); } } @@ -4022,41 +3514,15 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int id, - Uint8List txid, - int height, - int time, - PlatformInt64 value, - int? tpe, - String? category, - PlatformInt64 zsaValue, - int? assetId, - String assetDisplay, - double? price, - String? memo, - bool isUserMemo, - String? contactName)? + TResult? Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, + String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName)? $default, ) { final _that = this; switch (_that) { case _Tx() when $default != null: - return $default( - _that.id, - _that.txid, - _that.height, - _that.time, - _that.value, - _that.tpe, - _that.category, - _that.zsaValue, - _that.assetId, - _that.assetDisplay, - _that.price, - _that.memo, - _that.isUserMemo, - _that.contactName); + return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, + _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); case _: return null; } @@ -4129,38 +3595,19 @@ class _Tx implements Tx { (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && (identical(other.tpe, tpe) || other.tpe == tpe) && - (identical(other.category, category) || - other.category == category) && - (identical(other.zsaValue, zsaValue) || - other.zsaValue == zsaValue) && + (identical(other.category, category) || other.category == category) && + (identical(other.zsaValue, zsaValue) || other.zsaValue == zsaValue) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetDisplay, assetDisplay) || - other.assetDisplay == assetDisplay) && + (identical(other.assetDisplay, assetDisplay) || other.assetDisplay == assetDisplay) && (identical(other.price, price) || other.price == price) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || - other.isUserMemo == isUserMemo) && - (identical(other.contactName, contactName) || - other.contactName == contactName)); + (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo) && + (identical(other.contactName, contactName) || other.contactName == contactName)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - const DeepCollectionEquality().hash(txid), - height, - time, - value, - tpe, - category, - zsaValue, - assetId, - assetDisplay, - price, - memo, - isUserMemo, - contactName); + int get hashCode => Object.hash(runtimeType, id, const DeepCollectionEquality().hash(txid), height, time, value, tpe, category, zsaValue, assetId, + assetDisplay, price, memo, isUserMemo, contactName); @override String toString() { diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index 2bffde001..18109a36e 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -11,13 +11,11 @@ part 'coin.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `network`, `open_proxied_stream`, `try_open` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` -Future initDatadir({required String directory}) => - RustLib.instance.api.crateApiCoinInitDatadir(directory: directory); +Future initDatadir({required String directory}) => RustLib.instance.api.crateApiCoinInitDatadir(directory: directory); Future getTorClient() => RustLib.instance.api.crateApiCoinGetTorClient(); -Future closePool({required String dbFilepath}) => - RustLib.instance.api.crateApiCoinClosePool(dbFilepath: dbFilepath); +Future closePool({required String dbFilepath}) => RustLib.instance.api.crateApiCoinClosePool(dbFilepath: dbFilepath); @freezed sealed class Coin with _$Coin { @@ -35,23 +33,16 @@ sealed class Coin with _$Coin { that: this, ); - factory Coin({int? defaultCoin}) => - RustLib.instance.api.crateApiCoinCoinNew(defaultCoin: defaultCoin); + factory Coin({int? defaultCoin}) => RustLib.instance.api.crateApiCoinCoinNew(defaultCoin: defaultCoin); Future openDatabase({required String dbFilepath, String? password}) => - RustLib.instance.api.crateApiCoinCoinOpenDatabase( - that: this, dbFilepath: dbFilepath, password: password); + RustLib.instance.api.crateApiCoinCoinOpenDatabase(that: this, dbFilepath: dbFilepath, password: password); - Future setAccount({required int account}) => RustLib.instance.api - .crateApiCoinCoinSetAccount(that: this, account: account); + Future setAccount({required int account}) => RustLib.instance.api.crateApiCoinCoinSetAccount(that: this, account: account); - Coin setLwd({required int serverType, required String url}) => - RustLib.instance.api - .crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); + Coin setLwd({required int serverType, required String url}) => RustLib.instance.api.crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); - Coin setProxy({required String proxy}) => - RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); + Coin setProxy({required String proxy}) => RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); - Future setUseTor({required bool useTor}) => RustLib.instance.api - .crateApiCoinCoinSetUseTor(that: this, useTor: useTor); + Future setUseTor({required bool useTor}) => RustLib.instance.api.crateApiCoinCoinSetUseTor(that: this, useTor: useTor); } diff --git a/lib/src/rust/api/coin.freezed.dart b/lib/src/rust/api/coin.freezed.dart index a6b9a8d97..b00fd0d2d 100644 --- a/lib/src/rust/api/coin.freezed.dart +++ b/lib/src/rust/api/coin.freezed.dart @@ -26,8 +26,7 @@ mixin _$Coin { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $CoinCopyWith get copyWith => - _$CoinCopyWithImpl(this as Coin, _$identity); + $CoinCopyWith get copyWith => _$CoinCopyWithImpl(this as Coin, _$identity); @override bool operator ==(Object other) { @@ -36,18 +35,15 @@ mixin _$Coin { other is Coin && (identical(other.coin, coin) || other.coin == coin) && (identical(other.account, account) || other.account == account) && - (identical(other.dbFilepath, dbFilepath) || - other.dbFilepath == dbFilepath) && + (identical(other.dbFilepath, dbFilepath) || other.dbFilepath == dbFilepath) && (identical(other.url, url) || other.url == url) && - (identical(other.serverType, serverType) || - other.serverType == serverType) && + (identical(other.serverType, serverType) || other.serverType == serverType) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash( - runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); @override String toString() { @@ -57,17 +53,9 @@ mixin _$Coin { /// @nodoc abstract mixin class $CoinCopyWith<$Res> { - factory $CoinCopyWith(Coin value, $Res Function(Coin) _then) = - _$CoinCopyWithImpl; + factory $CoinCopyWith(Coin value, $Res Function(Coin) _then) = _$CoinCopyWithImpl; @useResult - $Res call( - {int coin, - int account, - String dbFilepath, - String url, - int serverType, - bool useTor, - String proxy}); + $Res call({int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy}); } /// @nodoc @@ -214,16 +202,13 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult maybeWhen({ - TResult Function(int coin, int account, String dbFilepath, String url, - int serverType, bool useTor, String proxy)? - raw, + TResult Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy)? raw, required TResult orElse(), }) { final _that = this; switch (_that) { case _Coin() when raw != null: - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); case _: return orElse(); } @@ -244,15 +229,12 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult when({ - required TResult Function(int coin, int account, String dbFilepath, - String url, int serverType, bool useTor, String proxy) - raw, + required TResult Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy) raw, }) { final _that = this; switch (_that) { case _Coin(): - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); } } @@ -270,15 +252,12 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(int coin, int account, String dbFilepath, String url, - int serverType, bool useTor, String proxy)? - raw, + TResult? Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy)? raw, }) { final _that = this; switch (_that) { case _Coin() when raw != null: - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); case _: return null; } @@ -318,8 +297,7 @@ class _Coin extends Coin { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$CoinCopyWith<_Coin> get copyWith => - __$CoinCopyWithImpl<_Coin>(this, _$identity); + _$CoinCopyWith<_Coin> get copyWith => __$CoinCopyWithImpl<_Coin>(this, _$identity); @override bool operator ==(Object other) { @@ -328,18 +306,15 @@ class _Coin extends Coin { other is _Coin && (identical(other.coin, coin) || other.coin == coin) && (identical(other.account, account) || other.account == account) && - (identical(other.dbFilepath, dbFilepath) || - other.dbFilepath == dbFilepath) && + (identical(other.dbFilepath, dbFilepath) || other.dbFilepath == dbFilepath) && (identical(other.url, url) || other.url == url) && - (identical(other.serverType, serverType) || - other.serverType == serverType) && + (identical(other.serverType, serverType) || other.serverType == serverType) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash( - runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); @override String toString() { @@ -349,18 +324,10 @@ class _Coin extends Coin { /// @nodoc abstract mixin class _$CoinCopyWith<$Res> implements $CoinCopyWith<$Res> { - factory _$CoinCopyWith(_Coin value, $Res Function(_Coin) _then) = - __$CoinCopyWithImpl; + factory _$CoinCopyWith(_Coin value, $Res Function(_Coin) _then) = __$CoinCopyWithImpl; @override @useResult - $Res call( - {int coin, - int account, - String dbFilepath, - String url, - int serverType, - bool useTor, - String proxy}); + $Res call({int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy}); } /// @nodoc diff --git a/lib/src/rust/api/contacts.dart b/lib/src/rust/api/contacts.dart index 97c03c9dc..1ae2222ad 100644 --- a/lib/src/rust/api/contacts.dart +++ b/lib/src/rust/api/contacts.dart @@ -11,46 +11,28 @@ part 'contacts.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `from` -Future> listContacts({required Coin c}) => - RustLib.instance.api.crateApiContactsListContacts(c: c); +Future> listContacts({required Coin c}) => RustLib.instance.api.crateApiContactsListContacts(c: c); -Future createContact( - {required String name, - required List addresses, - required String notes, - required Coin c}) => - RustLib.instance.api.crateApiContactsCreateContact( - name: name, addresses: addresses, notes: notes, c: c); +Future createContact({required String name, required List addresses, required String notes, required Coin c}) => + RustLib.instance.api.crateApiContactsCreateContact(name: name, addresses: addresses, notes: notes, c: c); -Future updateContact( - {required int id, - String? name, - List? addresses, - String? notes, - required Coin c}) => - RustLib.instance.api.crateApiContactsUpdateContact( - id: id, name: name, addresses: addresses, notes: notes, c: c); +Future updateContact({required int id, String? name, List? addresses, String? notes, required Coin c}) => + RustLib.instance.api.crateApiContactsUpdateContact(id: id, name: name, addresses: addresses, notes: notes, c: c); -Future deleteContacts({required List ids, required Coin c}) => - RustLib.instance.api.crateApiContactsDeleteContacts(ids: ids, c: c); +Future deleteContacts({required List ids, required Coin c}) => RustLib.instance.api.crateApiContactsDeleteContacts(ids: ids, c: c); /// Find contacts whose stored addresses match the given address. /// /// The input address can be either a unified address (which will be expanded /// to its constituent receivers) or a single-pool receiver address. /// Returns matching contacts with the original address that produced the match. -Future> findContactsForAddress( - {required String address, required Coin c}) => - RustLib.instance.api - .crateApiContactsFindContactsForAddress(address: address, c: c); +Future> findContactsForAddress({required String address, required Coin c}) => + RustLib.instance.api.crateApiContactsFindContactsForAddress(address: address, c: c); -Future exportContactsVcard({required Coin c}) => - RustLib.instance.api.crateApiContactsExportContactsVcard(c: c); +Future exportContactsVcard({required Coin c}) => RustLib.instance.api.crateApiContactsExportContactsVcard(c: c); -Future> importContactsVcard( - {required String vcardData, required Coin c}) => - RustLib.instance.api - .crateApiContactsImportContactsVcard(vcardData: vcardData, c: c); +Future> importContactsVcard({required String vcardData, required Coin c}) => + RustLib.instance.api.crateApiContactsImportContactsVcard(vcardData: vcardData, c: c); @freezed sealed class Contact with _$Contact { diff --git a/lib/src/rust/api/contacts.freezed.dart b/lib/src/rust/api/contacts.freezed.dart index 757611b2d..0c4a60023 100644 --- a/lib/src/rust/api/contacts.freezed.dart +++ b/lib/src/rust/api/contacts.freezed.dart @@ -23,8 +23,7 @@ mixin _$Contact { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ContactCopyWith get copyWith => - _$ContactCopyWithImpl(this as Contact, _$identity); + $ContactCopyWith get copyWith => _$ContactCopyWithImpl(this as Contact, _$identity); @override bool operator ==(Object other) { @@ -38,8 +37,7 @@ mixin _$Contact { } @override - int get hashCode => Object.hash(runtimeType, id, name, - const DeepCollectionEquality().hash(addresses), notes); + int get hashCode => Object.hash(runtimeType, id, name, const DeepCollectionEquality().hash(addresses), notes); @override String toString() { @@ -49,8 +47,7 @@ mixin _$Contact { /// @nodoc abstract mixin class $ContactCopyWith<$Res> { - factory $ContactCopyWith(Contact value, $Res Function(Contact) _then) = - _$ContactCopyWithImpl; + factory $ContactCopyWith(Contact value, $Res Function(Contact) _then) = _$ContactCopyWithImpl; @useResult $Res call({int id, String name, List addresses, String notes}); } @@ -184,8 +181,7 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult maybeWhen( - TResult Function(int id, String name, List addresses, String notes)? - $default, { + TResult Function(int id, String name, List addresses, String notes)? $default, { required TResult orElse(), }) { final _that = this; @@ -212,8 +208,7 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult when( - TResult Function(int id, String name, List addresses, String notes) - $default, + TResult Function(int id, String name, List addresses, String notes) $default, ) { final _that = this; switch (_that) { @@ -236,9 +231,7 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int id, String name, List addresses, String notes)? - $default, + TResult? Function(int id, String name, List addresses, String notes)? $default, ) { final _that = this; switch (_that) { @@ -253,12 +246,7 @@ extension ContactPatterns on Contact { /// @nodoc class _Contact implements Contact { - const _Contact( - {required this.id, - required this.name, - required final List addresses, - required this.notes}) - : _addresses = addresses; + const _Contact({required this.id, required this.name, required final List addresses, required this.notes}) : _addresses = addresses; @override final int id; @@ -280,8 +268,7 @@ class _Contact implements Contact { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ContactCopyWith<_Contact> get copyWith => - __$ContactCopyWithImpl<_Contact>(this, _$identity); + _$ContactCopyWith<_Contact> get copyWith => __$ContactCopyWithImpl<_Contact>(this, _$identity); @override bool operator ==(Object other) { @@ -290,14 +277,12 @@ class _Contact implements Contact { other is _Contact && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - const DeepCollectionEquality() - .equals(other._addresses, _addresses) && + const DeepCollectionEquality().equals(other._addresses, _addresses) && (identical(other.notes, notes) || other.notes == notes)); } @override - int get hashCode => Object.hash(runtimeType, id, name, - const DeepCollectionEquality().hash(_addresses), notes); + int get hashCode => Object.hash(runtimeType, id, name, const DeepCollectionEquality().hash(_addresses), notes); @override String toString() { @@ -307,8 +292,7 @@ class _Contact implements Contact { /// @nodoc abstract mixin class _$ContactCopyWith<$Res> implements $ContactCopyWith<$Res> { - factory _$ContactCopyWith(_Contact value, $Res Function(_Contact) _then) = - __$ContactCopyWithImpl; + factory _$ContactCopyWith(_Contact value, $Res Function(_Contact) _then) = __$ContactCopyWithImpl; @override @useResult $Res call({int id, String name, List addresses, String notes}); @@ -361,9 +345,7 @@ mixin _$ContactMatch { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ContactMatchCopyWith get copyWith => - _$ContactMatchCopyWithImpl( - this as ContactMatch, _$identity); + $ContactMatchCopyWith get copyWith => _$ContactMatchCopyWithImpl(this as ContactMatch, _$identity); @override bool operator ==(Object other) { @@ -371,8 +353,7 @@ mixin _$ContactMatch { (other.runtimeType == runtimeType && other is ContactMatch && (identical(other.contact, contact) || other.contact == contact) && - (identical(other.matchedAddress, matchedAddress) || - other.matchedAddress == matchedAddress)); + (identical(other.matchedAddress, matchedAddress) || other.matchedAddress == matchedAddress)); } @override @@ -386,9 +367,7 @@ mixin _$ContactMatch { /// @nodoc abstract mixin class $ContactMatchCopyWith<$Res> { - factory $ContactMatchCopyWith( - ContactMatch value, $Res Function(ContactMatch) _then) = - _$ContactMatchCopyWithImpl; + factory $ContactMatchCopyWith(ContactMatch value, $Res Function(ContactMatch) _then) = _$ContactMatchCopyWithImpl; @useResult $Res call({Contact contact, String matchedAddress}); @@ -601,8 +580,7 @@ class _ContactMatch implements ContactMatch { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ContactMatchCopyWith<_ContactMatch> get copyWith => - __$ContactMatchCopyWithImpl<_ContactMatch>(this, _$identity); + _$ContactMatchCopyWith<_ContactMatch> get copyWith => __$ContactMatchCopyWithImpl<_ContactMatch>(this, _$identity); @override bool operator ==(Object other) { @@ -610,8 +588,7 @@ class _ContactMatch implements ContactMatch { (other.runtimeType == runtimeType && other is _ContactMatch && (identical(other.contact, contact) || other.contact == contact) && - (identical(other.matchedAddress, matchedAddress) || - other.matchedAddress == matchedAddress)); + (identical(other.matchedAddress, matchedAddress) || other.matchedAddress == matchedAddress)); } @override @@ -624,11 +601,8 @@ class _ContactMatch implements ContactMatch { } /// @nodoc -abstract mixin class _$ContactMatchCopyWith<$Res> - implements $ContactMatchCopyWith<$Res> { - factory _$ContactMatchCopyWith( - _ContactMatch value, $Res Function(_ContactMatch) _then) = - __$ContactMatchCopyWithImpl; +abstract mixin class _$ContactMatchCopyWith<$Res> implements $ContactMatchCopyWith<$Res> { + factory _$ContactMatchCopyWith(_ContactMatch value, $Res Function(_ContactMatch) _then) = __$ContactMatchCopyWithImpl; @override @useResult $Res call({Contact contact, String matchedAddress}); @@ -638,8 +612,7 @@ abstract mixin class _$ContactMatchCopyWith<$Res> } /// @nodoc -class __$ContactMatchCopyWithImpl<$Res> - implements _$ContactMatchCopyWith<$Res> { +class __$ContactMatchCopyWithImpl<$Res> implements _$ContactMatchCopyWith<$Res> { __$ContactMatchCopyWithImpl(this._self, this._then); final _ContactMatch _self; diff --git a/lib/src/rust/api/db.dart b/lib/src/rust/api/db.dart index 77746c5fd..64cef0cfe 100644 --- a/lib/src/rust/api/db.dart +++ b/lib/src/rust/api/db.dart @@ -7,29 +7,16 @@ import '../frb_generated.dart'; import 'coin.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -Future> listDbAccounts({required String dbFilepath}) => - RustLib.instance.api.crateApiDbListDbAccounts(dbFilepath: dbFilepath); - -Future changeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}) => - RustLib.instance.api.crateApiDbChangeDbPassword( - dbFilepath: dbFilepath, - tmpDir: tmpDir, - oldPassword: oldPassword, - newPassword: newPassword); - -Future getProp({required String key, required Coin c}) => - RustLib.instance.api.crateApiDbGetProp(key: key, c: c); - -Future putProp( - {required String key, required String value, required Coin c}) => - RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); - -Future> listDbNames({required String dir}) => - RustLib.instance.api.crateApiDbListDbNames(dir: dir); +Future> listDbAccounts({required String dbFilepath}) => RustLib.instance.api.crateApiDbListDbAccounts(dbFilepath: dbFilepath); + +Future changeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}) => + RustLib.instance.api.crateApiDbChangeDbPassword(dbFilepath: dbFilepath, tmpDir: tmpDir, oldPassword: oldPassword, newPassword: newPassword); + +Future getProp({required String key, required Coin c}) => RustLib.instance.api.crateApiDbGetProp(key: key, c: c); + +Future putProp({required String key, required String value, required Coin c}) => RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); + +Future> listDbNames({required String dir}) => RustLib.instance.api.crateApiDbListDbNames(dir: dir); class DbAccountPreview { final int id; @@ -45,9 +32,5 @@ class DbAccountPreview { @override bool operator ==(Object other) => - identical(this, other) || - other is DbAccountPreview && - runtimeType == other.runtimeType && - id == other.id && - name == other.name; + identical(this, other) || other is DbAccountPreview && runtimeType == other.runtimeType && id == other.id && name == other.name; } diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index a4ed66a81..c863adb20 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -15,58 +15,32 @@ part 'frost.freezed.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DKGParams` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt` -Future setDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}) => - RustLib.instance.api.crateApiFrostSetDkgParams( - name: name, id: id, n: n, t: t, fundingAccount: fundingAccount, c: c); - -Future hasDkgParams({required Coin c}) => - RustLib.instance.api.crateApiFrostHasDkgParams(c: c); - -Future initDkg({required Coin c}) => - RustLib.instance.api.crateApiFrostInitDkg(c: c); - -Future hasDkgAddresses({required Coin c}) => - RustLib.instance.api.crateApiFrostHasDkgAddresses(c: c); - -Stream doDkg({required Coin c}) => - RustLib.instance.api.crateApiFrostDoDkg(c: c); - -Future> getDkgAddresses({required Coin c}) => - RustLib.instance.api.crateApiFrostGetDkgAddresses(c: c); - -Future setDkgAddress( - {required int id, required String address, required Coin c}) => - RustLib.instance.api - .crateApiFrostSetDkgAddress(id: id, address: address, c: c); - -Future cancelDkg({required Coin c}) => - RustLib.instance.api.crateApiFrostCancelDkg(c: c); - -Future resetSign({required Coin c}) => - RustLib.instance.api.crateApiFrostResetSign(c: c); - -Future initSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}) => - RustLib.instance.api.crateApiFrostInitSign( - coordinator: coordinator, - fundingAccount: fundingAccount, - pczt: pczt, - c: c); - -Future isSigningInProgress({required Coin c}) => - RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); - -Stream doSign({required Coin c}) => - RustLib.instance.api.crateApiFrostDoSign(c: c); +Future setDkgParams({required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}) => + RustLib.instance.api.crateApiFrostSetDkgParams(name: name, id: id, n: n, t: t, fundingAccount: fundingAccount, c: c); + +Future hasDkgParams({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgParams(c: c); + +Future initDkg({required Coin c}) => RustLib.instance.api.crateApiFrostInitDkg(c: c); + +Future hasDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgAddresses(c: c); + +Stream doDkg({required Coin c}) => RustLib.instance.api.crateApiFrostDoDkg(c: c); + +Future> getDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostGetDkgAddresses(c: c); + +Future setDkgAddress({required int id, required String address, required Coin c}) => + RustLib.instance.api.crateApiFrostSetDkgAddress(id: id, address: address, c: c); + +Future cancelDkg({required Coin c}) => RustLib.instance.api.crateApiFrostCancelDkg(c: c); + +Future resetSign({required Coin c}) => RustLib.instance.api.crateApiFrostResetSign(c: c); + +Future initSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}) => + RustLib.instance.api.crateApiFrostInitSign(coordinator: coordinator, fundingAccount: fundingAccount, pczt: pczt, c: c); + +Future isSigningInProgress({required Coin c}) => RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); + +Stream doSign({required Coin c}) => RustLib.instance.api.crateApiFrostDoSign(c: c); @freezed sealed class DKGStatus with _$DKGStatus { @@ -94,32 +68,22 @@ sealed class FrostSignParams with _$FrostSignParams { required int coordinator, required int fundingAccount, }) = _FrostSignParams; - static Future default_() => - RustLib.instance.api.crateApiFrostFrostSignParamsDefault(); + static Future default_() => RustLib.instance.api.crateApiFrostFrostSignParamsDefault(); } @freezed sealed class SigningStatus with _$SigningStatus { const SigningStatus._(); - const factory SigningStatus.sendingCommitment() = - SigningStatus_SendingCommitment; - const factory SigningStatus.waitingForCommitments() = - SigningStatus_WaitingForCommitments; - const factory SigningStatus.sendingSigningPackage() = - SigningStatus_SendingSigningPackage; - const factory SigningStatus.waitingForSigningPackage() = - SigningStatus_WaitingForSigningPackage; - const factory SigningStatus.sendingSignatureShare() = - SigningStatus_SendingSignatureShare; - const factory SigningStatus.signingCompleted() = - SigningStatus_SigningCompleted; - const factory SigningStatus.waitingForSignatureShares() = - SigningStatus_WaitingForSignatureShares; - const factory SigningStatus.preparingTransaction() = - SigningStatus_PreparingTransaction; - const factory SigningStatus.sendingTransaction() = - SigningStatus_SendingTransaction; + const factory SigningStatus.sendingCommitment() = SigningStatus_SendingCommitment; + const factory SigningStatus.waitingForCommitments() = SigningStatus_WaitingForCommitments; + const factory SigningStatus.sendingSigningPackage() = SigningStatus_SendingSigningPackage; + const factory SigningStatus.waitingForSigningPackage() = SigningStatus_WaitingForSigningPackage; + const factory SigningStatus.sendingSignatureShare() = SigningStatus_SendingSignatureShare; + const factory SigningStatus.signingCompleted() = SigningStatus_SigningCompleted; + const factory SigningStatus.waitingForSignatureShares() = SigningStatus_WaitingForSignatureShares; + const factory SigningStatus.preparingTransaction() = SigningStatus_PreparingTransaction; + const factory SigningStatus.sendingTransaction() = SigningStatus_SendingTransaction; const factory SigningStatus.transactionSent( String field0, ) = SigningStatus_TransactionSent; diff --git a/lib/src/rust/api/frost.freezed.dart b/lib/src/rust/api/frost.freezed.dart index 9a9a2e016..2e3c255ad 100644 --- a/lib/src/rust/api/frost.freezed.dart +++ b/lib/src/rust/api/frost.freezed.dart @@ -16,8 +16,7 @@ T _$identity(T value) => value; mixin _$DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus); } @override @@ -100,11 +99,9 @@ extension DKGStatusPatterns on DKGStatus { TResult map({ required TResult Function(DKGStatus_WaitParams value) waitParams, required TResult Function(DKGStatus_WaitAddresses value) waitAddresses, - required TResult Function(DKGStatus_PublishRound1Pkg value) - publishRound1Pkg, + required TResult Function(DKGStatus_PublishRound1Pkg value) publishRound1Pkg, required TResult Function(DKGStatus_WaitRound1Pkg value) waitRound1Pkg, - required TResult Function(DKGStatus_PublishRound2Pkg value) - publishRound2Pkg, + required TResult Function(DKGStatus_PublishRound2Pkg value) publishRound2Pkg, required TResult Function(DKGStatus_WaitRound2Pkg value) waitRound2Pkg, required TResult Function(DKGStatus_Finalize value) finalize, required TResult Function(DKGStatus_SharedAddress value) sharedAddress, @@ -322,8 +319,7 @@ class DKGStatus_WaitParams extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_WaitParams); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitParams); } @override @@ -353,21 +349,16 @@ class DKGStatus_WaitAddresses extends DKGStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $DKGStatus_WaitAddressesCopyWith get copyWith => - _$DKGStatus_WaitAddressesCopyWithImpl( - this, _$identity); + $DKGStatus_WaitAddressesCopyWith get copyWith => _$DKGStatus_WaitAddressesCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is DKGStatus_WaitAddresses && - const DeepCollectionEquality().equals(other._field0, _field0)); + (other.runtimeType == runtimeType && other is DKGStatus_WaitAddresses && const DeepCollectionEquality().equals(other._field0, _field0)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0)); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0)); @override String toString() { @@ -376,18 +367,14 @@ class DKGStatus_WaitAddresses extends DKGStatus { } /// @nodoc -abstract mixin class $DKGStatus_WaitAddressesCopyWith<$Res> - implements $DKGStatusCopyWith<$Res> { - factory $DKGStatus_WaitAddressesCopyWith(DKGStatus_WaitAddresses value, - $Res Function(DKGStatus_WaitAddresses) _then) = - _$DKGStatus_WaitAddressesCopyWithImpl; +abstract mixin class $DKGStatus_WaitAddressesCopyWith<$Res> implements $DKGStatusCopyWith<$Res> { + factory $DKGStatus_WaitAddressesCopyWith(DKGStatus_WaitAddresses value, $Res Function(DKGStatus_WaitAddresses) _then) = _$DKGStatus_WaitAddressesCopyWithImpl; @useResult $Res call({List field0}); } /// @nodoc -class _$DKGStatus_WaitAddressesCopyWithImpl<$Res> - implements $DKGStatus_WaitAddressesCopyWith<$Res> { +class _$DKGStatus_WaitAddressesCopyWithImpl<$Res> implements $DKGStatus_WaitAddressesCopyWith<$Res> { _$DKGStatus_WaitAddressesCopyWithImpl(this._self, this._then); final DKGStatus_WaitAddresses _self; @@ -415,9 +402,7 @@ class DKGStatus_PublishRound1Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is DKGStatus_PublishRound1Pkg); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_PublishRound1Pkg); } @override @@ -436,8 +421,7 @@ class DKGStatus_WaitRound1Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_WaitRound1Pkg); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitRound1Pkg); } @override @@ -456,9 +440,7 @@ class DKGStatus_PublishRound2Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is DKGStatus_PublishRound2Pkg); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_PublishRound2Pkg); } @override @@ -477,8 +459,7 @@ class DKGStatus_WaitRound2Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_WaitRound2Pkg); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitRound2Pkg); } @override @@ -497,8 +478,7 @@ class DKGStatus_Finalize extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_Finalize); + return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_Finalize); } @override @@ -521,16 +501,12 @@ class DKGStatus_SharedAddress extends DKGStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $DKGStatus_SharedAddressCopyWith get copyWith => - _$DKGStatus_SharedAddressCopyWithImpl( - this, _$identity); + $DKGStatus_SharedAddressCopyWith get copyWith => _$DKGStatus_SharedAddressCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is DKGStatus_SharedAddress && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is DKGStatus_SharedAddress && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -543,18 +519,14 @@ class DKGStatus_SharedAddress extends DKGStatus { } /// @nodoc -abstract mixin class $DKGStatus_SharedAddressCopyWith<$Res> - implements $DKGStatusCopyWith<$Res> { - factory $DKGStatus_SharedAddressCopyWith(DKGStatus_SharedAddress value, - $Res Function(DKGStatus_SharedAddress) _then) = - _$DKGStatus_SharedAddressCopyWithImpl; +abstract mixin class $DKGStatus_SharedAddressCopyWith<$Res> implements $DKGStatusCopyWith<$Res> { + factory $DKGStatus_SharedAddressCopyWith(DKGStatus_SharedAddress value, $Res Function(DKGStatus_SharedAddress) _then) = _$DKGStatus_SharedAddressCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$DKGStatus_SharedAddressCopyWithImpl<$Res> - implements $DKGStatus_SharedAddressCopyWith<$Res> { +class _$DKGStatus_SharedAddressCopyWithImpl<$Res> implements $DKGStatus_SharedAddressCopyWith<$Res> { _$DKGStatus_SharedAddressCopyWithImpl(this._self, this._then); final DKGStatus_SharedAddress _self; @@ -585,9 +557,7 @@ mixin _$FrostSignParams { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FrostSignParamsCopyWith get copyWith => - _$FrostSignParamsCopyWithImpl( - this as FrostSignParams, _$identity); + $FrostSignParamsCopyWith get copyWith => _$FrostSignParamsCopyWithImpl(this as FrostSignParams, _$identity); @override bool operator ==(Object other) { @@ -595,15 +565,12 @@ mixin _$FrostSignParams { (other.runtimeType == runtimeType && other is FrostSignParams && (identical(other.account, account) || other.account == account) && - (identical(other.coordinator, coordinator) || - other.coordinator == coordinator) && - (identical(other.fundingAccount, fundingAccount) || - other.fundingAccount == fundingAccount)); + (identical(other.coordinator, coordinator) || other.coordinator == coordinator) && + (identical(other.fundingAccount, fundingAccount) || other.fundingAccount == fundingAccount)); } @override - int get hashCode => - Object.hash(runtimeType, account, coordinator, fundingAccount); + int get hashCode => Object.hash(runtimeType, account, coordinator, fundingAccount); @override String toString() { @@ -613,16 +580,13 @@ mixin _$FrostSignParams { /// @nodoc abstract mixin class $FrostSignParamsCopyWith<$Res> { - factory $FrostSignParamsCopyWith( - FrostSignParams value, $Res Function(FrostSignParams) _then) = - _$FrostSignParamsCopyWithImpl; + factory $FrostSignParamsCopyWith(FrostSignParams value, $Res Function(FrostSignParams) _then) = _$FrostSignParamsCopyWithImpl; @useResult $Res call({int account, int coordinator, int fundingAccount}); } /// @nodoc -class _$FrostSignParamsCopyWithImpl<$Res> - implements $FrostSignParamsCopyWith<$Res> { +class _$FrostSignParamsCopyWithImpl<$Res> implements $FrostSignParamsCopyWith<$Res> { _$FrostSignParamsCopyWithImpl(this._self, this._then); final FrostSignParams _self; @@ -745,8 +709,7 @@ extension FrostSignParamsPatterns on FrostSignParams { @optionalTypeArgs TResult maybeWhen( - TResult Function(int account, int coordinator, int fundingAccount)? - $default, { + TResult Function(int account, int coordinator, int fundingAccount)? $default, { required TResult orElse(), }) { final _that = this; @@ -796,8 +759,7 @@ extension FrostSignParamsPatterns on FrostSignParams { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int account, int coordinator, int fundingAccount)? - $default, + TResult? Function(int account, int coordinator, int fundingAccount)? $default, ) { final _that = this; switch (_that) { @@ -812,11 +774,7 @@ extension FrostSignParamsPatterns on FrostSignParams { /// @nodoc class _FrostSignParams extends FrostSignParams { - const _FrostSignParams( - {required this.account, - required this.coordinator, - required this.fundingAccount}) - : super._(); + const _FrostSignParams({required this.account, required this.coordinator, required this.fundingAccount}) : super._(); @override final int account; @@ -830,8 +788,7 @@ class _FrostSignParams extends FrostSignParams { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FrostSignParamsCopyWith<_FrostSignParams> get copyWith => - __$FrostSignParamsCopyWithImpl<_FrostSignParams>(this, _$identity); + _$FrostSignParamsCopyWith<_FrostSignParams> get copyWith => __$FrostSignParamsCopyWithImpl<_FrostSignParams>(this, _$identity); @override bool operator ==(Object other) { @@ -839,15 +796,12 @@ class _FrostSignParams extends FrostSignParams { (other.runtimeType == runtimeType && other is _FrostSignParams && (identical(other.account, account) || other.account == account) && - (identical(other.coordinator, coordinator) || - other.coordinator == coordinator) && - (identical(other.fundingAccount, fundingAccount) || - other.fundingAccount == fundingAccount)); + (identical(other.coordinator, coordinator) || other.coordinator == coordinator) && + (identical(other.fundingAccount, fundingAccount) || other.fundingAccount == fundingAccount)); } @override - int get hashCode => - Object.hash(runtimeType, account, coordinator, fundingAccount); + int get hashCode => Object.hash(runtimeType, account, coordinator, fundingAccount); @override String toString() { @@ -856,19 +810,15 @@ class _FrostSignParams extends FrostSignParams { } /// @nodoc -abstract mixin class _$FrostSignParamsCopyWith<$Res> - implements $FrostSignParamsCopyWith<$Res> { - factory _$FrostSignParamsCopyWith( - _FrostSignParams value, $Res Function(_FrostSignParams) _then) = - __$FrostSignParamsCopyWithImpl; +abstract mixin class _$FrostSignParamsCopyWith<$Res> implements $FrostSignParamsCopyWith<$Res> { + factory _$FrostSignParamsCopyWith(_FrostSignParams value, $Res Function(_FrostSignParams) _then) = __$FrostSignParamsCopyWithImpl; @override @useResult $Res call({int account, int coordinator, int fundingAccount}); } /// @nodoc -class __$FrostSignParamsCopyWithImpl<$Res> - implements _$FrostSignParamsCopyWith<$Res> { +class __$FrostSignParamsCopyWithImpl<$Res> implements _$FrostSignParamsCopyWith<$Res> { __$FrostSignParamsCopyWithImpl(this._self, this._then); final _FrostSignParams _self; @@ -904,8 +854,7 @@ class __$FrostSignParamsCopyWithImpl<$Res> mixin _$SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is SigningStatus); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus); } @override @@ -939,21 +888,14 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult maybeMap({ TResult Function(SigningStatus_SendingCommitment value)? sendingCommitment, - TResult Function(SigningStatus_WaitingForCommitments value)? - waitingForCommitments, - TResult Function(SigningStatus_SendingSigningPackage value)? - sendingSigningPackage, - TResult Function(SigningStatus_WaitingForSigningPackage value)? - waitingForSigningPackage, - TResult Function(SigningStatus_SendingSignatureShare value)? - sendingSignatureShare, + TResult Function(SigningStatus_WaitingForCommitments value)? waitingForCommitments, + TResult Function(SigningStatus_SendingSigningPackage value)? sendingSigningPackage, + TResult Function(SigningStatus_WaitingForSigningPackage value)? waitingForSigningPackage, + TResult Function(SigningStatus_SendingSignatureShare value)? sendingSignatureShare, TResult Function(SigningStatus_SigningCompleted value)? signingCompleted, - TResult Function(SigningStatus_WaitingForSignatureShares value)? - waitingForSignatureShares, - TResult Function(SigningStatus_PreparingTransaction value)? - preparingTransaction, - TResult Function(SigningStatus_SendingTransaction value)? - sendingTransaction, + TResult Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, + TResult Function(SigningStatus_PreparingTransaction value)? preparingTransaction, + TResult Function(SigningStatus_SendingTransaction value)? sendingTransaction, TResult Function(SigningStatus_TransactionSent value)? transactionSent, required TResult orElse(), }) { @@ -961,25 +903,19 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(_that); - case SigningStatus_WaitingForCommitments() - when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: return waitingForCommitments(_that); - case SigningStatus_SendingSigningPackage() - when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: return sendingSigningPackage(_that); - case SigningStatus_WaitingForSigningPackage() - when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: return waitingForSigningPackage(_that); - case SigningStatus_SendingSignatureShare() - when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: return sendingSignatureShare(_that); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(_that); - case SigningStatus_WaitingForSignatureShares() - when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(_that); - case SigningStatus_PreparingTransaction() - when preparingTransaction != null: + case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(_that); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(_that); @@ -1005,26 +941,16 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult map({ - required TResult Function(SigningStatus_SendingCommitment value) - sendingCommitment, - required TResult Function(SigningStatus_WaitingForCommitments value) - waitingForCommitments, - required TResult Function(SigningStatus_SendingSigningPackage value) - sendingSigningPackage, - required TResult Function(SigningStatus_WaitingForSigningPackage value) - waitingForSigningPackage, - required TResult Function(SigningStatus_SendingSignatureShare value) - sendingSignatureShare, - required TResult Function(SigningStatus_SigningCompleted value) - signingCompleted, - required TResult Function(SigningStatus_WaitingForSignatureShares value) - waitingForSignatureShares, - required TResult Function(SigningStatus_PreparingTransaction value) - preparingTransaction, - required TResult Function(SigningStatus_SendingTransaction value) - sendingTransaction, - required TResult Function(SigningStatus_TransactionSent value) - transactionSent, + required TResult Function(SigningStatus_SendingCommitment value) sendingCommitment, + required TResult Function(SigningStatus_WaitingForCommitments value) waitingForCommitments, + required TResult Function(SigningStatus_SendingSigningPackage value) sendingSigningPackage, + required TResult Function(SigningStatus_WaitingForSigningPackage value) waitingForSigningPackage, + required TResult Function(SigningStatus_SendingSignatureShare value) sendingSignatureShare, + required TResult Function(SigningStatus_SigningCompleted value) signingCompleted, + required TResult Function(SigningStatus_WaitingForSignatureShares value) waitingForSignatureShares, + required TResult Function(SigningStatus_PreparingTransaction value) preparingTransaction, + required TResult Function(SigningStatus_SendingTransaction value) sendingTransaction, + required TResult Function(SigningStatus_TransactionSent value) transactionSent, }) { final _that = this; switch (_that) { @@ -1066,46 +992,33 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult? mapOrNull({ TResult? Function(SigningStatus_SendingCommitment value)? sendingCommitment, - TResult? Function(SigningStatus_WaitingForCommitments value)? - waitingForCommitments, - TResult? Function(SigningStatus_SendingSigningPackage value)? - sendingSigningPackage, - TResult? Function(SigningStatus_WaitingForSigningPackage value)? - waitingForSigningPackage, - TResult? Function(SigningStatus_SendingSignatureShare value)? - sendingSignatureShare, + TResult? Function(SigningStatus_WaitingForCommitments value)? waitingForCommitments, + TResult? Function(SigningStatus_SendingSigningPackage value)? sendingSigningPackage, + TResult? Function(SigningStatus_WaitingForSigningPackage value)? waitingForSigningPackage, + TResult? Function(SigningStatus_SendingSignatureShare value)? sendingSignatureShare, TResult? Function(SigningStatus_SigningCompleted value)? signingCompleted, - TResult? Function(SigningStatus_WaitingForSignatureShares value)? - waitingForSignatureShares, - TResult? Function(SigningStatus_PreparingTransaction value)? - preparingTransaction, - TResult? Function(SigningStatus_SendingTransaction value)? - sendingTransaction, + TResult? Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, + TResult? Function(SigningStatus_PreparingTransaction value)? preparingTransaction, + TResult? Function(SigningStatus_SendingTransaction value)? sendingTransaction, TResult? Function(SigningStatus_TransactionSent value)? transactionSent, }) { final _that = this; switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(_that); - case SigningStatus_WaitingForCommitments() - when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: return waitingForCommitments(_that); - case SigningStatus_SendingSigningPackage() - when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: return sendingSigningPackage(_that); - case SigningStatus_WaitingForSigningPackage() - when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: return waitingForSigningPackage(_that); - case SigningStatus_SendingSignatureShare() - when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: return sendingSignatureShare(_that); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(_that); - case SigningStatus_WaitingForSignatureShares() - when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(_that); - case SigningStatus_PreparingTransaction() - when preparingTransaction != null: + case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(_that); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(_that); @@ -1146,25 +1059,19 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(); - case SigningStatus_WaitingForCommitments() - when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: return waitingForCommitments(); - case SigningStatus_SendingSigningPackage() - when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: return sendingSigningPackage(); - case SigningStatus_WaitingForSigningPackage() - when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: return waitingForSigningPackage(); - case SigningStatus_SendingSignatureShare() - when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: return sendingSignatureShare(); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(); - case SigningStatus_WaitingForSignatureShares() - when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(); - case SigningStatus_PreparingTransaction() - when preparingTransaction != null: + case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(); @@ -1255,25 +1162,19 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(); - case SigningStatus_WaitingForCommitments() - when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: return waitingForCommitments(); - case SigningStatus_SendingSigningPackage() - when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: return sendingSigningPackage(); - case SigningStatus_WaitingForSigningPackage() - when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: return waitingForSigningPackage(); - case SigningStatus_SendingSignatureShare() - when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: return sendingSignatureShare(); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(); - case SigningStatus_WaitingForSignatureShares() - when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(); - case SigningStatus_PreparingTransaction() - when preparingTransaction != null: + case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(); @@ -1292,9 +1193,7 @@ class SigningStatus_SendingCommitment extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_SendingCommitment); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingCommitment); } @override @@ -1313,9 +1212,7 @@ class SigningStatus_WaitingForCommitments extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_WaitingForCommitments); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForCommitments); } @override @@ -1334,9 +1231,7 @@ class SigningStatus_SendingSigningPackage extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_SendingSigningPackage); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingSigningPackage); } @override @@ -1355,9 +1250,7 @@ class SigningStatus_WaitingForSigningPackage extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_WaitingForSigningPackage); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForSigningPackage); } @override @@ -1376,9 +1269,7 @@ class SigningStatus_SendingSignatureShare extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_SendingSignatureShare); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingSignatureShare); } @override @@ -1397,9 +1288,7 @@ class SigningStatus_SigningCompleted extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_SigningCompleted); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SigningCompleted); } @override @@ -1418,9 +1307,7 @@ class SigningStatus_WaitingForSignatureShares extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_WaitingForSignatureShares); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForSignatureShares); } @override @@ -1439,9 +1326,7 @@ class SigningStatus_PreparingTransaction extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_PreparingTransaction); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_PreparingTransaction); } @override @@ -1460,9 +1345,7 @@ class SigningStatus_SendingTransaction extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_SendingTransaction); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingTransaction); } @override @@ -1485,16 +1368,13 @@ class SigningStatus_TransactionSent extends SigningStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningStatus_TransactionSentCopyWith - get copyWith => _$SigningStatus_TransactionSentCopyWithImpl< - SigningStatus_TransactionSent>(this, _$identity); + $SigningStatus_TransactionSentCopyWith get copyWith => + _$SigningStatus_TransactionSentCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningStatus_TransactionSent && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is SigningStatus_TransactionSent && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -1507,19 +1387,15 @@ class SigningStatus_TransactionSent extends SigningStatus { } /// @nodoc -abstract mixin class $SigningStatus_TransactionSentCopyWith<$Res> - implements $SigningStatusCopyWith<$Res> { - factory $SigningStatus_TransactionSentCopyWith( - SigningStatus_TransactionSent value, - $Res Function(SigningStatus_TransactionSent) _then) = +abstract mixin class $SigningStatus_TransactionSentCopyWith<$Res> implements $SigningStatusCopyWith<$Res> { + factory $SigningStatus_TransactionSentCopyWith(SigningStatus_TransactionSent value, $Res Function(SigningStatus_TransactionSent) _then) = _$SigningStatus_TransactionSentCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$SigningStatus_TransactionSentCopyWithImpl<$Res> - implements $SigningStatus_TransactionSentCopyWith<$Res> { +class _$SigningStatus_TransactionSentCopyWithImpl<$Res> implements $SigningStatus_TransactionSentCopyWith<$Res> { _$SigningStatus_TransactionSentCopyWithImpl(this._self, this._then); final SigningStatus_TransactionSent _self; diff --git a/lib/src/rust/api/init.dart b/lib/src/rust/api/init.dart index bbc587bcb..013be7f73 100644 --- a/lib/src/rust/api/init.dart +++ b/lib/src/rust/api/init.dart @@ -16,11 +16,9 @@ part 'init.freezed.dart'; /// Enable expert mode, which lowers the log filter to allow /// sync, mempool, and memo target debug messages /// while keeping everything else at `info`. -void setExpertMode({required bool enabled}) => - RustLib.instance.api.crateApiInitSetExpertMode(enabled: enabled); +void setExpertMode({required bool enabled}) => RustLib.instance.api.crateApiInitSetExpertMode(enabled: enabled); -Stream setLogStream() => - RustLib.instance.api.crateApiInitSetLogStream(); +Stream setLogStream() => RustLib.instance.api.crateApiInitSetLogStream(); @freezed sealed class LogMessage with _$LogMessage { diff --git a/lib/src/rust/api/init.freezed.dart b/lib/src/rust/api/init.freezed.dart index 9b794dc69..ca8fb8a8b 100644 --- a/lib/src/rust/api/init.freezed.dart +++ b/lib/src/rust/api/init.freezed.dart @@ -22,8 +22,7 @@ mixin _$LogMessage { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $LogMessageCopyWith get copyWith => - _$LogMessageCopyWithImpl(this as LogMessage, _$identity); + $LogMessageCopyWith get copyWith => _$LogMessageCopyWithImpl(this as LogMessage, _$identity); @override bool operator ==(Object other) { @@ -46,9 +45,7 @@ mixin _$LogMessage { /// @nodoc abstract mixin class $LogMessageCopyWith<$Res> { - factory $LogMessageCopyWith( - LogMessage value, $Res Function(LogMessage) _then) = - _$LogMessageCopyWithImpl; + factory $LogMessageCopyWith(LogMessage value, $Res Function(LogMessage) _then) = _$LogMessageCopyWithImpl; @useResult $Res call({int level, String message, String? span}); } @@ -256,8 +253,7 @@ class _LogMessage implements LogMessage { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$LogMessageCopyWith<_LogMessage> get copyWith => - __$LogMessageCopyWithImpl<_LogMessage>(this, _$identity); + _$LogMessageCopyWith<_LogMessage> get copyWith => __$LogMessageCopyWithImpl<_LogMessage>(this, _$identity); @override bool operator ==(Object other) { @@ -279,11 +275,8 @@ class _LogMessage implements LogMessage { } /// @nodoc -abstract mixin class _$LogMessageCopyWith<$Res> - implements $LogMessageCopyWith<$Res> { - factory _$LogMessageCopyWith( - _LogMessage value, $Res Function(_LogMessage) _then) = - __$LogMessageCopyWithImpl; +abstract mixin class _$LogMessageCopyWith<$Res> implements $LogMessageCopyWith<$Res> { + factory _$LogMessageCopyWith(_LogMessage value, $Res Function(_LogMessage) _then) = __$LogMessageCopyWithImpl; @override @useResult $Res call({int level, String message, String? span}); diff --git a/lib/src/rust/api/issuance.dart b/lib/src/rust/api/issuance.dart index baa7321b7..20240f0b7 100644 --- a/lib/src/rust/api/issuance.dart +++ b/lib/src/rust/api/issuance.dart @@ -36,10 +36,4 @@ Future issueAsset( required int idAccount, required Coin c}) => RustLib.instance.api.crateApiIssuanceIssueAsset( - assetName: assetName, - amount: amount, - firstIssuance: firstIssuance, - finalize: finalize, - descHash: descHash, - idAccount: idAccount, - c: c); + assetName: assetName, amount: amount, firstIssuance: firstIssuance, finalize: finalize, descHash: descHash, idAccount: idAccount, c: c); diff --git a/lib/src/rust/api/key.dart b/lib/src/rust/api/key.dart index 65992f57e..05287a57d 100644 --- a/lib/src/rust/api/key.dart +++ b/lib/src/rust/api/key.dart @@ -9,24 +9,16 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; String generateSeed() => RustLib.instance.api.crateApiKeyGenerateSeed(); -bool isValidPhrase({required String phrase}) => - RustLib.instance.api.crateApiKeyIsValidPhrase(phrase: phrase); +bool isValidPhrase({required String phrase}) => RustLib.instance.api.crateApiKeyIsValidPhrase(phrase: phrase); -bool isValidFvk({required String fvk, required Coin c}) => - RustLib.instance.api.crateApiKeyIsValidFvk(fvk: fvk, c: c); +bool isValidFvk({required String fvk, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidFvk(fvk: fvk, c: c); -bool isValidKey({required String key, required Coin c}) => - RustLib.instance.api.crateApiKeyIsValidKey(key: key, c: c); +bool isValidKey({required String key, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidKey(key: key, c: c); -bool isValidAddress({required String address}) => - RustLib.instance.api.crateApiKeyIsValidAddress(address: address); +bool isValidAddress({required String address}) => RustLib.instance.api.crateApiKeyIsValidAddress(address: address); -bool isValidTransparentAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiKeyIsValidTransparentAddress(address: address, c: c); +bool isValidTransparentAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidTransparentAddress(address: address, c: c); -bool isTexAddress({required String address, required Coin c}) => - RustLib.instance.api.crateApiKeyIsTexAddress(address: address, c: c); +bool isTexAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiKeyIsTexAddress(address: address, c: c); -int getKeyPools({required String key, required Coin c}) => - RustLib.instance.api.crateApiKeyGetKeyPools(key: key, c: c); +int getKeyPools({required String key, required Coin c}) => RustLib.instance.api.crateApiKeyGetKeyPools(key: key, c: c); diff --git a/lib/src/rust/api/mempool.dart b/lib/src/rust/api/mempool.dart index 847ca3ee0..290ee8ce1 100644 --- a/lib/src/rust/api/mempool.dart +++ b/lib/src/rust/api/mempool.dart @@ -12,8 +12,7 @@ part 'mempool.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `run_mempool` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt` -Future getMempoolTx({required String txId, required Coin c}) => - RustLib.instance.api.crateApiMempoolGetMempoolTx(txId: txId, c: c); +Future getMempoolTx({required String txId, required Coin c}) => RustLib.instance.api.crateApiMempoolGetMempoolTx(txId: txId, c: c); // Rust type: RustOpaqueMoi> abstract class Mempool implements RustOpaqueInterface { @@ -41,11 +40,7 @@ class MempoolAmount { @override bool operator ==(Object other) => identical(this, other) || - other is MempoolAmount && - runtimeType == other.runtimeType && - account == other.account && - name == other.name && - value == other.value; + other is MempoolAmount && runtimeType == other.runtimeType && account == other.account && name == other.name && value == other.value; } @freezed @@ -125,16 +120,10 @@ class MempoolTx { }); @override - int get hashCode => - txid.hashCode ^ amounts.hashCode ^ notes.hashCode ^ size.hashCode; + int get hashCode => txid.hashCode ^ amounts.hashCode ^ notes.hashCode ^ size.hashCode; @override bool operator ==(Object other) => identical(this, other) || - other is MempoolTx && - runtimeType == other.runtimeType && - txid == other.txid && - amounts == other.amounts && - notes == other.notes && - size == other.size; + other is MempoolTx && runtimeType == other.runtimeType && txid == other.txid && amounts == other.amounts && notes == other.notes && size == other.size; } diff --git a/lib/src/rust/api/mempool.freezed.dart b/lib/src/rust/api/mempool.freezed.dart index 98fd47a0a..e409be207 100644 --- a/lib/src/rust/api/mempool.freezed.dart +++ b/lib/src/rust/api/mempool.freezed.dart @@ -18,15 +18,11 @@ mixin _$MempoolMsg { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is MempoolMsg && - const DeepCollectionEquality().equals(other.field0, field0)); + return identical(this, other) || (other.runtimeType == runtimeType && other is MempoolMsg && const DeepCollectionEquality().equals(other.field0, field0)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); @override String toString() { @@ -222,16 +218,12 @@ class MempoolMsg_BlockHeight extends MempoolMsg { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolMsg_BlockHeightCopyWith get copyWith => - _$MempoolMsg_BlockHeightCopyWithImpl( - this, _$identity); + $MempoolMsg_BlockHeightCopyWith get copyWith => _$MempoolMsg_BlockHeightCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is MempoolMsg_BlockHeight && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is MempoolMsg_BlockHeight && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -244,18 +236,14 @@ class MempoolMsg_BlockHeight extends MempoolMsg { } /// @nodoc -abstract mixin class $MempoolMsg_BlockHeightCopyWith<$Res> - implements $MempoolMsgCopyWith<$Res> { - factory $MempoolMsg_BlockHeightCopyWith(MempoolMsg_BlockHeight value, - $Res Function(MempoolMsg_BlockHeight) _then) = - _$MempoolMsg_BlockHeightCopyWithImpl; +abstract mixin class $MempoolMsg_BlockHeightCopyWith<$Res> implements $MempoolMsgCopyWith<$Res> { + factory $MempoolMsg_BlockHeightCopyWith(MempoolMsg_BlockHeight value, $Res Function(MempoolMsg_BlockHeight) _then) = _$MempoolMsg_BlockHeightCopyWithImpl; @useResult $Res call({int field0}); } /// @nodoc -class _$MempoolMsg_BlockHeightCopyWithImpl<$Res> - implements $MempoolMsg_BlockHeightCopyWith<$Res> { +class _$MempoolMsg_BlockHeightCopyWithImpl<$Res> implements $MempoolMsg_BlockHeightCopyWith<$Res> { _$MempoolMsg_BlockHeightCopyWithImpl(this._self, this._then); final MempoolMsg_BlockHeight _self; @@ -288,15 +276,12 @@ class MempoolMsg_TxId extends MempoolMsg { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolMsg_TxIdCopyWith get copyWith => - _$MempoolMsg_TxIdCopyWithImpl(this, _$identity); + $MempoolMsg_TxIdCopyWith get copyWith => _$MempoolMsg_TxIdCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is MempoolMsg_TxId && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is MempoolMsg_TxId && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -309,18 +294,14 @@ class MempoolMsg_TxId extends MempoolMsg { } /// @nodoc -abstract mixin class $MempoolMsg_TxIdCopyWith<$Res> - implements $MempoolMsgCopyWith<$Res> { - factory $MempoolMsg_TxIdCopyWith( - MempoolMsg_TxId value, $Res Function(MempoolMsg_TxId) _then) = - _$MempoolMsg_TxIdCopyWithImpl; +abstract mixin class $MempoolMsg_TxIdCopyWith<$Res> implements $MempoolMsgCopyWith<$Res> { + factory $MempoolMsg_TxIdCopyWith(MempoolMsg_TxId value, $Res Function(MempoolMsg_TxId) _then) = _$MempoolMsg_TxIdCopyWithImpl; @useResult $Res call({MempoolTx field0}); } /// @nodoc -class _$MempoolMsg_TxIdCopyWithImpl<$Res> - implements $MempoolMsg_TxIdCopyWith<$Res> { +class _$MempoolMsg_TxIdCopyWithImpl<$Res> implements $MempoolMsg_TxIdCopyWith<$Res> { _$MempoolMsg_TxIdCopyWithImpl(this._self, this._then); final MempoolMsg_TxId _self; diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index 424c45381..6636f2cfb 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -13,19 +13,16 @@ part 'migrate.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). -Future stepMigration({required Coin c}) => - RustLib.instance.api.crateApiMigrateStepMigration(c: c); +Future stepMigration({required Coin c}) => RustLib.instance.api.crateApiMigrateStepMigration(c: c); /// Stub kept for FRB generated-code compatibility. -Future getMigrationStatus({required Coin c}) => - RustLib.instance.api.crateApiMigrateGetMigrationStatus(c: c); +Future getMigrationStatus({required Coin c}) => RustLib.instance.api.crateApiMigrateGetMigrationStatus(c: c); // Rust type: RustOpaqueMoi> abstract class NoteMigration implements RustOpaqueInterface { Future cancel(); - factory NoteMigration() => - RustLib.instance.api.crateApiMigrateNoteMigrationNew(); + factory NoteMigration() => RustLib.instance.api.crateApiMigrateNoteMigrationNew(); Stream run({required Coin c, required BigInt meanDelayMs}); } diff --git a/lib/src/rust/api/migrate.freezed.dart b/lib/src/rust/api/migrate.freezed.dart index 09e367646..c5184cc96 100644 --- a/lib/src/rust/api/migrate.freezed.dart +++ b/lib/src/rust/api/migrate.freezed.dart @@ -16,8 +16,7 @@ T _$identity(T value) => value; mixin _$MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is MigrationEvent); + return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent); } @override @@ -90,8 +89,7 @@ extension MigrationEventPatterns on MigrationEvent { @optionalTypeArgs TResult map({ required TResult Function(MigrationEvent_SplitComplete value) splitComplete, - required TResult Function(MigrationEvent_MigrateComplete value) - migrateComplete, + required TResult Function(MigrationEvent_MigrateComplete value) migrateComplete, required TResult Function(MigrationEvent_Complete value) complete, required TResult Function(MigrationEvent_NothingToDo value) nothingToDo, required TResult Function(MigrationEvent_Error value) error, @@ -271,16 +269,13 @@ class MigrationEvent_SplitComplete extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_SplitCompleteCopyWith - get copyWith => _$MigrationEvent_SplitCompleteCopyWithImpl< - MigrationEvent_SplitComplete>(this, _$identity); + $MigrationEvent_SplitCompleteCopyWith get copyWith => + _$MigrationEvent_SplitCompleteCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is MigrationEvent_SplitComplete && - (identical(other.fee, fee) || other.fee == fee)); + (other.runtimeType == runtimeType && other is MigrationEvent_SplitComplete && (identical(other.fee, fee) || other.fee == fee)); } @override @@ -293,19 +288,15 @@ class MigrationEvent_SplitComplete extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_SplitCompleteCopyWith<$Res> - implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_SplitCompleteCopyWith( - MigrationEvent_SplitComplete value, - $Res Function(MigrationEvent_SplitComplete) _then) = +abstract mixin class $MigrationEvent_SplitCompleteCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_SplitCompleteCopyWith(MigrationEvent_SplitComplete value, $Res Function(MigrationEvent_SplitComplete) _then) = _$MigrationEvent_SplitCompleteCopyWithImpl; @useResult $Res call({BigInt fee}); } /// @nodoc -class _$MigrationEvent_SplitCompleteCopyWithImpl<$Res> - implements $MigrationEvent_SplitCompleteCopyWith<$Res> { +class _$MigrationEvent_SplitCompleteCopyWithImpl<$Res> implements $MigrationEvent_SplitCompleteCopyWith<$Res> { _$MigrationEvent_SplitCompleteCopyWithImpl(this._self, this._then); final MigrationEvent_SplitComplete _self; @@ -337,16 +328,13 @@ class MigrationEvent_MigrateComplete extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_MigrateCompleteCopyWith - get copyWith => _$MigrationEvent_MigrateCompleteCopyWithImpl< - MigrationEvent_MigrateComplete>(this, _$identity); + $MigrationEvent_MigrateCompleteCopyWith get copyWith => + _$MigrationEvent_MigrateCompleteCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is MigrationEvent_MigrateComplete && - (identical(other.fee, fee) || other.fee == fee)); + (other.runtimeType == runtimeType && other is MigrationEvent_MigrateComplete && (identical(other.fee, fee) || other.fee == fee)); } @override @@ -359,19 +347,15 @@ class MigrationEvent_MigrateComplete extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_MigrateCompleteCopyWith<$Res> - implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_MigrateCompleteCopyWith( - MigrationEvent_MigrateComplete value, - $Res Function(MigrationEvent_MigrateComplete) _then) = +abstract mixin class $MigrationEvent_MigrateCompleteCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_MigrateCompleteCopyWith(MigrationEvent_MigrateComplete value, $Res Function(MigrationEvent_MigrateComplete) _then) = _$MigrationEvent_MigrateCompleteCopyWithImpl; @useResult $Res call({BigInt fee}); } /// @nodoc -class _$MigrationEvent_MigrateCompleteCopyWithImpl<$Res> - implements $MigrationEvent_MigrateCompleteCopyWith<$Res> { +class _$MigrationEvent_MigrateCompleteCopyWithImpl<$Res> implements $MigrationEvent_MigrateCompleteCopyWith<$Res> { _$MigrationEvent_MigrateCompleteCopyWithImpl(this._self, this._then); final MigrationEvent_MigrateComplete _self; @@ -399,8 +383,7 @@ class MigrationEvent_Complete extends MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is MigrationEvent_Complete); + return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent_Complete); } @override @@ -419,9 +402,7 @@ class MigrationEvent_NothingToDo extends MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is MigrationEvent_NothingToDo); + return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent_NothingToDo); } @override @@ -444,16 +425,12 @@ class MigrationEvent_Error extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_ErrorCopyWith get copyWith => - _$MigrationEvent_ErrorCopyWithImpl( - this, _$identity); + $MigrationEvent_ErrorCopyWith get copyWith => _$MigrationEvent_ErrorCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is MigrationEvent_Error && - (identical(other.message, message) || other.message == message)); + (other.runtimeType == runtimeType && other is MigrationEvent_Error && (identical(other.message, message) || other.message == message)); } @override @@ -466,18 +443,14 @@ class MigrationEvent_Error extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_ErrorCopyWith<$Res> - implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_ErrorCopyWith(MigrationEvent_Error value, - $Res Function(MigrationEvent_Error) _then) = - _$MigrationEvent_ErrorCopyWithImpl; +abstract mixin class $MigrationEvent_ErrorCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_ErrorCopyWith(MigrationEvent_Error value, $Res Function(MigrationEvent_Error) _then) = _$MigrationEvent_ErrorCopyWithImpl; @useResult $Res call({String message}); } /// @nodoc -class _$MigrationEvent_ErrorCopyWithImpl<$Res> - implements $MigrationEvent_ErrorCopyWith<$Res> { +class _$MigrationEvent_ErrorCopyWithImpl<$Res> implements $MigrationEvent_ErrorCopyWith<$Res> { _$MigrationEvent_ErrorCopyWithImpl(this._self, this._then); final MigrationEvent_Error _self; diff --git a/lib/src/rust/api/network.dart b/lib/src/rust/api/network.dart index 05afff178..434c4f910 100644 --- a/lib/src/rust/api/network.dart +++ b/lib/src/rust/api/network.dart @@ -12,38 +12,26 @@ part 'network.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `coingecko_client` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt` -Future initDatadir({required String directory}) => - RustLib.instance.api.crateApiNetworkInitDatadir(directory: directory); +Future initDatadir({required String directory}) => RustLib.instance.api.crateApiNetworkInitDatadir(directory: directory); -Future isIronwoodActive({required Coin c}) => - RustLib.instance.api.crateApiNetworkIsIronwoodActive(c: c); +Future isIronwoodActive({required Coin c}) => RustLib.instance.api.crateApiNetworkIsIronwoodActive(c: c); -Future getCurrentHeight({required Coin c}) => - RustLib.instance.api.crateApiNetworkGetCurrentHeight(c: c); +Future getCurrentHeight({required Coin c}) => RustLib.instance.api.crateApiNetworkGetCurrentHeight(c: c); -Future getCoingeckoPrice( - {required String api, required String currency}) => - RustLib.instance.api - .crateApiNetworkGetCoingeckoPrice(api: api, currency: currency); +Future getCoingeckoPrice({required String api, required String currency}) => + RustLib.instance.api.crateApiNetworkGetCoingeckoPrice(api: api, currency: currency); -Future> getSupportedVsCurrencies({required String api}) => - RustLib.instance.api.crateApiNetworkGetSupportedVsCurrencies(api: api); +Future> getSupportedVsCurrencies({required String api}) => RustLib.instance.api.crateApiNetworkGetSupportedVsCurrencies(api: api); /// Returns the ZEC price in both `from_currency` and `to_currency`. /// The exchange rate from `from_currency` to `to_currency` can be computed as /// `to_price / from_price`. -Future getExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}) => - RustLib.instance.api.crateApiNetworkGetExchangeRate( - api: api, fromCurrency: fromCurrency, toCurrency: toCurrency); +Future getExchangeRate({required String api, required String fromCurrency, required String toCurrency}) => + RustLib.instance.api.crateApiNetworkGetExchangeRate(api: api, fromCurrency: fromCurrency, toCurrency: toCurrency); -Future getNetworkName({required Coin c}) => - RustLib.instance.api.crateApiNetworkGetNetworkName(c: c); +Future getNetworkName({required Coin c}) => RustLib.instance.api.crateApiNetworkGetNetworkName(c: c); -Future> queryLwdList({required int coin}) => - RustLib.instance.api.crateApiNetworkQueryLwdList(coin: coin); +Future> queryLwdList({required int coin}) => RustLib.instance.api.crateApiNetworkQueryLwdList(coin: coin); @freezed sealed class ExchangeRate with _$ExchangeRate { diff --git a/lib/src/rust/api/network.freezed.dart b/lib/src/rust/api/network.freezed.dart index 7ed5a4bb3..94697f15e 100644 --- a/lib/src/rust/api/network.freezed.dart +++ b/lib/src/rust/api/network.freezed.dart @@ -23,27 +23,21 @@ mixin _$ExchangeRate { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ExchangeRateCopyWith get copyWith => - _$ExchangeRateCopyWithImpl( - this as ExchangeRate, _$identity); + $ExchangeRateCopyWith get copyWith => _$ExchangeRateCopyWithImpl(this as ExchangeRate, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is ExchangeRate && - (identical(other.fromPrice, fromPrice) || - other.fromPrice == fromPrice) && + (identical(other.fromPrice, fromPrice) || other.fromPrice == fromPrice) && (identical(other.toPrice, toPrice) || other.toPrice == toPrice) && - (identical(other.fromCurrency, fromCurrency) || - other.fromCurrency == fromCurrency) && - (identical(other.toCurrency, toCurrency) || - other.toCurrency == toCurrency)); + (identical(other.fromCurrency, fromCurrency) || other.fromCurrency == fromCurrency) && + (identical(other.toCurrency, toCurrency) || other.toCurrency == toCurrency)); } @override - int get hashCode => - Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); + int get hashCode => Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); @override String toString() { @@ -53,15 +47,9 @@ mixin _$ExchangeRate { /// @nodoc abstract mixin class $ExchangeRateCopyWith<$Res> { - factory $ExchangeRateCopyWith( - ExchangeRate value, $Res Function(ExchangeRate) _then) = - _$ExchangeRateCopyWithImpl; + factory $ExchangeRateCopyWith(ExchangeRate value, $Res Function(ExchangeRate) _then) = _$ExchangeRateCopyWithImpl; @useResult - $Res call( - {double fromPrice, - double toPrice, - String fromCurrency, - String toCurrency}); + $Res call({double fromPrice, double toPrice, String fromCurrency, String toCurrency}); } /// @nodoc @@ -193,16 +181,13 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult maybeWhen( - TResult Function(double fromPrice, double toPrice, String fromCurrency, - String toCurrency)? - $default, { + TResult Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _ExchangeRate() when $default != null: - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, - _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); case _: return orElse(); } @@ -223,15 +208,12 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult when( - TResult Function(double fromPrice, double toPrice, String fromCurrency, - String toCurrency) - $default, + TResult Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency) $default, ) { final _that = this; switch (_that) { case _ExchangeRate(): - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, - _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); } } @@ -249,15 +231,12 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(double fromPrice, double toPrice, String fromCurrency, - String toCurrency)? - $default, + TResult? Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency)? $default, ) { final _that = this; switch (_that) { case _ExchangeRate() when $default != null: - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, - _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); case _: return null; } @@ -267,11 +246,7 @@ extension ExchangeRatePatterns on ExchangeRate { /// @nodoc class _ExchangeRate implements ExchangeRate { - const _ExchangeRate( - {required this.fromPrice, - required this.toPrice, - required this.fromCurrency, - required this.toCurrency}); + const _ExchangeRate({required this.fromPrice, required this.toPrice, required this.fromCurrency, required this.toCurrency}); @override final double fromPrice; @@ -287,26 +262,21 @@ class _ExchangeRate implements ExchangeRate { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ExchangeRateCopyWith<_ExchangeRate> get copyWith => - __$ExchangeRateCopyWithImpl<_ExchangeRate>(this, _$identity); + _$ExchangeRateCopyWith<_ExchangeRate> get copyWith => __$ExchangeRateCopyWithImpl<_ExchangeRate>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _ExchangeRate && - (identical(other.fromPrice, fromPrice) || - other.fromPrice == fromPrice) && + (identical(other.fromPrice, fromPrice) || other.fromPrice == fromPrice) && (identical(other.toPrice, toPrice) || other.toPrice == toPrice) && - (identical(other.fromCurrency, fromCurrency) || - other.fromCurrency == fromCurrency) && - (identical(other.toCurrency, toCurrency) || - other.toCurrency == toCurrency)); + (identical(other.fromCurrency, fromCurrency) || other.fromCurrency == fromCurrency) && + (identical(other.toCurrency, toCurrency) || other.toCurrency == toCurrency)); } @override - int get hashCode => - Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); + int get hashCode => Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); @override String toString() { @@ -315,23 +285,15 @@ class _ExchangeRate implements ExchangeRate { } /// @nodoc -abstract mixin class _$ExchangeRateCopyWith<$Res> - implements $ExchangeRateCopyWith<$Res> { - factory _$ExchangeRateCopyWith( - _ExchangeRate value, $Res Function(_ExchangeRate) _then) = - __$ExchangeRateCopyWithImpl; +abstract mixin class _$ExchangeRateCopyWith<$Res> implements $ExchangeRateCopyWith<$Res> { + factory _$ExchangeRateCopyWith(_ExchangeRate value, $Res Function(_ExchangeRate) _then) = __$ExchangeRateCopyWithImpl; @override @useResult - $Res call( - {double fromPrice, - double toPrice, - String fromCurrency, - String toCurrency}); + $Res call({double fromPrice, double toPrice, String fromCurrency, String toCurrency}); } /// @nodoc -class __$ExchangeRateCopyWithImpl<$Res> - implements _$ExchangeRateCopyWith<$Res> { +class __$ExchangeRateCopyWithImpl<$Res> implements _$ExchangeRateCopyWith<$Res> { __$ExchangeRateCopyWithImpl(this._self, this._then); final _ExchangeRate _self; @@ -382,8 +344,7 @@ mixin _$LWDInfo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $LWDInfoCopyWith get copyWith => - _$LWDInfoCopyWithImpl(this as LWDInfo, _$identity); + $LWDInfoCopyWith get copyWith => _$LWDInfoCopyWithImpl(this as LWDInfo, _$identity); @override bool operator ==(Object other) { @@ -400,8 +361,7 @@ mixin _$LWDInfo { } @override - int get hashCode => Object.hash( - runtimeType, url, isTor, height, status, uptime, version, ping); + int get hashCode => Object.hash(runtimeType, url, isTor, height, status, uptime, version, ping); @override String toString() { @@ -411,17 +371,9 @@ mixin _$LWDInfo { /// @nodoc abstract mixin class $LWDInfoCopyWith<$Res> { - factory $LWDInfoCopyWith(LWDInfo value, $Res Function(LWDInfo) _then) = - _$LWDInfoCopyWithImpl; + factory $LWDInfoCopyWith(LWDInfo value, $Res Function(LWDInfo) _then) = _$LWDInfoCopyWithImpl; @useResult - $Res call( - {String url, - bool isTor, - int height, - String status, - int uptime, - String version, - int ping}); + $Res call({String url, bool isTor, int height, String status, int uptime, String version, int ping}); } /// @nodoc @@ -568,16 +520,13 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult maybeWhen( - TResult Function(String url, bool isTor, int height, String status, - int uptime, String version, int ping)? - $default, { + TResult Function(String url, bool isTor, int height, String status, int uptime, String version, int ping)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _LWDInfo() when $default != null: - return $default(_that.url, _that.isTor, _that.height, _that.status, - _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); case _: return orElse(); } @@ -598,15 +547,12 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult when( - TResult Function(String url, bool isTor, int height, String status, - int uptime, String version, int ping) - $default, + TResult Function(String url, bool isTor, int height, String status, int uptime, String version, int ping) $default, ) { final _that = this; switch (_that) { case _LWDInfo(): - return $default(_that.url, _that.isTor, _that.height, _that.status, - _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); } } @@ -624,15 +570,12 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String url, bool isTor, int height, String status, - int uptime, String version, int ping)? - $default, + TResult? Function(String url, bool isTor, int height, String status, int uptime, String version, int ping)? $default, ) { final _that = this; switch (_that) { case _LWDInfo() when $default != null: - return $default(_that.url, _that.isTor, _that.height, _that.status, - _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); case _: return null; } @@ -643,13 +586,7 @@ extension LWDInfoPatterns on LWDInfo { class _LWDInfo implements LWDInfo { const _LWDInfo( - {required this.url, - required this.isTor, - required this.height, - required this.status, - required this.uptime, - required this.version, - required this.ping}); + {required this.url, required this.isTor, required this.height, required this.status, required this.uptime, required this.version, required this.ping}); @override final String url; @@ -671,8 +608,7 @@ class _LWDInfo implements LWDInfo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$LWDInfoCopyWith<_LWDInfo> get copyWith => - __$LWDInfoCopyWithImpl<_LWDInfo>(this, _$identity); + _$LWDInfoCopyWith<_LWDInfo> get copyWith => __$LWDInfoCopyWithImpl<_LWDInfo>(this, _$identity); @override bool operator ==(Object other) { @@ -689,8 +625,7 @@ class _LWDInfo implements LWDInfo { } @override - int get hashCode => Object.hash( - runtimeType, url, isTor, height, status, uptime, version, ping); + int get hashCode => Object.hash(runtimeType, url, isTor, height, status, uptime, version, ping); @override String toString() { @@ -700,18 +635,10 @@ class _LWDInfo implements LWDInfo { /// @nodoc abstract mixin class _$LWDInfoCopyWith<$Res> implements $LWDInfoCopyWith<$Res> { - factory _$LWDInfoCopyWith(_LWDInfo value, $Res Function(_LWDInfo) _then) = - __$LWDInfoCopyWithImpl; + factory _$LWDInfoCopyWith(_LWDInfo value, $Res Function(_LWDInfo) _then) = __$LWDInfoCopyWithImpl; @override @useResult - $Res call( - {String url, - bool isTor, - int height, - String status, - int uptime, - String version, - int ping}); + $Res call({String url, bool isTor, int height, String status, int uptime, String version, int ping}); } /// @nodoc diff --git a/lib/src/rust/api/openalias.dart b/lib/src/rust/api/openalias.dart index 7e0e0fb46..5c9507625 100644 --- a/lib/src/rust/api/openalias.dart +++ b/lib/src/rust/api/openalias.dart @@ -15,39 +15,32 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// /// Performs DNS TXT lookup, parses OA1 records, filters for Zcash /// addresses, and validates them against the wallet's network type. -Future resolveOpenalias( - {required String alias, required Coin c}) => +Future resolveOpenalias({required String alias, required Coin c}) => RustLib.instance.api.crateApiOpenaliasResolveOpenalias(alias: alias, c: c); /// Resolve an OpenAlias name and return ALL cryptocurrency addresses /// found (not just Zcash) as [`Recipient`]s. -Future resolveOpenaliasAll({required String alias}) => - RustLib.instance.api.crateApiOpenaliasResolveOpenaliasAll(alias: alias); +Future resolveOpenaliasAll({required String alias}) => RustLib.instance.api.crateApiOpenaliasResolveOpenaliasAll(alias: alias); /// Validate whether a string looks like a valid OpenAlias name format. /// Returns true/false without performing any DNS lookup. -bool validateOpenaliasName({required String alias}) => - RustLib.instance.api.crateApiOpenaliasValidateOpenaliasName(alias: alias); +bool validateOpenaliasName({required String alias}) => RustLib.instance.api.crateApiOpenaliasValidateOpenaliasName(alias: alias); /// Validate that an address string is a syntactically valid Zcash address /// for the wallet's network (convenience wrapper returning bool). /// /// See [`try_validate_zcash_address`] for the `Result`-returning variant /// that provides error details. -bool validateZcashAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiOpenaliasValidateZcashAddress(address: address, c: c); +bool validateZcashAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiOpenaliasValidateZcashAddress(address: address, c: c); /// Try to validate that an address string is a syntactically valid Zcash /// address for the wallet's network, returning `Ok(())` or an error with /// details about why validation failed. void tryValidateZcashAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiOpenaliasTryValidateZcashAddress(address: address, c: c); + RustLib.instance.api.crateApiOpenaliasTryValidateZcashAddress(address: address, c: c); /// Get the raw OpenAlias TXT record strings for diagnostic purposes. -Future resolveOpenaliasRaw({required String alias}) => - RustLib.instance.api.crateApiOpenaliasResolveOpenaliasRaw(alias: alias); +Future resolveOpenaliasRaw({required String alias}) => RustLib.instance.api.crateApiOpenaliasResolveOpenaliasRaw(alias: alias); /// Result of an OpenAlias resolution, including DNSSEC verification status. class OpenAliasResolution { @@ -67,10 +60,7 @@ class OpenAliasResolution { @override bool operator ==(Object other) => identical(this, other) || - other is OpenAliasResolution && - runtimeType == other.runtimeType && - recipients == other.recipients && - dnssecStatus == other.dnssecStatus; + other is OpenAliasResolution && runtimeType == other.runtimeType && recipients == other.recipients && dnssecStatus == other.dnssecStatus; } /// Result of a raw OpenAlias resolution, including DNSSEC verification status. @@ -91,8 +81,5 @@ class RawOpenAliasResolution { @override bool operator ==(Object other) => identical(this, other) || - other is RawOpenAliasResolution && - runtimeType == other.runtimeType && - records == other.records && - dnssecStatus == other.dnssecStatus; + other is RawOpenAliasResolution && runtimeType == other.runtimeType && records == other.records && dnssecStatus == other.dnssecStatus; } diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index 5af48ef4c..9da534193 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -13,61 +13,35 @@ part 'pay.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `borrow_decode`, `decode`, `encode` -Future buildPuri({required List recipients}) => - RustLib.instance.api.crateApiPayBuildPuri(recipients: recipients); +Future buildPuri({required List recipients}) => RustLib.instance.api.crateApiPayBuildPuri(recipients: recipients); -Future prepare( - {required List recipients, - required PaymentOptions options, - required Coin c}) => - RustLib.instance.api - .crateApiPayPrepare(recipients: recipients, options: options, c: c); +Future prepare({required List recipients, required PaymentOptions options, required Coin c}) => + RustLib.instance.api.crateApiPayPrepare(recipients: recipients, options: options, c: c); /// Prepare a migration transaction (splitting or migrating). /// Uses `migration=true` to allow Orchard outputs when Ironwood is active. -Future prepareMigration( - {required List recipients, - required int srcPools, - required Coin c}) => - RustLib.instance.api.crateApiPayPrepareMigration( - recipients: recipients, srcPools: srcPools, c: c); - -Future signTransaction( - {required PcztPackage pczt, required Coin c}) => - RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); - -Future extractTransaction({required PcztPackage package}) => - RustLib.instance.api.crateApiPayExtractTransaction(package: package); - -Future packTransaction({required PcztPackage pczt}) => - RustLib.instance.api.crateApiPayPackTransaction(pczt: pczt); - -Future unpackTransaction({required List bytes}) => - RustLib.instance.api.crateApiPayUnpackTransaction(bytes: bytes); - -Future broadcastTransaction( - {required int height, required List txBytes, required Coin c}) => - RustLib.instance.api.crateApiPayBroadcastTransaction( - height: height, txBytes: txBytes, c: c); - -TxPlan toPlan({required PcztPackage package, required Coin c}) => - RustLib.instance.api.crateApiPayToPlan(package: package, c: c); - -Future send( - {required int height, required List data, required Coin c}) => - RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); - -Future storePendingTx( - {required int height, - required List txid, - double? price, - int? category, - required Coin c}) => - RustLib.instance.api.crateApiPayStorePendingTx( - height: height, txid: txid, price: price, category: category, c: c); - -List? parsePaymentUri({required String uri}) => - RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); +Future prepareMigration({required List recipients, required int srcPools, required Coin c}) => + RustLib.instance.api.crateApiPayPrepareMigration(recipients: recipients, srcPools: srcPools, c: c); + +Future signTransaction({required PcztPackage pczt, required Coin c}) => RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); + +Future extractTransaction({required PcztPackage package}) => RustLib.instance.api.crateApiPayExtractTransaction(package: package); + +Future packTransaction({required PcztPackage pczt}) => RustLib.instance.api.crateApiPayPackTransaction(pczt: pczt); + +Future unpackTransaction({required List bytes}) => RustLib.instance.api.crateApiPayUnpackTransaction(bytes: bytes); + +Future broadcastTransaction({required int height, required List txBytes, required Coin c}) => + RustLib.instance.api.crateApiPayBroadcastTransaction(height: height, txBytes: txBytes, c: c); + +TxPlan toPlan({required PcztPackage package, required Coin c}) => RustLib.instance.api.crateApiPayToPlan(package: package, c: c); + +Future send({required int height, required List data, required Coin c}) => RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); + +Future storePendingTx({required int height, required List txid, double? price, int? category, required Coin c}) => + RustLib.instance.api.crateApiPayStorePendingTx(height: height, txid: txid, price: price, category: category, c: c); + +List? parsePaymentUri({required String uri}) => RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); class PaymentOptions { final int srcPools; @@ -83,11 +57,7 @@ class PaymentOptions { }); @override - int get hashCode => - srcPools.hashCode ^ - recipientPaysFee.hashCode ^ - smartTransparent.hashCode ^ - category.hashCode; + int get hashCode => srcPools.hashCode ^ recipientPaysFee.hashCode ^ smartTransparent.hashCode ^ category.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/pay.freezed.dart b/lib/src/rust/api/pay.freezed.dart index 489143a29..10328fae2 100644 --- a/lib/src/rust/api/pay.freezed.dart +++ b/lib/src/rust/api/pay.freezed.dart @@ -29,8 +29,7 @@ mixin _$PcztPackage { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $PcztPackageCopyWith get copyWith => - _$PcztPackageCopyWithImpl(this as PcztPackage, _$identity); + $PcztPackageCopyWith get copyWith => _$PcztPackageCopyWithImpl(this as PcztPackage, _$identity); @override bool operator ==(Object other) { @@ -39,20 +38,14 @@ mixin _$PcztPackage { other is PcztPackage && const DeepCollectionEquality().equals(other.pczt, pczt) && const DeepCollectionEquality().equals(other.nSpends, nSpends) && - const DeepCollectionEquality() - .equals(other.saplingIndices, saplingIndices) && - const DeepCollectionEquality() - .equals(other.orchardIndices, orchardIndices) && - const DeepCollectionEquality() - .equals(other.ironwoodIndices, ironwoodIndices) && + const DeepCollectionEquality().equals(other.saplingIndices, saplingIndices) && + const DeepCollectionEquality().equals(other.orchardIndices, orchardIndices) && + const DeepCollectionEquality().equals(other.ironwoodIndices, ironwoodIndices) && (identical(other.canSign, canSign) || other.canSign == canSign) && - (identical(other.canBroadcast, canBroadcast) || - other.canBroadcast == canBroadcast) && + (identical(other.canBroadcast, canBroadcast) || other.canBroadcast == canBroadcast) && (identical(other.price, price) || other.price == price) && - (identical(other.category, category) || - other.category == category) && - (identical(other.isIssuance, isIssuance) || - other.isIssuance == isIssuance)); + (identical(other.category, category) || other.category == category) && + (identical(other.isIssuance, isIssuance) || other.isIssuance == isIssuance)); } @override @@ -77,9 +70,7 @@ mixin _$PcztPackage { /// @nodoc abstract mixin class $PcztPackageCopyWith<$Res> { - factory $PcztPackageCopyWith( - PcztPackage value, $Res Function(PcztPackage) _then) = - _$PcztPackageCopyWithImpl; + factory $PcztPackageCopyWith(PcztPackage value, $Res Function(PcztPackage) _then) = _$PcztPackageCopyWithImpl; @useResult $Res call( {Uint8List pczt, @@ -253,34 +244,16 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult maybeWhen( - TResult Function( - Uint8List pczt, - UsizeArray4 nSpends, - Uint64List saplingIndices, - Uint64List orchardIndices, - Uint64List ironwoodIndices, - bool canSign, - bool canBroadcast, - double? price, - int? category, - bool isIssuance)? + TResult Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, + bool canBroadcast, double? price, int? category, bool isIssuance)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _PcztPackage() when $default != null: - return $default( - _that.pczt, - _that.nSpends, - _that.saplingIndices, - _that.orchardIndices, - _that.ironwoodIndices, - _that.canSign, - _that.canBroadcast, - _that.price, - _that.category, - _that.isIssuance); + return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, + _that.price, _that.category, _that.isIssuance); case _: return orElse(); } @@ -301,33 +274,15 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult when( - TResult Function( - Uint8List pczt, - UsizeArray4 nSpends, - Uint64List saplingIndices, - Uint64List orchardIndices, - Uint64List ironwoodIndices, - bool canSign, - bool canBroadcast, - double? price, - int? category, - bool isIssuance) + TResult Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, + bool canBroadcast, double? price, int? category, bool isIssuance) $default, ) { final _that = this; switch (_that) { case _PcztPackage(): - return $default( - _that.pczt, - _that.nSpends, - _that.saplingIndices, - _that.orchardIndices, - _that.ironwoodIndices, - _that.canSign, - _that.canBroadcast, - _that.price, - _that.category, - _that.isIssuance); + return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, + _that.price, _that.category, _that.isIssuance); } } @@ -345,33 +300,15 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Uint8List pczt, - UsizeArray4 nSpends, - Uint64List saplingIndices, - Uint64List orchardIndices, - Uint64List ironwoodIndices, - bool canSign, - bool canBroadcast, - double? price, - int? category, - bool isIssuance)? + TResult? Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, + bool canBroadcast, double? price, int? category, bool isIssuance)? $default, ) { final _that = this; switch (_that) { case _PcztPackage() when $default != null: - return $default( - _that.pczt, - _that.nSpends, - _that.saplingIndices, - _that.orchardIndices, - _that.ironwoodIndices, - _that.canSign, - _that.canBroadcast, - _that.price, - _that.category, - _that.isIssuance); + return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, + _that.price, _that.category, _that.isIssuance); case _: return null; } @@ -419,8 +356,7 @@ class _PcztPackage implements PcztPackage { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$PcztPackageCopyWith<_PcztPackage> get copyWith => - __$PcztPackageCopyWithImpl<_PcztPackage>(this, _$identity); + _$PcztPackageCopyWith<_PcztPackage> get copyWith => __$PcztPackageCopyWithImpl<_PcztPackage>(this, _$identity); @override bool operator ==(Object other) { @@ -429,20 +365,14 @@ class _PcztPackage implements PcztPackage { other is _PcztPackage && const DeepCollectionEquality().equals(other.pczt, pczt) && const DeepCollectionEquality().equals(other.nSpends, nSpends) && - const DeepCollectionEquality() - .equals(other.saplingIndices, saplingIndices) && - const DeepCollectionEquality() - .equals(other.orchardIndices, orchardIndices) && - const DeepCollectionEquality() - .equals(other.ironwoodIndices, ironwoodIndices) && + const DeepCollectionEquality().equals(other.saplingIndices, saplingIndices) && + const DeepCollectionEquality().equals(other.orchardIndices, orchardIndices) && + const DeepCollectionEquality().equals(other.ironwoodIndices, ironwoodIndices) && (identical(other.canSign, canSign) || other.canSign == canSign) && - (identical(other.canBroadcast, canBroadcast) || - other.canBroadcast == canBroadcast) && + (identical(other.canBroadcast, canBroadcast) || other.canBroadcast == canBroadcast) && (identical(other.price, price) || other.price == price) && - (identical(other.category, category) || - other.category == category) && - (identical(other.isIssuance, isIssuance) || - other.isIssuance == isIssuance)); + (identical(other.category, category) || other.category == category) && + (identical(other.isIssuance, isIssuance) || other.isIssuance == isIssuance)); } @override @@ -466,11 +396,8 @@ class _PcztPackage implements PcztPackage { } /// @nodoc -abstract mixin class _$PcztPackageCopyWith<$Res> - implements $PcztPackageCopyWith<$Res> { - factory _$PcztPackageCopyWith( - _PcztPackage value, $Res Function(_PcztPackage) _then) = - __$PcztPackageCopyWithImpl; +abstract mixin class _$PcztPackageCopyWith<$Res> implements $PcztPackageCopyWith<$Res> { + factory _$PcztPackageCopyWith(_PcztPackage value, $Res Function(_PcztPackage) _then) = __$PcztPackageCopyWithImpl; @override @useResult $Res call( @@ -560,15 +487,11 @@ mixin _$SigningEvent { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningEvent && - const DeepCollectionEquality().equals(other.field0, field0)); + return identical(this, other) || (other.runtimeType == runtimeType && other is SigningEvent && const DeepCollectionEquality().equals(other.field0, field0)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); @override String toString() { @@ -764,16 +687,12 @@ class SigningEvent_Progress extends SigningEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningEvent_ProgressCopyWith get copyWith => - _$SigningEvent_ProgressCopyWithImpl( - this, _$identity); + $SigningEvent_ProgressCopyWith get copyWith => _$SigningEvent_ProgressCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningEvent_Progress && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is SigningEvent_Progress && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -786,18 +705,14 @@ class SigningEvent_Progress extends SigningEvent { } /// @nodoc -abstract mixin class $SigningEvent_ProgressCopyWith<$Res> - implements $SigningEventCopyWith<$Res> { - factory $SigningEvent_ProgressCopyWith(SigningEvent_Progress value, - $Res Function(SigningEvent_Progress) _then) = - _$SigningEvent_ProgressCopyWithImpl; +abstract mixin class $SigningEvent_ProgressCopyWith<$Res> implements $SigningEventCopyWith<$Res> { + factory $SigningEvent_ProgressCopyWith(SigningEvent_Progress value, $Res Function(SigningEvent_Progress) _then) = _$SigningEvent_ProgressCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$SigningEvent_ProgressCopyWithImpl<$Res> - implements $SigningEvent_ProgressCopyWith<$Res> { +class _$SigningEvent_ProgressCopyWithImpl<$Res> implements $SigningEvent_ProgressCopyWith<$Res> { _$SigningEvent_ProgressCopyWithImpl(this._self, this._then); final SigningEvent_Progress _self; @@ -830,15 +745,12 @@ class SigningEvent_Result extends SigningEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningEvent_ResultCopyWith get copyWith => - _$SigningEvent_ResultCopyWithImpl(this, _$identity); + $SigningEvent_ResultCopyWith get copyWith => _$SigningEvent_ResultCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is SigningEvent_Result && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is SigningEvent_Result && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -851,11 +763,8 @@ class SigningEvent_Result extends SigningEvent { } /// @nodoc -abstract mixin class $SigningEvent_ResultCopyWith<$Res> - implements $SigningEventCopyWith<$Res> { - factory $SigningEvent_ResultCopyWith( - SigningEvent_Result value, $Res Function(SigningEvent_Result) _then) = - _$SigningEvent_ResultCopyWithImpl; +abstract mixin class $SigningEvent_ResultCopyWith<$Res> implements $SigningEventCopyWith<$Res> { + factory $SigningEvent_ResultCopyWith(SigningEvent_Result value, $Res Function(SigningEvent_Result) _then) = _$SigningEvent_ResultCopyWithImpl; @useResult $Res call({PcztPackage field0}); @@ -863,8 +772,7 @@ abstract mixin class $SigningEvent_ResultCopyWith<$Res> } /// @nodoc -class _$SigningEvent_ResultCopyWithImpl<$Res> - implements $SigningEvent_ResultCopyWith<$Res> { +class _$SigningEvent_ResultCopyWithImpl<$Res> implements $SigningEvent_ResultCopyWith<$Res> { _$SigningEvent_ResultCopyWithImpl(this._self, this._then); final SigningEvent_Result _self; diff --git a/lib/src/rust/api/plugin.dart b/lib/src/rust/api/plugin.dart index 773ec276d..739965a1d 100644 --- a/lib/src/rust/api/plugin.dart +++ b/lib/src/rust/api/plugin.dart @@ -10,30 +10,23 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'plugin.freezed.dart'; /// List all installed plugins. -Future> listPlugins({required Coin c}) => - RustLib.instance.api.crateApiPluginListPlugins(c: c); +Future> listPlugins({required Coin c}) => RustLib.instance.api.crateApiPluginListPlugins(c: c); /// Install a plugin from a URL (downloads a .zip archive). -Future installPlugin({required String url, required Coin c}) => - RustLib.instance.api.crateApiPluginInstallPlugin(url: url, c: c); +Future installPlugin({required String url, required Coin c}) => RustLib.instance.api.crateApiPluginInstallPlugin(url: url, c: c); /// Remove a plugin completely (files + DB). -Future removePlugin({required String id, required Coin c}) => - RustLib.instance.api.crateApiPluginRemovePlugin(id: id, c: c); +Future removePlugin({required String id, required Coin c}) => RustLib.instance.api.crateApiPluginRemovePlugin(id: id, c: c); /// Enable or disable a plugin. -Future setPluginEnabled( - {required String id, required bool enabled, required Coin c}) => - RustLib.instance.api - .crateApiPluginSetPluginEnabled(id: id, enabled: enabled, c: c); +Future setPluginEnabled({required String id, required bool enabled, required Coin c}) => + RustLib.instance.api.crateApiPluginSetPluginEnabled(id: id, enabled: enabled, c: c); /// Parse a memo with all matching plugins. /// `memo_bytes` is the full 512-byte memo (including the 0xFF type byte). /// Returns sections from all plugins whose prefixes match. -Future> parseMemoWithPlugins( - {required List memoBytes, required Coin c}) => - RustLib.instance.api - .crateApiPluginParseMemoWithPlugins(memoBytes: memoBytes, c: c); +Future> parseMemoWithPlugins({required List memoBytes, required Coin c}) => + RustLib.instance.api.crateApiPluginParseMemoWithPlugins(memoBytes: memoBytes, c: c); /// Initialize the plugin system at app startup (creates plugins directory). void initPlugins() => RustLib.instance.api.crateApiPluginInitPlugins(); diff --git a/lib/src/rust/api/plugin.freezed.dart b/lib/src/rust/api/plugin.freezed.dart index 60e74f136..563e395aa 100644 --- a/lib/src/rust/api/plugin.freezed.dart +++ b/lib/src/rust/api/plugin.freezed.dart @@ -21,16 +21,14 @@ mixin _$MemoCell { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoCellCopyWith get copyWith => - _$MemoCellCopyWithImpl(this as MemoCell, _$identity); + $MemoCellCopyWith get copyWith => _$MemoCellCopyWithImpl(this as MemoCell, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is MemoCell && - (identical(other.cellType, cellType) || - other.cellType == cellType) && + (identical(other.cellType, cellType) || other.cellType == cellType) && (identical(other.value, value) || other.value == value)); } @@ -45,8 +43,7 @@ mixin _$MemoCell { /// @nodoc abstract mixin class $MemoCellCopyWith<$Res> { - factory $MemoCellCopyWith(MemoCell value, $Res Function(MemoCell) _then) = - _$MemoCellCopyWithImpl; + factory $MemoCellCopyWith(MemoCell value, $Res Function(MemoCell) _then) = _$MemoCellCopyWithImpl; @useResult $Res call({String cellType, String value}); } @@ -247,16 +244,14 @@ class _MemoCell implements MemoCell { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoCellCopyWith<_MemoCell> get copyWith => - __$MemoCellCopyWithImpl<_MemoCell>(this, _$identity); + _$MemoCellCopyWith<_MemoCell> get copyWith => __$MemoCellCopyWithImpl<_MemoCell>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _MemoCell && - (identical(other.cellType, cellType) || - other.cellType == cellType) && + (identical(other.cellType, cellType) || other.cellType == cellType) && (identical(other.value, value) || other.value == value)); } @@ -270,10 +265,8 @@ class _MemoCell implements MemoCell { } /// @nodoc -abstract mixin class _$MemoCellCopyWith<$Res> - implements $MemoCellCopyWith<$Res> { - factory _$MemoCellCopyWith(_MemoCell value, $Res Function(_MemoCell) _then) = - __$MemoCellCopyWithImpl; +abstract mixin class _$MemoCellCopyWith<$Res> implements $MemoCellCopyWith<$Res> { + factory _$MemoCellCopyWith(_MemoCell value, $Res Function(_MemoCell) _then) = __$MemoCellCopyWithImpl; @override @useResult $Res call({String cellType, String value}); @@ -315,20 +308,15 @@ mixin _$MemoRow { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoRowCopyWith get copyWith => - _$MemoRowCopyWithImpl(this as MemoRow, _$identity); + $MemoRowCopyWith get copyWith => _$MemoRowCopyWithImpl(this as MemoRow, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is MemoRow && - const DeepCollectionEquality().equals(other.cells, cells)); + return identical(this, other) || (other.runtimeType == runtimeType && other is MemoRow && const DeepCollectionEquality().equals(other.cells, cells)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(cells)); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(cells)); @override String toString() { @@ -338,8 +326,7 @@ mixin _$MemoRow { /// @nodoc abstract mixin class $MemoRowCopyWith<$Res> { - factory $MemoRowCopyWith(MemoRow value, $Res Function(MemoRow) _then) = - _$MemoRowCopyWithImpl; + factory $MemoRowCopyWith(MemoRow value, $Res Function(MemoRow) _then) = _$MemoRowCopyWithImpl; @useResult $Res call({List cells}); } @@ -538,20 +525,15 @@ class _MemoRow implements MemoRow { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoRowCopyWith<_MemoRow> get copyWith => - __$MemoRowCopyWithImpl<_MemoRow>(this, _$identity); + _$MemoRowCopyWith<_MemoRow> get copyWith => __$MemoRowCopyWithImpl<_MemoRow>(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _MemoRow && - const DeepCollectionEquality().equals(other._cells, _cells)); + return identical(this, other) || (other.runtimeType == runtimeType && other is _MemoRow && const DeepCollectionEquality().equals(other._cells, _cells)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(_cells)); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_cells)); @override String toString() { @@ -561,8 +543,7 @@ class _MemoRow implements MemoRow { /// @nodoc abstract mixin class _$MemoRowCopyWith<$Res> implements $MemoRowCopyWith<$Res> { - factory _$MemoRowCopyWith(_MemoRow value, $Res Function(_MemoRow) _then) = - __$MemoRowCopyWithImpl; + factory _$MemoRowCopyWith(_MemoRow value, $Res Function(_MemoRow) _then) = __$MemoRowCopyWithImpl; @override @useResult $Res call({List cells}); @@ -601,8 +582,7 @@ mixin _$MemoSection { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoSectionCopyWith get copyWith => - _$MemoSectionCopyWithImpl(this as MemoSection, _$identity); + $MemoSectionCopyWith get copyWith => _$MemoSectionCopyWithImpl(this as MemoSection, _$identity); @override bool operator ==(Object other) { @@ -615,11 +595,7 @@ mixin _$MemoSection { } @override - int get hashCode => Object.hash( - runtimeType, - title, - const DeepCollectionEquality().hash(headers), - const DeepCollectionEquality().hash(rows)); + int get hashCode => Object.hash(runtimeType, title, const DeepCollectionEquality().hash(headers), const DeepCollectionEquality().hash(rows)); @override String toString() { @@ -629,9 +605,7 @@ mixin _$MemoSection { /// @nodoc abstract mixin class $MemoSectionCopyWith<$Res> { - factory $MemoSectionCopyWith( - MemoSection value, $Res Function(MemoSection) _then) = - _$MemoSectionCopyWithImpl; + factory $MemoSectionCopyWith(MemoSection value, $Res Function(MemoSection) _then) = _$MemoSectionCopyWithImpl; @useResult $Res call({String title, List headers, List rows}); } @@ -760,8 +734,7 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult maybeWhen( - TResult Function(String title, List headers, List rows)? - $default, { + TResult Function(String title, List headers, List rows)? $default, { required TResult orElse(), }) { final _that = this; @@ -788,8 +761,7 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult when( - TResult Function(String title, List headers, List rows) - $default, + TResult Function(String title, List headers, List rows) $default, ) { final _that = this; switch (_that) { @@ -812,8 +784,7 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String title, List headers, List rows)? - $default, + TResult? Function(String title, List headers, List rows)? $default, ) { final _that = this; switch (_that) { @@ -828,10 +799,7 @@ extension MemoSectionPatterns on MemoSection { /// @nodoc class _MemoSection implements MemoSection { - const _MemoSection( - {required this.title, - required final List headers, - required final List rows}) + const _MemoSection({required this.title, required final List headers, required final List rows}) : _headers = headers, _rows = rows; @@ -858,8 +826,7 @@ class _MemoSection implements MemoSection { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoSectionCopyWith<_MemoSection> get copyWith => - __$MemoSectionCopyWithImpl<_MemoSection>(this, _$identity); + _$MemoSectionCopyWith<_MemoSection> get copyWith => __$MemoSectionCopyWithImpl<_MemoSection>(this, _$identity); @override bool operator ==(Object other) { @@ -872,11 +839,7 @@ class _MemoSection implements MemoSection { } @override - int get hashCode => Object.hash( - runtimeType, - title, - const DeepCollectionEquality().hash(_headers), - const DeepCollectionEquality().hash(_rows)); + int get hashCode => Object.hash(runtimeType, title, const DeepCollectionEquality().hash(_headers), const DeepCollectionEquality().hash(_rows)); @override String toString() { @@ -885,11 +848,8 @@ class _MemoSection implements MemoSection { } /// @nodoc -abstract mixin class _$MemoSectionCopyWith<$Res> - implements $MemoSectionCopyWith<$Res> { - factory _$MemoSectionCopyWith( - _MemoSection value, $Res Function(_MemoSection) _then) = - __$MemoSectionCopyWithImpl; +abstract mixin class _$MemoSectionCopyWith<$Res> implements $MemoSectionCopyWith<$Res> { + factory _$MemoSectionCopyWith(_MemoSection value, $Res Function(_MemoSection) _then) = __$MemoSectionCopyWithImpl; @override @useResult $Res call({String title, List headers, List rows}); @@ -943,8 +903,7 @@ mixin _$PluginInfo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $PluginInfoCopyWith get copyWith => - _$PluginInfoCopyWithImpl(this as PluginInfo, _$identity); + $PluginInfoCopyWith get copyWith => _$PluginInfoCopyWithImpl(this as PluginInfo, _$identity); @override bool operator ==(Object other) { @@ -955,24 +914,14 @@ mixin _$PluginInfo { (identical(other.name, name) || other.name == name) && (identical(other.version, version) || other.version == version) && (identical(other.author, author) || other.author == author) && - (identical(other.description, description) || - other.description == description) && + (identical(other.description, description) || other.description == description) && (identical(other.enabled, enabled) || other.enabled == enabled) && const DeepCollectionEquality().equals(other.types, types) && - const DeepCollectionEquality() - .equals(other.memoPrefixes, memoPrefixes)); + const DeepCollectionEquality().equals(other.memoPrefixes, memoPrefixes)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - name, - version, - author, - description, - enabled, - const DeepCollectionEquality().hash(types), + int get hashCode => Object.hash(runtimeType, id, name, version, author, description, enabled, const DeepCollectionEquality().hash(types), const DeepCollectionEquality().hash(memoPrefixes)); @override @@ -983,19 +932,9 @@ mixin _$PluginInfo { /// @nodoc abstract mixin class $PluginInfoCopyWith<$Res> { - factory $PluginInfoCopyWith( - PluginInfo value, $Res Function(PluginInfo) _then) = - _$PluginInfoCopyWithImpl; + factory $PluginInfoCopyWith(PluginInfo value, $Res Function(PluginInfo) _then) = _$PluginInfoCopyWithImpl; @useResult - $Res call( - {String id, - String name, - String version, - String? author, - String? description, - bool enabled, - List types, - List memoPrefixes}); + $Res call({String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes}); } /// @nodoc @@ -1147,23 +1086,14 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult maybeWhen( - TResult Function( - String id, - String name, - String version, - String? author, - String? description, - bool enabled, - List types, - List memoPrefixes)? + TResult Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _PluginInfo() when $default != null: - return $default(_that.id, _that.name, _that.version, _that.author, - _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); case _: return orElse(); } @@ -1184,22 +1114,13 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult when( - TResult Function( - String id, - String name, - String version, - String? author, - String? description, - bool enabled, - List types, - List memoPrefixes) + TResult Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes) $default, ) { final _that = this; switch (_that) { case _PluginInfo(): - return $default(_that.id, _that.name, _that.version, _that.author, - _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); } } @@ -1217,22 +1138,13 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - String id, - String name, - String version, - String? author, - String? description, - bool enabled, - List types, - List memoPrefixes)? + TResult? Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes)? $default, ) { final _that = this; switch (_that) { case _PluginInfo() when $default != null: - return $default(_that.id, _that.name, _that.version, _that.author, - _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); case _: return null; } @@ -1287,8 +1199,7 @@ class _PluginInfo implements PluginInfo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$PluginInfoCopyWith<_PluginInfo> get copyWith => - __$PluginInfoCopyWithImpl<_PluginInfo>(this, _$identity); + _$PluginInfoCopyWith<_PluginInfo> get copyWith => __$PluginInfoCopyWithImpl<_PluginInfo>(this, _$identity); @override bool operator ==(Object other) { @@ -1299,24 +1210,14 @@ class _PluginInfo implements PluginInfo { (identical(other.name, name) || other.name == name) && (identical(other.version, version) || other.version == version) && (identical(other.author, author) || other.author == author) && - (identical(other.description, description) || - other.description == description) && + (identical(other.description, description) || other.description == description) && (identical(other.enabled, enabled) || other.enabled == enabled) && const DeepCollectionEquality().equals(other._types, _types) && - const DeepCollectionEquality() - .equals(other._memoPrefixes, _memoPrefixes)); + const DeepCollectionEquality().equals(other._memoPrefixes, _memoPrefixes)); } @override - int get hashCode => Object.hash( - runtimeType, - id, - name, - version, - author, - description, - enabled, - const DeepCollectionEquality().hash(_types), + int get hashCode => Object.hash(runtimeType, id, name, version, author, description, enabled, const DeepCollectionEquality().hash(_types), const DeepCollectionEquality().hash(_memoPrefixes)); @override @@ -1326,22 +1227,11 @@ class _PluginInfo implements PluginInfo { } /// @nodoc -abstract mixin class _$PluginInfoCopyWith<$Res> - implements $PluginInfoCopyWith<$Res> { - factory _$PluginInfoCopyWith( - _PluginInfo value, $Res Function(_PluginInfo) _then) = - __$PluginInfoCopyWithImpl; +abstract mixin class _$PluginInfoCopyWith<$Res> implements $PluginInfoCopyWith<$Res> { + factory _$PluginInfoCopyWith(_PluginInfo value, $Res Function(_PluginInfo) _then) = __$PluginInfoCopyWithImpl; @override @useResult - $Res call( - {String id, - String name, - String version, - String? author, - String? description, - bool enabled, - List types, - List memoPrefixes}); + $Res call({String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes}); } /// @nodoc diff --git a/lib/src/rust/api/raptor.dart b/lib/src/rust/api/raptor.dart index 584e6f953..3b63c3c07 100644 --- a/lib/src/rust/api/raptor.dart +++ b/lib/src/rust/api/raptor.dart @@ -8,15 +8,11 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `ec_level_of` -Future> encode( - {required String path, required RaptorQParams params}) => - RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); +Future> encode({required String path, required RaptorQParams params}) => RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); -Uint8List getQrBytes({required List data}) => - RustLib.instance.api.crateApiRaptorGetQrBytes(data: data); +Uint8List getQrBytes({required List data}) => RustLib.instance.api.crateApiRaptorGetQrBytes(data: data); -Future decode({required List packet}) => - RustLib.instance.api.crateApiRaptorDecode(packet: packet); +Future decode({required List packet}) => RustLib.instance.api.crateApiRaptorDecode(packet: packet); Future endDecode() => RustLib.instance.api.crateApiRaptorEndDecode(); @@ -37,9 +33,5 @@ class RaptorQParams { @override bool operator ==(Object other) => identical(this, other) || - other is RaptorQParams && - runtimeType == other.runtimeType && - version == other.version && - ecLevel == other.ecLevel && - repair == other.repair; + other is RaptorQParams && runtimeType == other.runtimeType && version == other.version && ecLevel == other.ecLevel && repair == other.repair; } diff --git a/lib/src/rust/api/sapling.dart b/lib/src/rust/api/sapling.dart index dfc524efd..9a154871b 100644 --- a/lib/src/rust/api/sapling.dart +++ b/lib/src/rust/api/sapling.dart @@ -9,15 +9,13 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `download_and_verify`, `resolve_params_dir`, `set_sapling_params_dir` /// Check whether Sapling parameters are already on disk. -SaplingParamsStatus checkSaplingParams() => - RustLib.instance.api.crateApiSaplingCheckSaplingParams(); +SaplingParamsStatus checkSaplingParams() => RustLib.instance.api.crateApiSaplingCheckSaplingParams(); /// Download Sapling parameters from the z.cash download server. /// /// Verifies file size and Blake2b hash upon download. /// Safe to call even if they are already downloaded (no-op if valid). -Future downloadSaplingParams() => - RustLib.instance.api.crateApiSaplingDownloadSaplingParams(); +Future downloadSaplingParams() => RustLib.instance.api.crateApiSaplingDownloadSaplingParams(); /// Status of the Sapling proving parameters on disk. class SaplingParamsStatus { @@ -32,8 +30,5 @@ class SaplingParamsStatus { @override bool operator ==(Object other) => - identical(this, other) || - other is SaplingParamsStatus && - runtimeType == other.runtimeType && - downloaded == other.downloaded; + identical(this, other) || other is SaplingParamsStatus && runtimeType == other.runtimeType && downloaded == other.downloaded; } diff --git a/lib/src/rust/api/sweep.dart b/lib/src/rust/api/sweep.dart index 3b11052b8..19c7ce2aa 100644 --- a/lib/src/rust/api/sweep.dart +++ b/lib/src/rust/api/sweep.dart @@ -12,9 +12,7 @@ abstract class TransparentScanner implements RustOpaqueInterface { Future cancel(); // HINT: Make it `#[frb(sync)]` to let it become the default constructor of Dart class. - static Future newInstance() => - RustLib.instance.api.crateApiSweepTransparentScannerNew(); + static Future newInstance() => RustLib.instance.api.crateApiSweepTransparentScannerNew(); - Stream run( - {required int endHeight, required int gapLimit, required Coin c}); + Stream run({required int endHeight, required int gapLimit, required Coin c}); } diff --git a/lib/src/rust/api/sync.dart b/lib/src/rust/api/sync.dart index 2e19f76a8..d9c1cf6db 100644 --- a/lib/src/rust/api/sync.dart +++ b/lib/src/rust/api/sync.dart @@ -27,24 +27,18 @@ Stream synchronize( fast: fast, c: c); -Future balance({required Coin c}) => - RustLib.instance.api.crateApiSyncBalance(c: c); +Future balance({required Coin c}) => RustLib.instance.api.crateApiSyncBalance(c: c); Future cancelSync() => RustLib.instance.api.crateApiSyncCancelSync(); -Future rewindSync( - {required int height, required int account, required Coin c}) => - RustLib.instance.api - .crateApiSyncRewindSync(height: height, account: account, c: c); +Future rewindSync({required int height, required int account, required Coin c}) => + RustLib.instance.api.crateApiSyncRewindSync(height: height, account: account, c: c); -Future getDbHeight({required Coin c}) => - RustLib.instance.api.crateApiSyncGetDbHeight(c: c); +Future getDbHeight({required Coin c}) => RustLib.instance.api.crateApiSyncGetDbHeight(c: c); -Future fetchTxDetails({required int account, required Coin c}) => - RustLib.instance.api.crateApiSyncFetchTxDetails(account: account, c: c); +Future fetchTxDetails({required int account, required Coin c}) => RustLib.instance.api.crateApiSyncFetchTxDetails(account: account, c: c); -Future cacheBlockTime({required int height, required Coin c}) => - RustLib.instance.api.crateApiSyncCacheBlockTime(height: height, c: c); +Future cacheBlockTime({required int height, required Coin c}) => RustLib.instance.api.crateApiSyncCacheBlockTime(height: height, c: c); class PoolBalance { final Uint64List field0; @@ -57,11 +51,7 @@ class PoolBalance { int get hashCode => field0.hashCode; @override - bool operator ==(Object other) => - identical(this, other) || - other is PoolBalance && - runtimeType == other.runtimeType && - field0 == other.field0; + bool operator ==(Object other) => identical(this, other) || other is PoolBalance && runtimeType == other.runtimeType && field0 == other.field0; } class SyncProgress { @@ -78,9 +68,5 @@ class SyncProgress { @override bool operator ==(Object other) => - identical(this, other) || - other is SyncProgress && - runtimeType == other.runtimeType && - height == other.height && - time == other.time; + identical(this, other) || other is SyncProgress && runtimeType == other.runtimeType && height == other.height && time == other.time; } diff --git a/lib/src/rust/api/transaction.dart b/lib/src/rust/api/transaction.dart index a3eb4e2ce..2281ceff3 100644 --- a/lib/src/rust/api/transaction.dart +++ b/lib/src/rust/api/transaction.dart @@ -7,36 +7,22 @@ import '../frb_generated.dart'; import 'coin.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -Future fillMissingTxPrices( - {required String api, required String currency, required Coin c}) => - RustLib.instance.api.crateApiTransactionFillMissingTxPrices( - api: api, currency: currency, c: c); - -Future updateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}) => - RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices( - currency: currency, exchangeRate: exchangeRate, c: c); +Future fillMissingTxPrices({required String api, required String currency, required Coin c}) => + RustLib.instance.api.crateApiTransactionFillMissingTxPrices(api: api, currency: currency, c: c); + +Future updateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}) => + RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices(currency: currency, exchangeRate: exchangeRate, c: c); Future setUserMemo({required int idTx, String? memo, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetUserMemo(idTx: idTx, memo: memo, c: c); + RustLib.instance.api.crateApiTransactionSetUserMemo(idTx: idTx, memo: memo, c: c); Future setTxCategory({required int id, int? category, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetTxCategory(id: id, category: category, c: c); - -Future setTxPrice({required int id, double? price, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetTxPrice(id: id, price: price, c: c); - -Future> fetchCategoryAmounts( - {int? from, int? to, required Coin c}) => - RustLib.instance.api - .crateApiTransactionFetchCategoryAmounts(from: from, to: to, c: c); - -Future> fetchAmounts( - {int? from, int? to, required int category, required Coin c}) => - RustLib.instance.api.crateApiTransactionFetchAmounts( - from: from, to: to, category: category, c: c); + RustLib.instance.api.crateApiTransactionSetTxCategory(id: id, category: category, c: c); + +Future setTxPrice({required int id, double? price, required Coin c}) => RustLib.instance.api.crateApiTransactionSetTxPrice(id: id, price: price, c: c); + +Future> fetchCategoryAmounts({int? from, int? to, required Coin c}) => + RustLib.instance.api.crateApiTransactionFetchCategoryAmounts(from: from, to: to, c: c); + +Future> fetchAmounts({int? from, int? to, required int category, required Coin c}) => + RustLib.instance.api.crateApiTransactionFetchAmounts(from: from, to: to, category: category, c: c); diff --git a/lib/src/rust/api/vault.dart b/lib/src/rust/api/vault.dart index 749ed9dab..4dbc93860 100644 --- a/lib/src/rust/api/vault.dart +++ b/lib/src/rust/api/vault.dart @@ -8,28 +8,17 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` -Future initVault( - {required FutureOr Function(Uint8List) append}) => - RustLib.instance.api.crateApiVaultInitVault(append: append); +Future initVault({required FutureOr Function(Uint8List) append}) => RustLib.instance.api.crateApiVaultInitVault(append: append); // Rust type: RustOpaqueMoi> abstract class DartVault implements RustOpaqueInterface { - Future> recover( - {required List vaultBytes, required String masterPassword}); + Future> recover({required List vaultBytes, required String masterPassword}); - Future> recoverWithPrf( - {required List vaultBytes, - required String deviceIdStr, - required List prfOutput}); + Future> recoverWithPrf({required List vaultBytes, required String deviceIdStr, required List prfOutput}); - Future registerDevice( - {required List initBytes, - required String masterPassword, - required String deviceIdStr, - required List prfOutput}); + Future registerDevice({required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}); - Future setMasterPassword( - {String? oldPassword, required String newPassword, Uint8List? oldBytes}); + Future setMasterPassword({String? oldPassword, required String newPassword, Uint8List? oldBytes}); Future storeAccount( {required int timestamp, @@ -61,13 +50,7 @@ class RestoredAccount { }); @override - int get hashCode => - timestamp.hashCode ^ - name.hashCode ^ - seed.hashCode ^ - aindex.hashCode ^ - useInternal.hashCode ^ - birthHeight.hashCode; + int get hashCode => timestamp.hashCode ^ name.hashCode ^ seed.hashCode ^ aindex.hashCode ^ useInternal.hashCode ^ birthHeight.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/zsa.dart b/lib/src/rust/api/zsa.dart index a8ade42f8..fd7aaa061 100644 --- a/lib/src/rust/api/zsa.dart +++ b/lib/src/rust/api/zsa.dart @@ -11,23 +11,17 @@ part 'zsa.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`, `from` -Future> listZsaHoldings({required Coin c}) => - RustLib.instance.api.crateApiZsaListZsaHoldings(c: c); +Future> listZsaHoldings({required Coin c}) => RustLib.instance.api.crateApiZsaListZsaHoldings(c: c); /// Set or update the human-readable name for a ZSA asset. /// Pass an empty string to clear the name (reverting to the hex fallback display). -Future setAssetName( - {required PlatformInt64 idAsset, - required String name, - required Coin c}) => - RustLib.instance.api - .crateApiZsaSetAssetName(idAsset: idAsset, name: name, c: c); +Future setAssetName({required PlatformInt64 idAsset, required String name, required Coin c}) => + RustLib.instance.api.crateApiZsaSetAssetName(idAsset: idAsset, name: name, c: c); /// Check whether ZSA (Zcash Shielded Assets) is available on the current network. /// /// ZSA is enabled when the network's [`OrchardMode`] is set to [`OrchardMode::Zsa`]. -Future isZsaAvailable({required Coin c}) => - RustLib.instance.api.crateApiZsaIsZsaAvailable(c: c); +Future isZsaAvailable({required Coin c}) => RustLib.instance.api.crateApiZsaIsZsaAvailable(c: c); /// A ZSA token holding representing a balance of a specific asset. @freezed diff --git a/lib/src/rust/api/zsa.freezed.dart b/lib/src/rust/api/zsa.freezed.dart index 921cf9e94..ce3e0f66d 100644 --- a/lib/src/rust/api/zsa.freezed.dart +++ b/lib/src/rust/api/zsa.freezed.dart @@ -27,8 +27,7 @@ mixin _$ZsaHolding { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ZsaHoldingCopyWith get copyWith => - _$ZsaHoldingCopyWithImpl(this as ZsaHolding, _$identity); + $ZsaHoldingCopyWith get copyWith => _$ZsaHoldingCopyWithImpl(this as ZsaHolding, _$identity); @override bool operator ==(Object other) { @@ -36,30 +35,18 @@ mixin _$ZsaHolding { (other.runtimeType == runtimeType && other is ZsaHolding && (identical(other.idAsset, idAsset) || other.idAsset == idAsset) && - const DeepCollectionEquality() - .equals(other.assetDescHash, assetDescHash) && - (identical(other.assetName, assetName) || - other.assetName == assetName) && + const DeepCollectionEquality().equals(other.assetDescHash, assetDescHash) && + (identical(other.assetName, assetName) || other.assetName == assetName) && const DeepCollectionEquality().equals(other.ik, ik) && const DeepCollectionEquality().equals(other.assetBase, assetBase) && - (identical(other.finalized, finalized) || - other.finalized == finalized) && - (identical(other.firstSeenHeight, firstSeenHeight) || - other.firstSeenHeight == firstSeenHeight) && + (identical(other.finalized, finalized) || other.finalized == finalized) && + (identical(other.firstSeenHeight, firstSeenHeight) || other.firstSeenHeight == firstSeenHeight) && (identical(other.balance, balance) || other.balance == balance)); } @override - int get hashCode => Object.hash( - runtimeType, - idAsset, - const DeepCollectionEquality().hash(assetDescHash), - assetName, - const DeepCollectionEquality().hash(ik), - const DeepCollectionEquality().hash(assetBase), - finalized, - firstSeenHeight, - balance); + int get hashCode => Object.hash(runtimeType, idAsset, const DeepCollectionEquality().hash(assetDescHash), assetName, const DeepCollectionEquality().hash(ik), + const DeepCollectionEquality().hash(assetBase), finalized, firstSeenHeight, balance); @override String toString() { @@ -69,9 +56,7 @@ mixin _$ZsaHolding { /// @nodoc abstract mixin class $ZsaHoldingCopyWith<$Res> { - factory $ZsaHoldingCopyWith( - ZsaHolding value, $Res Function(ZsaHolding) _then) = - _$ZsaHoldingCopyWithImpl; + factory $ZsaHoldingCopyWith(ZsaHolding value, $Res Function(ZsaHolding) _then) = _$ZsaHoldingCopyWithImpl; @useResult $Res call( {PlatformInt64 idAsset, @@ -233,14 +218,7 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult maybeWhen( - TResult Function( - PlatformInt64 idAsset, - Uint8List assetDescHash, - String assetName, - Uint8List ik, - Uint8List assetBase, - bool finalized, - int firstSeenHeight, + TResult Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, BigInt balance)? $default, { required TResult orElse(), @@ -248,15 +226,7 @@ extension ZsaHoldingPatterns on ZsaHolding { final _that = this; switch (_that) { case _ZsaHolding() when $default != null: - return $default( - _that.idAsset, - _that.assetDescHash, - _that.assetName, - _that.ik, - _that.assetBase, - _that.finalized, - _that.firstSeenHeight, - _that.balance); + return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); case _: return orElse(); } @@ -277,29 +247,14 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult when( - TResult Function( - PlatformInt64 idAsset, - Uint8List assetDescHash, - String assetName, - Uint8List ik, - Uint8List assetBase, - bool finalized, - int firstSeenHeight, + TResult Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, BigInt balance) $default, ) { final _that = this; switch (_that) { case _ZsaHolding(): - return $default( - _that.idAsset, - _that.assetDescHash, - _that.assetName, - _that.ik, - _that.assetBase, - _that.finalized, - _that.firstSeenHeight, - _that.balance); + return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); } } @@ -317,29 +272,14 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - PlatformInt64 idAsset, - Uint8List assetDescHash, - String assetName, - Uint8List ik, - Uint8List assetBase, - bool finalized, - int firstSeenHeight, + TResult? Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, BigInt balance)? $default, ) { final _that = this; switch (_that) { case _ZsaHolding() when $default != null: - return $default( - _that.idAsset, - _that.assetDescHash, - _that.assetName, - _that.ik, - _that.assetBase, - _that.finalized, - _that.firstSeenHeight, - _that.balance); + return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); case _: return null; } @@ -381,8 +321,7 @@ class _ZsaHolding implements ZsaHolding { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ZsaHoldingCopyWith<_ZsaHolding> get copyWith => - __$ZsaHoldingCopyWithImpl<_ZsaHolding>(this, _$identity); + _$ZsaHoldingCopyWith<_ZsaHolding> get copyWith => __$ZsaHoldingCopyWithImpl<_ZsaHolding>(this, _$identity); @override bool operator ==(Object other) { @@ -390,30 +329,18 @@ class _ZsaHolding implements ZsaHolding { (other.runtimeType == runtimeType && other is _ZsaHolding && (identical(other.idAsset, idAsset) || other.idAsset == idAsset) && - const DeepCollectionEquality() - .equals(other.assetDescHash, assetDescHash) && - (identical(other.assetName, assetName) || - other.assetName == assetName) && + const DeepCollectionEquality().equals(other.assetDescHash, assetDescHash) && + (identical(other.assetName, assetName) || other.assetName == assetName) && const DeepCollectionEquality().equals(other.ik, ik) && const DeepCollectionEquality().equals(other.assetBase, assetBase) && - (identical(other.finalized, finalized) || - other.finalized == finalized) && - (identical(other.firstSeenHeight, firstSeenHeight) || - other.firstSeenHeight == firstSeenHeight) && + (identical(other.finalized, finalized) || other.finalized == finalized) && + (identical(other.firstSeenHeight, firstSeenHeight) || other.firstSeenHeight == firstSeenHeight) && (identical(other.balance, balance) || other.balance == balance)); } @override - int get hashCode => Object.hash( - runtimeType, - idAsset, - const DeepCollectionEquality().hash(assetDescHash), - assetName, - const DeepCollectionEquality().hash(ik), - const DeepCollectionEquality().hash(assetBase), - finalized, - firstSeenHeight, - balance); + int get hashCode => Object.hash(runtimeType, idAsset, const DeepCollectionEquality().hash(assetDescHash), assetName, const DeepCollectionEquality().hash(ik), + const DeepCollectionEquality().hash(assetBase), finalized, firstSeenHeight, balance); @override String toString() { @@ -422,11 +349,8 @@ class _ZsaHolding implements ZsaHolding { } /// @nodoc -abstract mixin class _$ZsaHoldingCopyWith<$Res> - implements $ZsaHoldingCopyWith<$Res> { - factory _$ZsaHoldingCopyWith( - _ZsaHolding value, $Res Function(_ZsaHolding) _then) = - __$ZsaHoldingCopyWithImpl; +abstract mixin class _$ZsaHoldingCopyWith<$Res> implements $ZsaHoldingCopyWith<$Res> { + factory _$ZsaHoldingCopyWith(_ZsaHolding value, $Res Function(_ZsaHolding) _then) = __$ZsaHoldingCopyWithImpl; @override @useResult $Res call( diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index e9b24589b..57fce034f 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -27,8 +27,7 @@ import 'api/zsa.dart'; import 'dart:async'; import 'dart:convert'; import 'frb_generated.dart'; -import 'frb_generated.io.dart' - if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; import 'io.dart'; import 'lib.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; @@ -73,12 +72,10 @@ class RustLib extends BaseEntrypoint { static void dispose() => instance.disposeImpl(); @override - ApiImplConstructor get apiImplConstructor => - RustLibApiImpl.new; + ApiImplConstructor get apiImplConstructor => RustLibApiImpl.new; @override - WireConstructor get wireConstructor => - RustLibWire.fromExternalLibrary; + WireConstructor get wireConstructor => RustLibWire.fromExternalLibrary; @override Future executeRustInitializers() async { @@ -87,8 +84,7 @@ class RustLib extends BaseEntrypoint { } @override - ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => - kDefaultExternalLibraryLoaderConfig; + ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => kDefaultExternalLibraryLoaderConfig; @override String get codegenVersion => '2.12.0'; @@ -96,8 +92,7 @@ class RustLib extends BaseEntrypoint { @override int get rustContentHash => -492919685; - static const kDefaultExternalLibraryLoaderConfig = - ExternalLibraryLoaderConfig( + static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( stem: 'rlz', ioDirectory: 'rust/target/release/', webPrefix: 'pkg/', @@ -106,29 +101,15 @@ class RustLib extends BaseEntrypoint { } abstract class RustLibApi extends BaseApi { - Future> crateApiVaultDartVaultRecover( - {required DartVault that, - required List vaultBytes, - required String masterPassword}); + Future> crateApiVaultDartVaultRecover({required DartVault that, required List vaultBytes, required String masterPassword}); Future> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, - required List vaultBytes, - required String deviceIdStr, - required List prfOutput}); + {required DartVault that, required List vaultBytes, required String deviceIdStr, required List prfOutput}); Future crateApiVaultDartVaultRegisterDevice( - {required DartVault that, - required List initBytes, - required String masterPassword, - required String deviceIdStr, - required List prfOutput}); + {required DartVault that, required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}); - Future crateApiVaultDartVaultSetMasterPassword( - {required DartVault that, - String? oldPassword, - required String newPassword, - Uint8List? oldBytes}); + Future crateApiVaultDartVaultSetMasterPassword({required DartVault that, String? oldPassword, required String newPassword, Uint8List? oldBytes}); Future crateApiVaultDartVaultStoreAccount( {required DartVault that, @@ -146,49 +127,33 @@ abstract class RustLibApi extends BaseApi { Mempool crateApiMempoolMempoolNew(); - Stream crateApiMempoolMempoolRun( - {required Mempool that, required Coin c}); + Stream crateApiMempoolMempoolRun({required Mempool that, required Coin c}); - Future crateApiMigrateNoteMigrationCancel( - {required NoteMigration that}); + Future crateApiMigrateNoteMigrationCancel({required NoteMigration that}); NoteMigration crateApiMigrateNoteMigrationNew(); - Stream crateApiMigrateNoteMigrationRun( - {required NoteMigration that, - required Coin c, - required BigInt meanDelayMs}); + Stream crateApiMigrateNoteMigrationRun({required NoteMigration that, required Coin c, required BigInt meanDelayMs}); - Future crateApiSweepTransparentScannerCancel( - {required TransparentScanner that}); + Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}); Future crateApiSweepTransparentScannerNew(); - Stream crateApiSweepTransparentScannerRun( - {required TransparentScanner that, - required int endHeight, - required int gapLimit, - required Coin c}); + Stream crateApiSweepTransparentScannerRun({required TransparentScanner that, required int endHeight, required int gapLimit, required Coin c}); Future crateApiSyncBalance({required Coin c}); - Future crateApiPayBroadcastTransaction( - {required int height, required List txBytes, required Coin c}); + Future crateApiPayBroadcastTransaction({required int height, required List txBytes, required Coin c}); Future crateApiPayBuildPuri({required List recipients}); - Future crateApiSyncCacheBlockTime( - {required int height, required Coin c}); + Future crateApiSyncCacheBlockTime({required int height, required Coin c}); Future crateApiFrostCancelDkg({required Coin c}); Future crateApiSyncCancelSync(); - Future crateApiDbChangeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}); + Future crateApiDbChangeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}); SaplingParamsStatus crateApiSaplingCheckSaplingParams(); @@ -198,45 +163,31 @@ abstract class RustLibApi extends BaseApi { Coin crateApiCoinCoinNew({int? defaultCoin}); - Future crateApiCoinCoinOpenDatabase( - {required Coin that, required String dbFilepath, String? password}); + Future crateApiCoinCoinOpenDatabase({required Coin that, required String dbFilepath, String? password}); - Future crateApiCoinCoinSetAccount( - {required Coin that, required int account}); + Future crateApiCoinCoinSetAccount({required Coin that, required int account}); - Coin crateApiCoinCoinSetLwd( - {required Coin that, required int serverType, required String url}); + Coin crateApiCoinCoinSetLwd({required Coin that, required int serverType, required String url}); Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}); - Future crateApiCoinCoinSetUseTor( - {required Coin that, required bool useTor}); + Future crateApiCoinCoinSetUseTor({required Coin that, required bool useTor}); - Future crateApiContactsCreateContact( - {required String name, - required List addresses, - required String notes, - required Coin c}); + Future crateApiContactsCreateContact({required String name, required List addresses, required String notes, required Coin c}); - Future crateApiAccountCreateNewCategory( - {required Category category, required Coin c}); + Future crateApiAccountCreateNewCategory({required Category category, required Coin c}); - Future crateApiAccountCreateNewFolder( - {required String name, required Coin c}); + Future crateApiAccountCreateNewFolder({required String name, required Coin c}); Future crateApiRaptorDecode({required List packet}); - Future crateApiAccountDeleteAccount( - {required int account, required Coin c}); + Future crateApiAccountDeleteAccount({required int account, required Coin c}); - Future crateApiAccountDeleteCategories( - {required List ids, required Coin c}); + Future crateApiAccountDeleteCategories({required List ids, required Coin c}); - Future crateApiContactsDeleteContacts( - {required List ids, required Coin c}); + Future crateApiContactsDeleteContacts({required List ids, required Coin c}); - Future crateApiAccountDeleteFolders( - {required List ids, required Coin c}); + Future crateApiAccountDeleteFolders({required List ids, required Coin c}); Stream crateApiFrostDoDkg({required Coin c}); @@ -246,39 +197,29 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountDummyExport({required SigningEvent a}); - Future> crateApiRaptorEncode( - {required String path, required RaptorQParams params}); + Future> crateApiRaptorEncode({required String path, required RaptorQParams params}); Future crateApiRaptorEndDecode(); - Future crateApiAccountExportAccount( - {required int id, required String passphrase, required Coin c}); + Future crateApiAccountExportAccount({required int id, required String passphrase, required Coin c}); Future crateApiContactsExportContactsVcard({required Coin c}); - Future crateApiPayExtractTransaction( - {required PcztPackage package}); + Future crateApiPayExtractTransaction({required PcztPackage package}); - Future> crateApiAccountFetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}); + Future> crateApiAccountFetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}); - Future> crateApiTransactionFetchAmounts( - {int? from, int? to, required int category, required Coin c}); + Future> crateApiTransactionFetchAmounts({int? from, int? to, required int category, required Coin c}); - Future> crateApiTransactionFetchCategoryAmounts( - {int? from, int? to, required Coin c}); + Future> crateApiTransactionFetchCategoryAmounts({int? from, int? to, required Coin c}); - Future> crateApiAccountFetchTransparentAddressTxCount( - {required Coin c}); + Future> crateApiAccountFetchTransparentAddressTxCount({required Coin c}); - Future crateApiSyncFetchTxDetails( - {required int account, required Coin c}); + Future crateApiSyncFetchTxDetails({required int account, required Coin c}); - Future crateApiTransactionFillMissingTxPrices( - {required String api, required String currency, required Coin c}); + Future crateApiTransactionFillMissingTxPrices({required String api, required String currency, required Coin c}); - Future> crateApiContactsFindContactsForAddress( - {required String address, required Coin c}); + Future> crateApiContactsFindContactsForAddress({required String address, required Coin c}); Future crateApiFrostFrostSignParamsDefault(); @@ -288,28 +229,21 @@ abstract class RustLibApi extends BaseApi { String crateApiKeyGenerateSeed(); - Future crateApiAccountGetAccountAddresses( - {required int account, required int uaPools, required Coin c}); + Future crateApiAccountGetAccountAddresses({required int account, required int uaPools, required Coin c}); - Future crateApiAccountGetAccountFingerprint( - {required int account, required Coin c}); + Future crateApiAccountGetAccountFingerprint({required int account, required Coin c}); Future crateApiAccountGetAccountFrostParams({required Coin c}); - Future crateApiAccountGetAccountPools( - {required int account, required Coin c}); + Future crateApiAccountGetAccountPools({required int account, required Coin c}); - Future crateApiAccountGetAccountSeed( - {required int account, required Coin c}); + Future crateApiAccountGetAccountSeed({required int account, required Coin c}); - Future crateApiAccountGetAccountUfvk( - {required int account, required int pools, required Coin c}); + Future crateApiAccountGetAccountUfvk({required int account, required int pools, required Coin c}); - Future crateApiAccountGetAddresses( - {required int uaPools, required Coin c}); + Future crateApiAccountGetAddresses({required int uaPools, required Coin c}); - Future crateApiNetworkGetCoingeckoPrice( - {required String api, required String currency}); + Future crateApiNetworkGetCoingeckoPrice({required String api, required String currency}); Future crateApiNetworkGetCurrentHeight({required Coin c}); @@ -317,18 +251,13 @@ abstract class RustLibApi extends BaseApi { Future> crateApiFrostGetDkgAddresses({required Coin c}); - Future crateApiNetworkGetExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}); + Future crateApiNetworkGetExchangeRate({required String api, required String fromCurrency, required String toCurrency}); - Future crateApiAccountGetExportedData( - {required int type, required Coin c}); + Future crateApiAccountGetExportedData({required int type, required Coin c}); int crateApiKeyGetKeyPools({required String key, required Coin c}); - Future crateApiMempoolGetMempoolTx( - {required String txId, required Coin c}); + Future crateApiMempoolGetMempoolTx({required String txId, required Coin c}); Future crateApiMigrateGetMigrationStatus({required Coin c}); @@ -338,13 +267,11 @@ abstract class RustLibApi extends BaseApi { Uint8List crateApiRaptorGetQrBytes({required List data}); - Future> crateApiNetworkGetSupportedVsCurrencies( - {required String api}); + Future> crateApiNetworkGetSupportedVsCurrencies({required String api}); Future crateApiCoinGetTorClient(); - Future crateApiAccountGetTxDetails( - {required int idTx, required Coin c}); + Future crateApiAccountGetTxDetails({required int idTx, required Coin c}); Future crateApiFrostHasDkgAddresses({required Coin c}); @@ -352,11 +279,9 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountHasTransparentPubKey({required Coin c}); - Future crateApiAccountImportAccount( - {required String passphrase, required List data, required Coin c}); + Future crateApiAccountImportAccount({required String passphrase, required List data, required Coin c}); - Future> crateApiContactsImportContactsVcard( - {required String vcardData, required Coin c}); + Future> crateApiContactsImportContactsVcard({required String vcardData, required Coin c}); Future crateApiInitInitApp(); @@ -370,17 +295,11 @@ abstract class RustLibApi extends BaseApi { void crateApiPluginInitPlugins(); - Future crateApiFrostInitSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}); + Future crateApiFrostInitSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}); - Future crateApiVaultInitVault( - {required FutureOr Function(Uint8List) append}); + Future crateApiVaultInitVault({required FutureOr Function(Uint8List) append}); - Future crateApiPluginInstallPlugin( - {required String url, required Coin c}); + Future crateApiPluginInstallPlugin({required String url, required Coin c}); Future crateApiNetworkIsIronwoodActive({required Coin c}); @@ -396,8 +315,7 @@ abstract class RustLibApi extends BaseApi { bool crateApiKeyIsValidPhrase({required String phrase}); - bool crateApiKeyIsValidTransparentAddress( - {required String address, required Coin c}); + bool crateApiKeyIsValidTransparentAddress({required String address, required Coin c}); Future crateApiZsaIsZsaAvailable({required Coin c}); @@ -416,8 +334,7 @@ abstract class RustLibApi extends BaseApi { Future> crateApiContactsListContacts({required Coin c}); - Future> crateApiDbListDbAccounts( - {required String dbFilepath}); + Future> crateApiDbListDbAccounts({required String dbFilepath}); Future> crateApiDbListDbNames({required String dir}); @@ -433,128 +350,87 @@ abstract class RustLibApi extends BaseApi { Future> crateApiZsaListZsaHoldings({required Coin c}); - Future crateApiAccountLockNote( - {required int id, required bool locked, required Coin c}); + Future crateApiAccountLockNote({required int id, required bool locked, required Coin c}); - Future crateApiAccountLockRecentNotes( - {required int height, required int threshold, required Coin c}); + Future crateApiAccountLockRecentNotes({required int height, required int threshold, required Coin c}); Future crateApiAccountMaxSpendable({required Coin c}); - Future crateApiAccountNewAccount( - {required NewAccount na, required Coin c}); + Future crateApiAccountNewAccount({required NewAccount na, required Coin c}); Future crateApiPayPackTransaction({required PcztPackage pczt}); - Future> crateApiPluginParseMemoWithPlugins( - {required List memoBytes, required Coin c}); + Future> crateApiPluginParseMemoWithPlugins({required List memoBytes, required Coin c}); List? crateApiPayParsePaymentUri({required String uri}); - Future crateApiPayPrepare( - {required List recipients, - required PaymentOptions options, - required Coin c}); + Future crateApiPayPrepare({required List recipients, required PaymentOptions options, required Coin c}); - Future crateApiPayPrepareMigration( - {required List recipients, - required int srcPools, - required Coin c}); + Future crateApiPayPrepareMigration({required List recipients, required int srcPools, required Coin c}); Future crateApiAccountPrintKeys({required int id, required Coin c}); - Future crateApiDbPutProp( - {required String key, required String value, required Coin c}); + Future crateApiDbPutProp({required String key, required String value, required Coin c}); Future> crateApiNetworkQueryLwdList({required int coin}); Future crateApiAccountReceiversDefault(); - Receivers crateApiAccountReceiversFromUa( - {required String ua, required Coin c}); + Receivers crateApiAccountReceiversFromUa({required String ua, required Coin c}); - Future crateApiAccountRemoveAccount( - {required int accountId, required Coin c}); + Future crateApiAccountRemoveAccount({required int accountId, required Coin c}); - Future crateApiPluginRemovePlugin( - {required String id, required Coin c}); + Future crateApiPluginRemovePlugin({required String id, required Coin c}); - Future crateApiAccountRenameCategory( - {required Category category, required Coin c}); + Future crateApiAccountRenameCategory({required Category category, required Coin c}); - Future crateApiAccountRenameFolder( - {required int id, required String name, required Coin c}); + Future crateApiAccountRenameFolder({required int id, required String name, required Coin c}); - Future crateApiAccountReorderAccount( - {required int oldPosition, required int newPosition, required Coin c}); + Future crateApiAccountReorderAccount({required int oldPosition, required int newPosition, required Coin c}); Future crateApiFrostResetSign({required Coin c}); Future crateApiAccountResetSync({required int id, required Coin c}); - Future crateApiOpenaliasResolveOpenalias( - {required String alias, required Coin c}); + Future crateApiOpenaliasResolveOpenalias({required String alias, required Coin c}); - Future crateApiOpenaliasResolveOpenaliasAll( - {required String alias}); + Future crateApiOpenaliasResolveOpenaliasAll({required String alias}); - Future crateApiOpenaliasResolveOpenaliasRaw( - {required String alias}); + Future crateApiOpenaliasResolveOpenaliasRaw({required String alias}); - Future crateApiSyncRewindSync( - {required int height, required int account, required Coin c}); + Future crateApiSyncRewindSync({required int height, required int account, required Coin c}); - Future crateApiPaySend( - {required int height, required List data, required Coin c}); + Future crateApiPaySend({required int height, required List data, required Coin c}); - Future crateApiZsaSetAssetName( - {required PlatformInt64 idAsset, required String name, required Coin c}); + Future crateApiZsaSetAssetName({required PlatformInt64 idAsset, required String name, required Coin c}); - Future crateApiFrostSetDkgAddress( - {required int id, required String address, required Coin c}); + Future crateApiFrostSetDkgAddress({required int id, required String address, required Coin c}); - Future crateApiFrostSetDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}); + Future crateApiFrostSetDkgParams({required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}); void crateApiInitSetExpertMode({required bool enabled}); Stream crateApiInitSetLogStream(); - Future crateApiPluginSetPluginEnabled( - {required String id, required bool enabled, required Coin c}); + Future crateApiPluginSetPluginEnabled({required String id, required bool enabled, required Coin c}); - Future crateApiTransactionSetTxCategory( - {required int id, int? category, required Coin c}); + Future crateApiTransactionSetTxCategory({required int id, int? category, required Coin c}); - Future crateApiTransactionSetTxPrice( - {required int id, double? price, required Coin c}); + Future crateApiTransactionSetTxPrice({required int id, double? price, required Coin c}); - Future crateApiTransactionSetUserMemo( - {required int idTx, String? memo, required Coin c}); + Future crateApiTransactionSetUserMemo({required int idTx, String? memo, required Coin c}); Future crateApiAccountShowLedgerSaplingAddress({required Coin c}); Future crateApiAccountShowLedgerTransparentAddress({required Coin c}); - Stream crateApiAccountSignLedgerTransaction( - {required PcztPackage package, required Coin c}); + Stream crateApiAccountSignLedgerTransaction({required PcztPackage package, required Coin c}); - Future crateApiPaySignTransaction( - {required PcztPackage pczt, required Coin c}); + Future crateApiPaySignTransaction({required PcztPackage pczt, required Coin c}); Future crateApiMigrateStepMigration({required Coin c}); - Future crateApiPayStorePendingTx( - {required int height, - required List txid, - double? price, - int? category, - required Coin c}); + Future crateApiPayStorePendingTx({required int height, required List txid, double? price, int? category, required Coin c}); Stream crateApiSyncSynchronize( {required List accounts, @@ -569,8 +445,7 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountToggleAllNotes({required Coin c}); - void crateApiOpenaliasTryValidateZcashAddress( - {required String address, required Coin c}); + void crateApiOpenaliasTryValidateZcashAddress({required String address, required Coin c}); Future crateApiAccountTxAccountDefault(); @@ -582,38 +457,25 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountTxSpendDefault(); - String crateApiAccountUaFromUfvk( - {required String ufvk, int? di, required Coin c}); + String crateApiAccountUaFromUfvk({required String ufvk, int? di, required Coin c}); Future crateApiAccountUnlockAllNotes({required Coin c}); Future crateApiPayUnpackTransaction({required List bytes}); - Future crateApiAccountUpdateAccount( - {required AccountUpdate update, required Coin c}); + Future crateApiAccountUpdateAccount({required AccountUpdate update, required Coin c}); - Future crateApiContactsUpdateContact( - {required int id, - String? name, - List? addresses, - String? notes, - required Coin c}); + Future crateApiContactsUpdateContact({required int id, String? name, List? addresses, String? notes, required Coin c}); - Future crateApiTransactionUpdateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}); + Future crateApiTransactionUpdateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}); bool crateApiOpenaliasValidateOpenaliasName({required String alias}); - bool crateApiOpenaliasValidateZcashAddress( - {required String address, required Coin c}); + bool crateApiOpenaliasValidateZcashAddress({required String address, required Coin c}); - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_DartVault; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_DartVault; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_DartVault; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr; @@ -623,23 +485,17 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr; - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_NoteMigration; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_NoteMigration; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_NoteMigration; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_NoteMigration; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr; - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_TransparentScanner; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_TransparentScanner; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_TransparentScanner; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr; } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -651,20 +507,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }); @override - Future> crateApiVaultDartVaultRecover( - {required DartVault that, - required List vaultBytes, - required String masterPassword}) { + Future> crateApiVaultDartVaultRecover({required DartVault that, required List vaultBytes, required String masterPassword}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); sse_encode_list_prim_u_8_loose(vaultBytes, serializer); sse_encode_String(masterPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 1, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_restored_account, @@ -677,29 +528,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultDartVaultRecoverConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiVaultDartVaultRecoverConstMeta => const TaskConstMeta( debugName: "DartVault_recover", argNames: ["that", "vaultBytes", "masterPassword"], ); @override Future> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, - required List vaultBytes, - required String deviceIdStr, - required List prfOutput}) { + {required DartVault that, required List vaultBytes, required String deviceIdStr, required List prfOutput}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); sse_encode_list_prim_u_8_loose(vaultBytes, serializer); sse_encode_String(deviceIdStr, serializer); sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 2, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_restored_account, @@ -712,31 +557,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultDartVaultRecoverWithPrfConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiVaultDartVaultRecoverWithPrfConstMeta => const TaskConstMeta( debugName: "DartVault_recover_with_prf", argNames: ["that", "vaultBytes", "deviceIdStr", "prfOutput"], ); @override Future crateApiVaultDartVaultRegisterDevice( - {required DartVault that, - required List initBytes, - required String masterPassword, - required String deviceIdStr, - required List prfOutput}) { + {required DartVault that, required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); sse_encode_list_prim_u_8_loose(initBytes, serializer); sse_encode_String(masterPassword, serializer); sse_encode_String(deviceIdStr, serializer); sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 3, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 3, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -749,35 +587,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultDartVaultRegisterDeviceConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiVaultDartVaultRegisterDeviceConstMeta => const TaskConstMeta( debugName: "DartVault_register_device", - argNames: [ - "that", - "initBytes", - "masterPassword", - "deviceIdStr", - "prfOutput" - ], + argNames: ["that", "initBytes", "masterPassword", "deviceIdStr", "prfOutput"], ); @override - Future crateApiVaultDartVaultSetMasterPassword( - {required DartVault that, - String? oldPassword, - required String newPassword, - Uint8List? oldBytes}) { + Future crateApiVaultDartVaultSetMasterPassword({required DartVault that, String? oldPassword, required String newPassword, Uint8List? oldBytes}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); sse_encode_opt_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 4, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 4, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -790,8 +615,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultDartVaultSetMasterPasswordConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiVaultDartVaultSetMasterPasswordConstMeta => const TaskConstMeta( debugName: "DartVault_set_master_password", argNames: ["that", "oldPassword", "newPassword", "oldBytes"], ); @@ -810,8 +634,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); sse_encode_u_32(timestamp, serializer); sse_encode_String(name, serializer); sse_encode_String(seed, serializer); @@ -819,42 +642,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(useInternal, serializer); sse_encode_u_32(birthHeight, serializer); sse_encode_list_prim_u_8_loose(pk, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 5, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 5, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiVaultDartVaultStoreAccountConstMeta, - argValues: [ - that, - timestamp, - name, - seed, - aindex, - useInternal, - birthHeight, - pk - ], + argValues: [that, timestamp, name, seed, aindex, useInternal, birthHeight, pk], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVaultDartVaultStoreAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiVaultDartVaultStoreAccountConstMeta => const TaskConstMeta( debugName: "DartVault_store_account", - argNames: [ - "that", - "timestamp", - "name", - "seed", - "aindex", - "useInternal", - "birthHeight", - "pk" - ], + argNames: ["that", "timestamp", "name", "seed", "aindex", "useInternal", "birthHeight", "pk"], ); @override @@ -863,10 +666,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 6, port: port_); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 6, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -890,10 +691,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 7, port: port_); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -906,8 +705,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => const TaskConstMeta( debugName: "Mempool_cancel", argNames: ["that"], ); @@ -921,8 +719,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; }, codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, + decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, decodeErrorData: null, ), constMeta: kCrateApiMempoolMempoolNewConstMeta, @@ -938,20 +735,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Stream crateApiMempoolMempoolRun( - {required Mempool that, required Coin c}) { + Stream crateApiMempoolMempoolRun({required Mempool that, required Coin c}) { final mempoolSink = RustStreamSink(); unawaited( handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(that, serializer); sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 9, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -972,16 +766,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiMigrateNoteMigrationCancel( - {required NoteMigration that}) { + Future crateApiMigrateNoteMigrationCancel({required NoteMigration that}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 10, port: port_); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -994,8 +785,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => const TaskConstMeta( debugName: "NoteMigration_cancel", argNames: ["that"], ); @@ -1009,8 +799,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; }, codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, + decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, decodeErrorData: null, ), constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, @@ -1020,30 +809,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => const TaskConstMeta( debugName: "NoteMigration_new", argNames: [], ); @override - Stream crateApiMigrateNoteMigrationRun( - {required NoteMigration that, - required Coin c, - required BigInt meanDelayMs}) { + Stream crateApiMigrateNoteMigrationRun({required NoteMigration that, required Coin c, required BigInt meanDelayMs}) { final sink = RustStreamSink(); unawaited( handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); sse_encode_StreamSink_migration_status_Sse(sink, serializer); sse_encode_box_autoadd_coin(c, serializer); sse_encode_u_64(meanDelayMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 12, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1058,23 +841,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return sink.stream; } - TaskConstMeta get kCrateApiMigrateNoteMigrationRunConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationRunConstMeta => const TaskConstMeta( debugName: "NoteMigration_run", argNames: ["that", "sink", "c", "meanDelayMs"], ); @override - Future crateApiSweepTransparentScannerCancel( - {required TransparentScanner that}) { + Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 13, port: port_); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1087,8 +866,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSweepTransparentScannerCancelConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiSweepTransparentScannerCancelConstMeta => const TaskConstMeta( debugName: "TransparentScanner_cancel", argNames: ["that"], ); @@ -1099,12 +877,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 14, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); }, codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, + decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiSweepTransparentScannerNewConstMeta, @@ -1114,32 +890,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => const TaskConstMeta( debugName: "TransparentScanner_new", argNames: [], ); @override - Stream crateApiSweepTransparentScannerRun( - {required TransparentScanner that, - required int endHeight, - required int gapLimit, - required Coin c}) { + Stream crateApiSweepTransparentScannerRun({required TransparentScanner that, required int endHeight, required int gapLimit, required Coin c}) { final addressStream = RustStreamSink(); unawaited( handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(that, serializer); sse_encode_StreamSink_String_Sse(addressStream, serializer); sse_encode_u_32(endHeight, serializer); sse_encode_u_32(gapLimit, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 15, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1154,8 +923,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return addressStream.stream; } - TaskConstMeta get kCrateApiSweepTransparentScannerRunConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiSweepTransparentScannerRunConstMeta => const TaskConstMeta( debugName: "TransparentScanner_run", argNames: ["that", "addressStream", "endHeight", "gapLimit", "c"], ); @@ -1167,8 +935,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 16, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pool_balance, @@ -1187,8 +954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayBroadcastTransaction( - {required int height, required List txBytes, required Coin c}) { + Future crateApiPayBroadcastTransaction({required int height, required List txBytes, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1196,8 +962,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(txBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 17, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1210,8 +975,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayBroadcastTransactionConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPayBroadcastTransactionConstMeta => const TaskConstMeta( debugName: "broadcast_transaction", argNames: ["height", "txBytes", "c"], ); @@ -1223,8 +987,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_recipient(recipients, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 18, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1243,16 +1006,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiSyncCacheBlockTime( - {required int height, required Coin c}) { + Future crateApiSyncCacheBlockTime({required int height, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(height, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 19, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1277,8 +1038,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 20, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1302,8 +1062,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 21, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1322,11 +1081,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiDbChangeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}) { + Future crateApiDbChangeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1335,8 +1090,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(tmpDir, serializer); sse_encode_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 22, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1373,8 +1127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => const TaskConstMeta( debugName: "check_sapling_params", argNames: [], ); @@ -1386,8 +1139,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 24, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1412,8 +1164,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 25, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1457,8 +1208,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiCoinCoinOpenDatabase( - {required Coin that, required String dbFilepath, String? password}) { + Future crateApiCoinCoinOpenDatabase({required Coin that, required String dbFilepath, String? password}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1466,8 +1216,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_String(dbFilepath, serializer); sse_encode_opt_String(password, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 27, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1480,23 +1229,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinCoinOpenDatabaseConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiCoinCoinOpenDatabaseConstMeta => const TaskConstMeta( debugName: "coin_open_database", argNames: ["that", "dbFilepath", "password"], ); @override - Future crateApiCoinCoinSetAccount( - {required Coin that, required int account}) { + Future crateApiCoinCoinSetAccount({required Coin that, required int account}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_32(account, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 28, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1515,8 +1261,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Coin crateApiCoinCoinSetLwd( - {required Coin that, required int serverType, required String url}) { + Coin crateApiCoinCoinSetLwd({required Coin that, required int serverType, required String url}) { return handler.executeSync( SyncTask( callFfi: () { @@ -1569,16 +1314,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiCoinCoinSetUseTor( - {required Coin that, required bool useTor}) { + Future crateApiCoinCoinSetUseTor({required Coin that, required bool useTor}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_bool(useTor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 31, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1597,11 +1340,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiContactsCreateContact( - {required String name, - required List addresses, - required String notes, - required Coin c}) { + Future crateApiContactsCreateContact({required String name, required List addresses, required String notes, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1610,8 +1349,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(addresses, serializer); sse_encode_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 32, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_contact, @@ -1624,23 +1362,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsCreateContactConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsCreateContactConstMeta => const TaskConstMeta( debugName: "create_contact", argNames: ["name", "addresses", "notes", "c"], ); @override - Future crateApiAccountCreateNewCategory( - {required Category category, required Coin c}) { + Future crateApiAccountCreateNewCategory({required Category category, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 33, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -1653,23 +1388,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountCreateNewCategoryConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountCreateNewCategoryConstMeta => const TaskConstMeta( debugName: "create_new_category", argNames: ["category", "c"], ); @override - Future crateApiAccountCreateNewFolder( - {required String name, required Coin c}) { + Future crateApiAccountCreateNewFolder({required String name, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 34, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_folder, @@ -1682,8 +1414,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountCreateNewFolderConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountCreateNewFolderConstMeta => const TaskConstMeta( debugName: "create_new_folder", argNames: ["name", "c"], ); @@ -1695,8 +1426,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(packet, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 35, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, @@ -1715,16 +1445,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountDeleteAccount( - {required int account, required Coin c}) { + Future crateApiAccountDeleteAccount({required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 36, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1737,23 +1465,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => const TaskConstMeta( debugName: "delete_account", argNames: ["account", "c"], ); @override - Future crateApiAccountDeleteCategories( - {required List ids, required Coin c}) { + Future crateApiAccountDeleteCategories({required List ids, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 37, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1766,23 +1491,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => const TaskConstMeta( debugName: "delete_categories", argNames: ["ids", "c"], ); @override - Future crateApiContactsDeleteContacts( - {required List ids, required Coin c}) { + Future crateApiContactsDeleteContacts({required List ids, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 38, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1795,23 +1517,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => const TaskConstMeta( debugName: "delete_contacts", argNames: ["ids", "c"], ); @override - Future crateApiAccountDeleteFolders( - {required List ids, required Coin c}) { + Future crateApiAccountDeleteFolders({required List ids, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 39, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1824,8 +1543,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => const TaskConstMeta( debugName: "delete_folders", argNames: ["ids", "c"], ); @@ -1840,8 +1558,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_dkg_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 40, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1871,8 +1588,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_signing_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 41, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1898,8 +1614,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 42, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1912,8 +1627,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => const TaskConstMeta( debugName: "download_sapling_params", argNames: [], ); @@ -1925,8 +1639,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_signing_event(a, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 43, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1945,16 +1658,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiRaptorEncode( - {required String path, required RaptorQParams params}) { + Future> crateApiRaptorEncode({required String path, required RaptorQParams params}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(path, serializer); sse_encode_box_autoadd_raptor_q_params(params, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 44, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_list_prim_u_8_strict, @@ -1978,8 +1689,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 45, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1998,8 +1708,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountExportAccount( - {required int id, required String passphrase, required Coin c}) { + Future crateApiAccountExportAccount({required int id, required String passphrase, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2007,8 +1716,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(passphrase, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 46, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2021,8 +1729,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountExportAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountExportAccountConstMeta => const TaskConstMeta( debugName: "export_account", argNames: ["id", "passphrase", "c"], ); @@ -2034,8 +1741,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 47, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2048,22 +1754,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => const TaskConstMeta( debugName: "export_contacts_vcard", argNames: ["c"], ); @override - Future crateApiPayExtractTransaction( - {required PcztPackage package}) { + Future crateApiPayExtractTransaction({required PcztPackage package}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 48, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2076,15 +1779,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayExtractTransactionConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPayExtractTransactionConstMeta => const TaskConstMeta( debugName: "extract_transaction", argNames: ["package"], ); @override - Future> crateApiAccountFetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}) { + Future> crateApiAccountFetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2092,8 +1793,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(c, serializer); sse_encode_bool(aggregate, serializer); sse_encode_u_8(poolFilter, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 49, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2106,15 +1806,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountFetchAddressTxCountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountFetchAddressTxCountConstMeta => const TaskConstMeta( debugName: "fetch_address_tx_count", argNames: ["c", "aggregate", "poolFilter"], ); @override - Future> crateApiTransactionFetchAmounts( - {int? from, int? to, required int category, required Coin c}) { + Future> crateApiTransactionFetchAmounts({int? from, int? to, required int category, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2123,8 +1821,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 50, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_u_32_f_64, @@ -2137,15 +1834,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionFetchAmountsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFetchAmountsConstMeta => const TaskConstMeta( debugName: "fetch_amounts", argNames: ["from", "to", "category", "c"], ); @override - Future> crateApiTransactionFetchCategoryAmounts( - {int? from, int? to, required Coin c}) { + Future> crateApiTransactionFetchCategoryAmounts({int? from, int? to, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2153,8 +1848,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(from, serializer); sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 51, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_string_f_64_bool, @@ -2167,22 +1861,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionFetchCategoryAmountsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFetchCategoryAmountsConstMeta => const TaskConstMeta( debugName: "fetch_category_amounts", argNames: ["from", "to", "c"], ); @override - Future> crateApiAccountFetchTransparentAddressTxCount( - {required Coin c}) { + Future> crateApiAccountFetchTransparentAddressTxCount({required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 52, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2195,23 +1886,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountFetchTransparentAddressTxCountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountFetchTransparentAddressTxCountConstMeta => const TaskConstMeta( debugName: "fetch_transparent_address_tx_count", argNames: ["c"], ); @override - Future crateApiSyncFetchTxDetails( - {required int account, required Coin c}) { + Future crateApiSyncFetchTxDetails({required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 53, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2230,8 +1918,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiTransactionFillMissingTxPrices( - {required String api, required String currency, required Coin c}) { + Future crateApiTransactionFillMissingTxPrices({required String api, required String currency, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2239,8 +1926,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 54, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2253,23 +1939,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionFillMissingTxPricesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFillMissingTxPricesConstMeta => const TaskConstMeta( debugName: "fill_missing_tx_prices", argNames: ["api", "currency", "c"], ); @override - Future> crateApiContactsFindContactsForAddress( - {required String address, required Coin c}) { + Future> crateApiContactsFindContactsForAddress({required String address, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 55, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact_match, @@ -2282,8 +1965,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsFindContactsForAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsFindContactsForAddressConstMeta => const TaskConstMeta( debugName: "find_contacts_for_address", argNames: ["address", "c"], ); @@ -2294,8 +1976,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 56, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_frost_sign_params, @@ -2308,8 +1989,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => const TaskConstMeta( debugName: "frost_sign_params_default", argNames: [], ); @@ -2321,8 +2001,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 57, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2335,8 +2014,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGenerateNextChangeAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGenerateNextChangeAddressConstMeta => const TaskConstMeta( debugName: "generate_next_change_address", argNames: ["c"], ); @@ -2348,8 +2026,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 58, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 58, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2362,8 +2039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => const TaskConstMeta( debugName: "generate_next_dindex", argNames: ["c"], ); @@ -2393,8 +2069,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountGetAccountAddresses( - {required int account, required int uaPools, required Coin c}) { + Future crateApiAccountGetAccountAddresses({required int account, required int uaPools, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2402,8 +2077,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 60, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2416,23 +2090,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountAddressesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountAddressesConstMeta => const TaskConstMeta( debugName: "get_account_addresses", argNames: ["account", "uaPools", "c"], ); @override - Future crateApiAccountGetAccountFingerprint( - {required int account, required Coin c}) { + Future crateApiAccountGetAccountFingerprint({required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 61, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 61, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2445,8 +2116,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountFingerprintConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountFingerprintConstMeta => const TaskConstMeta( debugName: "get_account_fingerprint", argNames: ["account", "c"], ); @@ -2458,8 +2128,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 62, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 62, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, @@ -2472,23 +2141,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountFrostParamsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountFrostParamsConstMeta => const TaskConstMeta( debugName: "get_account_frost_params", argNames: ["c"], ); @override - Future crateApiAccountGetAccountPools( - {required int account, required Coin c}) { + Future crateApiAccountGetAccountPools({required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 63, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 63, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2501,23 +2167,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountPoolsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountPoolsConstMeta => const TaskConstMeta( debugName: "get_account_pools", argNames: ["account", "c"], ); @override - Future crateApiAccountGetAccountSeed( - {required int account, required Coin c}) { + Future crateApiAccountGetAccountSeed({required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 64, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_seed, @@ -2530,15 +2193,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountSeedConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountSeedConstMeta => const TaskConstMeta( debugName: "get_account_seed", argNames: ["account", "c"], ); @override - Future crateApiAccountGetAccountUfvk( - {required int account, required int pools, required Coin c}) { + Future crateApiAccountGetAccountUfvk({required int account, required int pools, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2546,8 +2207,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(pools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2560,23 +2220,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAccountUfvkConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountUfvkConstMeta => const TaskConstMeta( debugName: "get_account_ufvk", argNames: ["account", "pools", "c"], ); @override - Future crateApiAccountGetAddresses( - {required int uaPools, required Coin c}) { + Future crateApiAccountGetAddresses({required int uaPools, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 66, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2589,23 +2246,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetAddressesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAddressesConstMeta => const TaskConstMeta( debugName: "get_addresses", argNames: ["uaPools", "c"], ); @override - Future crateApiNetworkGetCoingeckoPrice( - {required String api, required String currency}) { + Future crateApiNetworkGetCoingeckoPrice({required String api, required String currency}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); sse_encode_String(currency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -2618,8 +2272,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkGetCoingeckoPriceConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetCoingeckoPriceConstMeta => const TaskConstMeta( debugName: "get_coingecko_price", argNames: ["api", "currency"], ); @@ -2631,8 +2284,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 68, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2645,8 +2297,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => const TaskConstMeta( debugName: "get_current_height", argNames: ["c"], ); @@ -2658,8 +2309,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 69, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -2684,8 +2334,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 70, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2698,17 +2347,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => const TaskConstMeta( debugName: "get_dkg_addresses", argNames: ["c"], ); @override - Future crateApiNetworkGetExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}) { + Future crateApiNetworkGetExchangeRate({required String api, required String fromCurrency, required String toCurrency}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2716,8 +2361,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 71, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -2730,23 +2374,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkGetExchangeRateConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetExchangeRateConstMeta => const TaskConstMeta( debugName: "get_exchange_rate", argNames: ["api", "fromCurrency", "toCurrency"], ); @override - Future crateApiAccountGetExportedData( - {required int type, required Coin c}) { + Future crateApiAccountGetExportedData({required int type, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 72, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2759,8 +2400,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetExportedDataConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetExportedDataConstMeta => const TaskConstMeta( debugName: "get_exported_data", argNames: ["type", "c"], ); @@ -2792,16 +2432,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiMempoolGetMempoolTx( - {required String txId, required Coin c}) { + Future crateApiMempoolGetMempoolTx({required String txId, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 74, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2814,8 +2452,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => const TaskConstMeta( debugName: "get_mempool_tx", argNames: ["txId", "c"], ); @@ -2827,8 +2464,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 75, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -2841,8 +2477,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => const TaskConstMeta( debugName: "get_migration_status", argNames: ["c"], ); @@ -2854,8 +2489,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 76, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2868,8 +2502,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => const TaskConstMeta( debugName: "get_network_name", argNames: ["c"], ); @@ -2882,8 +2515,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 77, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2927,15 +2559,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiNetworkGetSupportedVsCurrencies( - {required String api}) { + Future> crateApiNetworkGetSupportedVsCurrencies({required String api}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 79, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2948,8 +2578,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkGetSupportedVsCurrenciesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetSupportedVsCurrenciesConstMeta => const TaskConstMeta( debugName: "get_supported_vs_currencies", argNames: ["api"], ); @@ -2960,8 +2589,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 80, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2980,16 +2608,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountGetTxDetails( - {required int idTx, required Coin c}) { + Future crateApiAccountGetTxDetails({required int idTx, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 81, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -3002,8 +2628,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => const TaskConstMeta( debugName: "get_tx_details", argNames: ["idTx", "c"], ); @@ -3015,8 +2640,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 82, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3029,8 +2653,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => const TaskConstMeta( debugName: "has_dkg_addresses", argNames: ["c"], ); @@ -3042,8 +2665,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 83, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3068,8 +2690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 84, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3082,15 +2703,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountHasTransparentPubKeyConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountHasTransparentPubKeyConstMeta => const TaskConstMeta( debugName: "has_transparent_pub_key", argNames: ["c"], ); @override - Future crateApiAccountImportAccount( - {required String passphrase, required List data, required Coin c}) { + Future crateApiAccountImportAccount({required String passphrase, required List data, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3098,8 +2717,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(passphrase, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 85, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3112,23 +2730,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountImportAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountImportAccountConstMeta => const TaskConstMeta( debugName: "import_account", argNames: ["passphrase", "data", "c"], ); @override - Future> crateApiContactsImportContactsVcard( - {required String vcardData, required Coin c}) { + Future> crateApiContactsImportContactsVcard({required String vcardData, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 86, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3141,8 +2756,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsImportContactsVcardConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsImportContactsVcardConstMeta => const TaskConstMeta( debugName: "import_contacts_vcard", argNames: ["vcardData", "c"], ); @@ -3153,8 +2767,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 87, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3178,8 +2791,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 88, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 88, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3204,8 +2816,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 89, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3230,8 +2841,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 90, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 90, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3256,8 +2866,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 91, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3300,11 +2909,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiFrostInitSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}) { + Future crateApiFrostInitSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3313,8 +2918,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 93, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3333,20 +2937,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiVaultInitVault( - {required FutureOr Function(Uint8List) append}) { + Future crateApiVaultInitVault({required FutureOr Function(Uint8List) append}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - append, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(append, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 94, port: port_); }, codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, + decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiVaultInitVaultConstMeta, @@ -3362,16 +2962,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPluginInstallPlugin( - {required String url, required Coin c}) { + Future crateApiPluginInstallPlugin({required String url, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 95, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -3384,8 +2982,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => const TaskConstMeta( debugName: "install_plugin", argNames: ["url", "c"], ); @@ -3397,8 +2994,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 96, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3411,8 +3007,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => const TaskConstMeta( debugName: "is_ironwood_active", argNames: ["c"], ); @@ -3424,8 +3019,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 97, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3438,8 +3032,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => const TaskConstMeta( debugName: "is_signing_in_progress", argNames: ["c"], ); @@ -3503,8 +3096,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 100)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3530,8 +3122,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 101)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3556,8 +3147,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 102)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3576,16 +3166,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - bool crateApiKeyIsValidTransparentAddress( - {required String address, required Coin c}) { + bool crateApiKeyIsValidTransparentAddress({required String address, required Coin c}) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 103)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3598,8 +3186,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyIsValidTransparentAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiKeyIsValidTransparentAddressConstMeta => const TaskConstMeta( debugName: "is_valid_transparent_address", argNames: ["address", "c"], ); @@ -3611,8 +3198,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 104, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3650,23 +3236,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_prim_u_8_strict(descHash, serializer); sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 105, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiIssuanceIssueAssetConstMeta, - argValues: [ - assetName, - amount, - firstIssuance, - finalize, - descHash, - idAccount, - c - ], + argValues: [assetName, amount, firstIssuance, finalize, descHash, idAccount, c], apiImpl: this, ), ); @@ -3674,15 +3251,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiIssuanceIssueAssetConstMeta => const TaskConstMeta( debugName: "issue_asset", - argNames: [ - "assetName", - "amount", - "firstIssuance", - "finalize", - "descHash", - "idAccount", - "c" - ], + argNames: ["assetName", "amount", "firstIssuance", "finalize", "descHash", "idAccount", "c"], ); @override @@ -3692,8 +3261,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 106, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -3706,8 +3274,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListAccountsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountListAccountsConstMeta => const TaskConstMeta( debugName: "list_accounts", argNames: ["c"], ); @@ -3719,8 +3286,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 107, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -3733,8 +3299,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => const TaskConstMeta( debugName: "list_categories", argNames: ["c"], ); @@ -3746,8 +3311,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 108, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3760,22 +3324,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsListContactsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsListContactsConstMeta => const TaskConstMeta( debugName: "list_contacts", argNames: ["c"], ); @override - Future> crateApiDbListDbAccounts( - {required String dbFilepath}) { + Future> crateApiDbListDbAccounts({required String dbFilepath}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 109, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -3800,8 +3361,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 110, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3826,8 +3386,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 111, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -3852,8 +3411,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 112, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -3878,8 +3436,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 113, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -3904,8 +3461,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 114, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -3930,8 +3486,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -3944,8 +3499,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => const TaskConstMeta( debugName: "list_tx_history", argNames: ["c"], ); @@ -3957,8 +3511,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -3977,8 +3530,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountLockNote( - {required int id, required bool locked, required Coin c}) { + Future crateApiAccountLockNote({required int id, required bool locked, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3986,8 +3538,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4006,8 +3557,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountLockRecentNotes( - {required int height, required int threshold, required Coin c}) { + Future crateApiAccountLockRecentNotes({required int height, required int threshold, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4015,8 +3565,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4029,8 +3578,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountLockRecentNotesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountLockRecentNotesConstMeta => const TaskConstMeta( debugName: "lock_recent_notes", argNames: ["height", "threshold", "c"], ); @@ -4042,8 +3590,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -4056,23 +3603,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => const TaskConstMeta( debugName: "max_spendable", argNames: ["c"], ); @override - Future crateApiAccountNewAccount( - {required NewAccount na, required Coin c}) { + Future crateApiAccountNewAccount({required NewAccount na, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 120, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4097,8 +3641,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4117,16 +3660,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiPluginParseMemoWithPlugins( - {required List memoBytes, required Coin c}) { + Future> crateApiPluginParseMemoWithPlugins({required List memoBytes, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4139,8 +3680,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginParseMemoWithPluginsConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPluginParseMemoWithPluginsConstMeta => const TaskConstMeta( debugName: "parse_memo_with_plugins", argNames: ["memoBytes", "c"], ); @@ -4152,8 +3692,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 123)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -4172,10 +3711,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayPrepare( - {required List recipients, - required PaymentOptions options, - required Coin c}) { + Future crateApiPayPrepare({required List recipients, required PaymentOptions options, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4183,8 +3719,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4203,10 +3738,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayPrepareMigration( - {required List recipients, - required int srcPools, - required Coin c}) { + Future crateApiPayPrepareMigration({required List recipients, required int srcPools, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4214,8 +3746,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4228,8 +3759,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayPrepareMigrationConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPayPrepareMigrationConstMeta => const TaskConstMeta( debugName: "prepare_migration", argNames: ["recipients", "srcPools", "c"], ); @@ -4242,8 +3772,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4262,8 +3791,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiDbPutProp( - {required String key, required String value, required Coin c}) { + Future crateApiDbPutProp({required String key, required String value, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4271,8 +3799,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 127, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4297,8 +3824,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -4311,8 +3837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => const TaskConstMeta( debugName: "query_lwd_list", argNames: ["coin"], ); @@ -4323,8 +3848,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 129, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4337,23 +3861,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => const TaskConstMeta( debugName: "receivers_default", argNames: [], ); @override - Receivers crateApiAccountReceiversFromUa( - {required String ua, required Coin c}) { + Receivers crateApiAccountReceiversFromUa({required String ua, required Coin c}) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 130)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4366,23 +3887,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountReceiversFromUaConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountReceiversFromUaConstMeta => const TaskConstMeta( debugName: "receivers_from_ua", argNames: ["ua", "c"], ); @override - Future crateApiAccountRemoveAccount( - {required int accountId, required Coin c}) { + Future crateApiAccountRemoveAccount({required int accountId, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4395,23 +3913,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountRemoveAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRemoveAccountConstMeta => const TaskConstMeta( debugName: "remove_account", argNames: ["accountId", "c"], ); @override - Future crateApiPluginRemovePlugin( - {required String id, required Coin c}) { + Future crateApiPluginRemovePlugin({required String id, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4430,16 +3945,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountRenameCategory( - {required Category category, required Coin c}) { + Future crateApiAccountRenameCategory({required Category category, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4452,15 +3965,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountRenameCategoryConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRenameCategoryConstMeta => const TaskConstMeta( debugName: "rename_category", argNames: ["category", "c"], ); @override - Future crateApiAccountRenameFolder( - {required int id, required String name, required Coin c}) { + Future crateApiAccountRenameFolder({required int id, required String name, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4468,8 +3979,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 134, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4482,15 +3992,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountRenameFolderConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRenameFolderConstMeta => const TaskConstMeta( debugName: "rename_folder", argNames: ["id", "name", "c"], ); @override - Future crateApiAccountReorderAccount( - {required int oldPosition, required int newPosition, required Coin c}) { + Future crateApiAccountReorderAccount({required int oldPosition, required int newPosition, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4498,8 +4006,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(oldPosition, serializer); sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4512,8 +4019,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountReorderAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountReorderAccountConstMeta => const TaskConstMeta( debugName: "reorder_account", argNames: ["oldPosition", "newPosition", "c"], ); @@ -4525,8 +4031,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 136, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4552,8 +4057,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4572,16 +4076,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiOpenaliasResolveOpenalias( - {required String alias, required Coin c}) { + Future crateApiOpenaliasResolveOpenalias({required String alias, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4594,22 +4096,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasConstMeta => const TaskConstMeta( debugName: "resolve_openalias", argNames: ["alias", "c"], ); @override - Future crateApiOpenaliasResolveOpenaliasAll( - {required String alias}) { + Future crateApiOpenaliasResolveOpenaliasAll({required String alias}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4622,22 +4121,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasAllConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasAllConstMeta => const TaskConstMeta( debugName: "resolve_openalias_all", argNames: ["alias"], ); @override - Future crateApiOpenaliasResolveOpenaliasRaw( - {required String alias}) { + Future crateApiOpenaliasResolveOpenaliasRaw({required String alias}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4650,15 +4146,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasRawConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasRawConstMeta => const TaskConstMeta( debugName: "resolve_openalias_raw", argNames: ["alias"], ); @override - Future crateApiSyncRewindSync( - {required int height, required int account, required Coin c}) { + Future crateApiSyncRewindSync({required int height, required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4666,8 +4160,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 141, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4686,8 +4179,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPaySend( - {required int height, required List data, required Coin c}) { + Future crateApiPaySend({required int height, required List data, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4695,8 +4187,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4715,8 +4206,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiZsaSetAssetName( - {required PlatformInt64 idAsset, required String name, required Coin c}) { + Future crateApiZsaSetAssetName({required PlatformInt64 idAsset, required String name, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4724,8 +4214,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_64(idAsset, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4744,8 +4233,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiFrostSetDkgAddress( - {required int id, required String address, required Coin c}) { + Future crateApiFrostSetDkgAddress({required int id, required String address, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4753,8 +4241,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(id, serializer); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 144, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4774,12 +4261,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostSetDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}) { + {required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4790,8 +4272,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(t, serializer); sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 145, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4816,8 +4297,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 146)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4843,8 +4323,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4864,8 +4343,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPluginSetPluginEnabled( - {required String id, required bool enabled, required Coin c}) { + Future crateApiPluginSetPluginEnabled({required String id, required bool enabled, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4873,8 +4351,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4887,15 +4364,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginSetPluginEnabledConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPluginSetPluginEnabledConstMeta => const TaskConstMeta( debugName: "set_plugin_enabled", argNames: ["id", "enabled", "c"], ); @override - Future crateApiTransactionSetTxCategory( - {required int id, int? category, required Coin c}) { + Future crateApiTransactionSetTxCategory({required int id, int? category, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4903,8 +4378,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4917,15 +4391,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionSetTxCategoryConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetTxCategoryConstMeta => const TaskConstMeta( debugName: "set_tx_category", argNames: ["id", "category", "c"], ); @override - Future crateApiTransactionSetTxPrice( - {required int id, double? price, required Coin c}) { + Future crateApiTransactionSetTxPrice({required int id, double? price, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4933,8 +4405,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4947,15 +4418,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionSetTxPriceConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetTxPriceConstMeta => const TaskConstMeta( debugName: "set_tx_price", argNames: ["id", "price", "c"], ); @override - Future crateApiTransactionSetUserMemo( - {required int idTx, String? memo, required Coin c}) { + Future crateApiTransactionSetUserMemo({required int idTx, String? memo, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4963,8 +4432,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4977,8 +4445,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionSetUserMemoConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetUserMemoConstMeta => const TaskConstMeta( debugName: "set_user_memo", argNames: ["idTx", "memo", "c"], ); @@ -4990,8 +4457,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 152, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5004,22 +4470,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountShowLedgerSaplingAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountShowLedgerSaplingAddressConstMeta => const TaskConstMeta( debugName: "show_ledger_sapling_address", argNames: ["c"], ); @override - Future crateApiAccountShowLedgerTransparentAddress( - {required Coin c}) { + Future crateApiAccountShowLedgerTransparentAddress({required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 153, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5032,15 +4495,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountShowLedgerTransparentAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountShowLedgerTransparentAddressConstMeta => const TaskConstMeta( debugName: "show_ledger_transparent_address", argNames: ["c"], ); @override - Stream crateApiAccountSignLedgerTransaction( - {required PcztPackage package, required Coin c}) { + Stream crateApiAccountSignLedgerTransaction({required PcztPackage package, required Coin c}) { final sink = RustStreamSink(); unawaited( handler.executeNormal( @@ -5050,8 +4511,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_signing_event_Sse(sink, serializer); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5066,23 +4526,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return sink.stream; } - TaskConstMeta get kCrateApiAccountSignLedgerTransactionConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountSignLedgerTransactionConstMeta => const TaskConstMeta( debugName: "sign_ledger_transaction", argNames: ["sink", "package", "c"], ); @override - Future crateApiPaySignTransaction( - {required PcztPackage pczt, required Coin c}) { + Future crateApiPaySignTransaction({required PcztPackage pczt, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5107,8 +4564,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5121,19 +4577,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => const TaskConstMeta( debugName: "step_migration", argNames: ["c"], ); @override - Future crateApiPayStorePendingTx( - {required int height, - required List txid, - double? price, - int? category, - required Coin c}) { + Future crateApiPayStorePendingTx({required int height, required List txid, double? price, int? category, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5143,8 +4593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 157, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5185,24 +4634,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(checkpointAge, serializer); sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 158, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiSyncSynchronizeConstMeta, - argValues: [ - progress, - accounts, - currentHeight, - actionsPerSync, - transparentLimit, - checkpointAge, - fast, - c - ], + argValues: [progress, accounts, currentHeight, actionsPerSync, transparentLimit, checkpointAge, fast, c], apiImpl: this, ), ), @@ -5212,16 +4651,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TaskConstMeta get kCrateApiSyncSynchronizeConstMeta => const TaskConstMeta( debugName: "synchronize", - argNames: [ - "progress", - "accounts", - "currentHeight", - "actionsPerSync", - "transparentLimit", - "checkpointAge", - "fast", - "c" - ], + argNames: ["progress", "accounts", "currentHeight", "actionsPerSync", "transparentLimit", "checkpointAge", "fast", "c"], ); @override @@ -5232,8 +4662,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 159)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5258,8 +4687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5272,23 +4700,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => const TaskConstMeta( debugName: "toggle_all_notes", argNames: ["c"], ); @override - void crateApiOpenaliasTryValidateZcashAddress( - {required String address, required Coin c}) { + void crateApiOpenaliasTryValidateZcashAddress({required String address, required Coin c}) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 161)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5301,8 +4726,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasTryValidateZcashAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasTryValidateZcashAddressConstMeta => const TaskConstMeta( debugName: "try_validate_zcash_address", argNames: ["address", "c"], ); @@ -5313,8 +4737,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5327,8 +4750,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => const TaskConstMeta( debugName: "tx_account_default", argNames: [], ); @@ -5339,8 +4761,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5353,8 +4774,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => const TaskConstMeta( debugName: "tx_memo_default", argNames: [], ); @@ -5365,8 +4785,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5379,8 +4798,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => const TaskConstMeta( debugName: "tx_note_default", argNames: [], ); @@ -5391,8 +4809,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 165, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5405,8 +4822,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => const TaskConstMeta( debugName: "tx_output_default", argNames: [], ); @@ -5417,8 +4833,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5431,15 +4846,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => const TaskConstMeta( debugName: "tx_spend_default", argNames: [], ); @override - String crateApiAccountUaFromUfvk( - {required String ufvk, int? di, required Coin c}) { + String crateApiAccountUaFromUfvk({required String ufvk, int? di, required Coin c}) { return handler.executeSync( SyncTask( callFfi: () { @@ -5447,8 +4860,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ufvk, serializer); sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 167)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5473,8 +4885,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5487,8 +4898,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => const TaskConstMeta( debugName: "unlock_all_notes", argNames: ["c"], ); @@ -5500,8 +4910,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5514,23 +4923,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => const TaskConstMeta( debugName: "unpack_transaction", argNames: ["bytes"], ); @override - Future crateApiAccountUpdateAccount( - {required AccountUpdate update, required Coin c}) { + Future crateApiAccountUpdateAccount({required AccountUpdate update, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 170, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5543,19 +4949,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountUpdateAccountConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiAccountUpdateAccountConstMeta => const TaskConstMeta( debugName: "update_account", argNames: ["update", "c"], ); @override - Future crateApiContactsUpdateContact( - {required int id, - String? name, - List? addresses, - String? notes, - required Coin c}) { + Future crateApiContactsUpdateContact({required int id, String? name, List? addresses, String? notes, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5565,8 +4965,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_String(addresses, serializer); sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 171, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5579,17 +4978,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiContactsUpdateContactConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiContactsUpdateContactConstMeta => const TaskConstMeta( debugName: "update_contact", argNames: ["id", "name", "addresses", "notes", "c"], ); @override - Future crateApiTransactionUpdateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}) { + Future crateApiTransactionUpdateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5597,8 +4992,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(currency, serializer); sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 172, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5611,8 +5005,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiTransactionUpdateHistoricalPricesConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionUpdateHistoricalPricesConstMeta => const TaskConstMeta( debugName: "update_historical_prices", argNames: ["currency", "exchangeRate", "c"], ); @@ -5624,8 +5017,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 173)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5638,23 +5030,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasValidateOpenaliasNameConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasValidateOpenaliasNameConstMeta => const TaskConstMeta( debugName: "validate_openalias_name", argNames: ["alias"], ); @override - bool crateApiOpenaliasValidateZcashAddress( - {required String address, required Coin c}) { + bool crateApiOpenaliasValidateZcashAddress({required String address, required Coin c}) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 174)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5667,15 +5056,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiOpenaliasValidateZcashAddressConstMeta => - const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasValidateZcashAddressConstMeta => const TaskConstMeta( debugName: "validate_zcash_address", argNames: ["address", "c"], ); - Future Function(int, dynamic) - encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr Function(Uint8List) raw) { + Future Function(int, dynamic) encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) raw) { return (callId, rawArg0) async { final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); @@ -5707,37 +5093,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }; } - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_DartVault => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_DartVault => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_DartVault => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_Mempool => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_Mempool => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_Mempool => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_Mempool => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_NoteMigration => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_NoteMigration => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_NoteMigration => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_NoteMigration => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_TransparentScanner => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_TransparentScanner => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_TransparentScanner => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw) { @@ -5746,81 +5124,61 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - FutureOr Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw) { + FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(''); } @@ -5832,33 +5190,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @@ -5876,43 +5226,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - RustStreamSink dco_decode_StreamSink_log_message_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_log_message_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_mempool_msg_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse( - dynamic raw) { + RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @@ -5927,8 +5271,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Account dco_decode_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 20) - throw Exception('unexpected arr length: expect 20 but see ${arr.length}'); + if (arr.length != 20) throw Exception('unexpected arr length: expect 20 but see ${arr.length}'); return Account( coin: dco_decode_u_8(arr[0]), id: dco_decode_u_32(arr[1]), @@ -5957,8 +5300,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { AccountUpdate dco_decode_account_update(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) - throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return AccountUpdate( coin: dco_decode_u_8(arr[0]), id: dco_decode_u_32(arr[1]), @@ -5975,8 +5317,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Addresses dco_decode_addresses(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 5) - throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + if (arr.length != 5) throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); return Addresses( taddr: dco_decode_opt_String(arr[0]), saddr: dco_decode_opt_String(arr[1]), @@ -6104,8 +5445,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Category dco_decode_category(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Category( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6117,8 +5457,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Coin dco_decode_coin(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) - throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return Coin.raw( coin: dco_decode_u_8(arr[0]), account: dco_decode_u_32(arr[1]), @@ -6134,8 +5473,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Contact dco_decode_contact(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return Contact( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6148,8 +5486,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ContactMatch dco_decode_contact_match(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return ContactMatch( contact: dco_decode_contact(arr[0]), matchedAddress: dco_decode_String(arr[1]), @@ -6160,8 +5497,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { DbAccountPreview dco_decode_db_account_preview(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return DbAccountPreview( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6201,8 +5537,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ExchangeRate dco_decode_exchange_rate(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return ExchangeRate( fromPrice: dco_decode_f_64(arr[0]), toPrice: dco_decode_f_64(arr[1]), @@ -6221,8 +5556,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Folder dco_decode_folder(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return Folder( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6233,8 +5567,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { FrostParams dco_decode_frost_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return FrostParams( id: dco_decode_u_8(arr[0]), n: dco_decode_u_8(arr[1]), @@ -6246,8 +5579,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { FrostSignParams dco_decode_frost_sign_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return FrostSignParams( account: dco_decode_u_32(arr[0]), coordinator: dco_decode_u_8(arr[1]), @@ -6412,12 +5744,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw) { + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List) - .map(dco_decode_record_string_f_64_bool) - .toList(); + return (raw as List).map(dco_decode_record_string_f_64_bool).toList(); } @protected @@ -6490,8 +5819,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { LogMessage dco_decode_log_message(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return LogMessage( level: dco_decode_u_8(arr[0]), message: dco_decode_String(arr[1]), @@ -6503,8 +5831,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { LWDInfo dco_decode_lwd_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) - throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return LWDInfo( url: dco_decode_String(arr[0]), isTor: dco_decode_bool(arr[1]), @@ -6520,8 +5847,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Memo dco_decode_memo(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) - throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return Memo( id: dco_decode_u_32(arr[0]), idTx: dco_decode_u_32(arr[1]), @@ -6540,8 +5866,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoCell dco_decode_memo_cell(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return MemoCell( cellType: dco_decode_String(arr[0]), value: dco_decode_String(arr[1]), @@ -6552,8 +5877,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoRow dco_decode_memo_row(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) - throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return MemoRow( cells: dco_decode_list_memo_cell(arr[0]), ); @@ -6563,8 +5887,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoSection dco_decode_memo_section(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return MemoSection( title: dco_decode_String(arr[0]), headers: dco_decode_list_String(arr[1]), @@ -6576,8 +5899,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolAmount dco_decode_mempool_amount(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return MempoolAmount( account: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6606,8 +5928,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolNote dco_decode_mempool_note(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 9) - throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + if (arr.length != 9) throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); return MempoolNote( account: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6625,8 +5946,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolTx dco_decode_mempool_tx(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return MempoolTx( txid: dco_decode_String(arr[0]), amounts: dco_decode_list_mempool_amount(arr[1]), @@ -6664,8 +5984,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MigrationStatus dco_decode_migration_status(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) - throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return MigrationStatus( phase: dco_decode_String(arr[0]), splitFees: dco_decode_u_64(arr[1]), @@ -6684,8 +6003,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NewAccount dco_decode_new_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 13) - throw Exception('unexpected arr length: expect 13 but see ${arr.length}'); + if (arr.length != 13) throw Exception('unexpected arr length: expect 13 but see ${arr.length}'); return NewAccount( icon: dco_decode_opt_list_prim_u_8_strict(arr[0]), name: dco_decode_String(arr[1]), @@ -6707,8 +6025,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { OpenAliasResolution dco_decode_open_alias_resolution(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return OpenAliasResolution( recipients: dco_decode_list_recipient(arr[0]), dnssecStatus: dco_decode_String(arr[1]), @@ -6797,8 +6114,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PaymentOptions dco_decode_payment_options(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return PaymentOptions( srcPools: dco_decode_u_8(arr[0]), recipientPaysFee: dco_decode_bool(arr[1]), @@ -6811,8 +6127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PcztPackage dco_decode_pczt_package(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) - throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return PcztPackage( pczt: dco_decode_list_prim_u_8_strict(arr[0]), nSpends: dco_decode_usize_array_4(arr[1]), @@ -6831,8 +6146,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PluginInfo dco_decode_plugin_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) - throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return PluginInfo( id: dco_decode_String(arr[0]), name: dco_decode_String(arr[1]), @@ -6849,8 +6163,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PoolBalance dco_decode_pool_balance(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) - throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return PoolBalance( field0: dco_decode_list_prim_u_64_strict(arr[0]), ); @@ -6860,8 +6173,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RaptorQParams dco_decode_raptor_q_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return RaptorQParams( version: dco_decode_u_16(arr[0]), ecLevel: dco_decode_u_8(arr[1]), @@ -6873,8 +6185,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RawOpenAliasResolution dco_decode_raw_open_alias_resolution(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return RawOpenAliasResolution( records: dco_decode_list_String(arr[0]), dnssecStatus: dco_decode_String(arr[1]), @@ -6885,8 +6196,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Receivers dco_decode_receivers(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Receivers( taddr: dco_decode_opt_String(arr[0]), saddr: dco_decode_opt_String(arr[1]), @@ -6898,8 +6208,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Recipient dco_decode_recipient(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) - throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return Recipient( address: dco_decode_String(arr[0]), amount: dco_decode_u_64(arr[1]), @@ -6943,8 +6252,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RestoredAccount dco_decode_restored_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return RestoredAccount( timestamp: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6959,8 +6267,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SaplingParamsStatus dco_decode_sapling_params_status(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) - throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return SaplingParamsStatus( downloaded: dco_decode_bool(arr[0]), ); @@ -6970,8 +6277,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Seed dco_decode_seed(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Seed( mnemonic: dco_decode_String(arr[0]), phrase: dco_decode_String(arr[1]), @@ -7031,8 +6337,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncHeight dco_decode_sync_height(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return SyncHeight( pool: dco_decode_u_8(arr[0]), height: dco_decode_u_32(arr[1]), @@ -7044,8 +6349,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncProgress dco_decode_sync_progress(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return SyncProgress( height: dco_decode_u_32(arr[0]), time: dco_decode_u_32(arr[1]), @@ -7056,8 +6360,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TAddressTxCount dco_decode_t_address_tx_count(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) - throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return TAddressTxCount( pool: dco_decode_u_8(arr[0]), address: dco_decode_String(arr[1]), @@ -7073,8 +6376,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Tx dco_decode_tx(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 14) - throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); + if (arr.length != 14) throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); return Tx( id: dco_decode_u_32(arr[0]), txid: dco_decode_list_prim_u_8_strict(arr[1]), @@ -7097,8 +6399,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxAccount dco_decode_tx_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 12) - throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); + if (arr.length != 12) throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); return TxAccount( id: dco_decode_u_32(arr[0]), account: dco_decode_u_32(arr[1]), @@ -7119,8 +6420,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxMemo dco_decode_tx_memo(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 5) - throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + if (arr.length != 5) throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); return TxMemo( note: dco_decode_opt_box_autoadd_u_32(arr[0]), output: dco_decode_opt_box_autoadd_u_32(arr[1]), @@ -7134,8 +6434,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxNote dco_decode_tx_note(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 12) - throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); + if (arr.length != 12) throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); return TxNote( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -7156,8 +6455,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxOutput dco_decode_tx_output(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxOutput( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -7172,8 +6470,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlan dco_decode_tx_plan(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxPlan( height: dco_decode_u_32(arr[0]), inputs: dco_decode_list_tx_plan_in(arr[1]), @@ -7188,8 +6485,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlanIn dco_decode_tx_plan_in(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) - throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return TxPlanIn( pool: dco_decode_u_8(arr[0]), amount: dco_decode_opt_box_autoadd_u_64(arr[1]), @@ -7201,8 +6497,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlanOut dco_decode_tx_plan_out(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) - throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return TxPlanOut( pool: dco_decode_u_8(arr[0]), amount: dco_decode_u_64(arr[1]), @@ -7215,8 +6510,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxSpend dco_decode_tx_spend(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxSpend( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -7273,8 +6567,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ZsaHolding dco_decode_zsa_holding(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) - throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return ZsaHolding( idAsset: dco_decode_i_64(arr[0]), assetDescHash: dco_decode_list_prim_u_8_strict(arr[1]), @@ -7295,84 +6588,57 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected @@ -7383,93 +6649,73 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - RustStreamSink sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @@ -7539,14 +6785,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_hidden = sse_decode_opt_box_autoadd_bool(deserializer); var var_enabled = sse_decode_opt_box_autoadd_bool(deserializer); return AccountUpdate( - coin: var_coin, - id: var_id, - name: var_name, - icon: var_icon, - birth: var_birth, - folder: var_folder, - hidden: var_hidden, - enabled: var_enabled); + coin: var_coin, id: var_id, name: var_name, icon: var_icon, birth: var_birth, folder: var_folder, hidden: var_hidden, enabled: var_enabled); } @protected @@ -7557,12 +6796,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_oaddr = sse_decode_opt_String(deserializer); var var_ua = sse_decode_opt_String(deserializer); var var_diversifierIndex = sse_decode_u_32(deserializer); - return Addresses( - taddr: var_taddr, - saddr: var_saddr, - oaddr: var_oaddr, - ua: var_ua, - diversifierIndex: var_diversifierIndex); + return Addresses(taddr: var_taddr, saddr: var_saddr, oaddr: var_oaddr, ua: var_ua, diversifierIndex: var_diversifierIndex); } @protected @@ -7572,8 +6806,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer) { + AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_account_update(deserializer)); } @@ -7603,8 +6836,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - FrostParams sse_decode_box_autoadd_frost_params( - SseDeserializer deserializer) { + FrostParams sse_decode_box_autoadd_frost_params(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_frost_params(deserializer)); } @@ -7634,22 +6866,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer) { + PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_payment_options(deserializer)); } @protected - PcztPackage sse_decode_box_autoadd_pczt_package( - SseDeserializer deserializer) { + PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_pczt_package(deserializer)); } @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer) { + RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_raptor_q_params(deserializer)); } @@ -7661,8 +6890,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer) { + SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_signing_event(deserializer)); } @@ -7705,13 +6933,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_useTor = sse_decode_bool(deserializer); var var_proxy = sse_decode_String(deserializer); return Coin.raw( - coin: var_coin, - account: var_account, - dbFilepath: var_dbFilepath, - url: var_url, - serverType: var_serverType, - useTor: var_useTor, - proxy: var_proxy); + coin: var_coin, account: var_account, dbFilepath: var_dbFilepath, url: var_url, serverType: var_serverType, useTor: var_useTor, proxy: var_proxy); } @protected @@ -7721,8 +6943,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_name = sse_decode_String(deserializer); var var_addresses = sse_decode_list_String(deserializer); var var_notes = sse_decode_String(deserializer); - return Contact( - id: var_id, name: var_name, addresses: var_addresses, notes: var_notes); + return Contact(id: var_id, name: var_name, addresses: var_addresses, notes: var_notes); } @protected @@ -7730,8 +6951,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs var var_contact = sse_decode_contact(deserializer); var var_matchedAddress = sse_decode_String(deserializer); - return ContactMatch( - contact: var_contact, matchedAddress: var_matchedAddress); + return ContactMatch(contact: var_contact, matchedAddress: var_matchedAddress); } @protected @@ -7778,11 +6998,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_toPrice = sse_decode_f_64(deserializer); var var_fromCurrency = sse_decode_String(deserializer); var var_toCurrency = sse_decode_String(deserializer); - return ExchangeRate( - fromPrice: var_fromPrice, - toPrice: var_toPrice, - fromCurrency: var_fromCurrency, - toCurrency: var_toCurrency); + return ExchangeRate(fromPrice: var_fromPrice, toPrice: var_toPrice, fromCurrency: var_fromCurrency, toCurrency: var_toCurrency); } @protected @@ -7814,10 +7030,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_account = sse_decode_u_32(deserializer); var var_coordinator = sse_decode_u_8(deserializer); var var_fundingAccount = sse_decode_u_32(deserializer); - return FrostSignParams( - account: var_account, - coordinator: var_coordinator, - fundingAccount: var_fundingAccount); + return FrostSignParams(account: var_account, coordinator: var_coordinator, fundingAccount: var_fundingAccount); } @protected @@ -7887,8 +7100,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_contact_match( - SseDeserializer deserializer) { + List sse_decode_list_contact_match(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7900,8 +7112,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_db_account_preview( - SseDeserializer deserializer) { + List sse_decode_list_db_account_preview(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7925,8 +7136,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer) { + List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7998,8 +7208,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_mempool_amount( - SseDeserializer deserializer) { + List sse_decode_list_mempool_amount(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -8089,8 +7298,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer) { + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -8102,8 +7310,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer) { + List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -8115,8 +7322,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_restored_account( - SseDeserializer deserializer) { + List sse_decode_list_restored_account(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -8128,8 +7334,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_t_address_tx_count( - SseDeserializer deserializer) { + List sse_decode_list_t_address_tx_count(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -8255,14 +7460,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_uptime = sse_decode_u_32(deserializer); var var_version = sse_decode_String(deserializer); var var_ping = sse_decode_u_32(deserializer); - return LWDInfo( - url: var_url, - isTor: var_isTor, - height: var_height, - status: var_status, - uptime: var_uptime, - version: var_version, - ping: var_ping); + return LWDInfo(url: var_url, isTor: var_isTor, height: var_height, status: var_status, uptime: var_uptime, version: var_version, ping: var_ping); } @protected @@ -8321,8 +7519,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_account = sse_decode_u_32(deserializer); var var_name = sse_decode_String(deserializer); var var_value = sse_decode_i_64(deserializer); - return MempoolAmount( - account: var_account, name: var_name, value: var_value); + return MempoolAmount(account: var_account, name: var_name, value: var_value); } @protected @@ -8373,8 +7570,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_amounts = sse_decode_list_mempool_amount(deserializer); var var_notes = sse_decode_list_mempool_note(deserializer); var var_size = sse_decode_u_32(deserializer); - return MempoolTx( - txid: var_txid, amounts: var_amounts, notes: var_notes, size: var_size); + return MempoolTx(txid: var_txid, amounts: var_amounts, notes: var_notes, size: var_size); } @protected @@ -8460,13 +7656,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer) { + OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_recipients = sse_decode_list_recipient(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); - return OpenAliasResolution( - recipients: var_recipients, dnssecStatus: var_dnssecStatus); + return OpenAliasResolution(recipients: var_recipients, dnssecStatus: var_dnssecStatus); } @protected @@ -8503,8 +7697,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer) { + FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { @@ -8620,11 +7813,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_recipientPaysFee = sse_decode_bool(deserializer); var var_smartTransparent = sse_decode_bool(deserializer); var var_category = sse_decode_opt_box_autoadd_u_32(deserializer); - return PaymentOptions( - srcPools: var_srcPools, - recipientPaysFee: var_recipientPaysFee, - smartTransparent: var_smartTransparent, - category: var_category); + return PaymentOptions(srcPools: var_srcPools, recipientPaysFee: var_recipientPaysFee, smartTransparent: var_smartTransparent, category: var_category); } @protected @@ -8688,18 +7877,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_version = sse_decode_u_16(deserializer); var var_ecLevel = sse_decode_u_8(deserializer); var var_repair = sse_decode_u_32(deserializer); - return RaptorQParams( - version: var_version, ecLevel: var_ecLevel, repair: var_repair); + return RaptorQParams(version: var_version, ecLevel: var_ecLevel, repair: var_repair); } @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer) { + RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_records = sse_decode_list_String(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); - return RawOpenAliasResolution( - records: var_records, dnssecStatus: var_dnssecStatus); + return RawOpenAliasResolution(records: var_records, dnssecStatus: var_dnssecStatus); } @protected @@ -8734,8 +7920,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer) { + (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_field0 = sse_decode_String(deserializer); var var_field1 = sse_decode_f_64(deserializer); @@ -8761,17 +7946,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_useInternal = sse_decode_bool(deserializer); var var_birthHeight = sse_decode_u_32(deserializer); return RestoredAccount( - timestamp: var_timestamp, - name: var_name, - seed: var_seed, - aindex: var_aindex, - useInternal: var_useInternal, - birthHeight: var_birthHeight); + timestamp: var_timestamp, name: var_name, seed: var_seed, aindex: var_aindex, useInternal: var_useInternal, birthHeight: var_birthHeight); } @protected - SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer) { + SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_downloaded = sse_decode_bool(deserializer); return SaplingParamsStatus(downloaded: var_downloaded); @@ -8863,13 +8042,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_txCount = sse_decode_u_32(deserializer); var var_time = sse_decode_u_32(deserializer); return TAddressTxCount( - pool: var_pool, - address: var_address, - scope: var_scope, - dindex: var_dindex, - amount: var_amount, - txCount: var_txCount, - time: var_time); + pool: var_pool, address: var_address, scope: var_scope, dindex: var_dindex, amount: var_amount, txCount: var_txCount, time: var_time); } @protected @@ -8944,12 +8117,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_pool = sse_decode_u_8(deserializer); var var_memo = sse_decode_opt_String(deserializer); var var_memoBytes = sse_decode_list_prim_u_8_strict(deserializer); - return TxMemo( - note: var_note, - output: var_output, - pool: var_pool, - memo: var_memo, - memoBytes: var_memoBytes); + return TxMemo(note: var_note, output: var_output, pool: var_pool, memo: var_memo, memoBytes: var_memoBytes); } @protected @@ -8991,13 +8159,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_value = sse_decode_u_64(deserializer); var var_address = sse_decode_String(deserializer); var var_contactName = sse_decode_opt_String(deserializer); - return TxOutput( - id: var_id, - pool: var_pool, - height: var_height, - value: var_value, - address: var_address, - contactName: var_contactName); + return TxOutput(id: var_id, pool: var_pool, height: var_height, value: var_value, address: var_address, contactName: var_contactName); } @protected @@ -9009,13 +8171,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_fee = sse_decode_u_64(deserializer); var var_canSign = sse_decode_bool(deserializer); var var_canBroadcast = sse_decode_bool(deserializer); - return TxPlan( - height: var_height, - inputs: var_inputs, - outputs: var_outputs, - fee: var_fee, - canSign: var_canSign, - canBroadcast: var_canBroadcast); + return TxPlan(height: var_height, inputs: var_inputs, outputs: var_outputs, fee: var_fee, canSign: var_canSign, canBroadcast: var_canBroadcast); } @protected @@ -9024,8 +8180,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_pool = sse_decode_u_8(deserializer); var var_amount = sse_decode_opt_box_autoadd_u_64(deserializer); var var_assetName = sse_decode_String(deserializer); - return TxPlanIn( - pool: var_pool, amount: var_amount, assetName: var_assetName); + return TxPlanIn(pool: var_pool, amount: var_amount, assetName: var_assetName); } @protected @@ -9035,11 +8190,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_amount = sse_decode_u_64(deserializer); var var_address = sse_decode_String(deserializer); var var_assetName = sse_decode_String(deserializer); - return TxPlanOut( - pool: var_pool, - amount: var_amount, - address: var_address, - assetName: var_assetName); + return TxPlanOut(pool: var_pool, amount: var_amount, address: var_address, assetName: var_assetName); } @protected @@ -9051,13 +8202,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_value = sse_decode_u_64(deserializer); var var_idAsset = sse_decode_opt_box_autoadd_u_32(deserializer); var var_assetDisplay = sse_decode_String(deserializer); - return TxSpend( - id: var_id, - pool: var_pool, - height: var_height, - value: var_value, - idAsset: var_idAsset, - assetDisplay: var_assetDisplay); + return TxSpend(id: var_id, pool: var_pool, height: var_height, value: var_value, idAsset: var_idAsset, assetDisplay: var_assetDisplay); } @protected @@ -9125,159 +8270,105 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer) { + void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.message, serializer); } @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: true), serializer); } @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: true), serializer); } @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: true), - serializer); + sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: true), serializer); } @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: true), - serializer); + sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: true), serializer); } @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: false), serializer); } @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: false), - serializer); + sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: false), serializer); } @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); } @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: false), - serializer); + sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: false), serializer); } @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: false), - serializer); + sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: false), serializer); } @protected - void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr Function(Uint8List) self, SseSerializer serializer) { + void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_DartOpaque( - encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - self), - serializer); + sse_encode_DartOpaque(encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(self), serializer); } @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_isize( - PlatformPointerUtil.ptrToPlatformInt64(encodeDartOpaque( - self, portManager.dartHandlerPort, generalizedFrbRustBinding)), - serializer); + sse_encode_isize(PlatformPointerUtil.ptrToPlatformInt64(encodeDartOpaque(self, portManager.dartHandlerPort, generalizedFrbRustBinding)), serializer); } @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: null), serializer); } @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: null), serializer); } @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: null), - serializer); + sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: null), serializer); } @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: null), - serializer); + sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: null), serializer); } @protected - void sse_encode_StreamSink_String_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9291,8 +8382,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9306,8 +8396,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_log_message_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9321,8 +8410,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9336,8 +8424,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9351,8 +8438,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9366,8 +8452,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9381,8 +8466,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -9456,8 +8540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer) { + void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_account_update(self, serializer); } @@ -9469,8 +8552,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_category( - Category self, SseSerializer serializer) { + void sse_encode_box_autoadd_category(Category self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_category(self, serializer); } @@ -9488,8 +8570,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer) { + void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_frost_params(self, serializer); } @@ -9501,43 +8582,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer) { + void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_64(self, serializer); } @protected - void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer) { + void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_mempool_tx(self, serializer); } @protected - void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer) { + void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_new_account(self, serializer); } @protected - void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer) { + void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_payment_options(self, serializer); } @protected - void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer) { + void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_pczt_package(self, serializer); } @protected - void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer) { + void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_raptor_q_params(self, serializer); } @@ -9549,8 +8624,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer) { + void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_signing_event(self, serializer); } @@ -9610,8 +8684,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer) { + void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.id, serializer); sse_encode_String(self.name, serializer); @@ -9673,8 +8746,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer) { + void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.account, serializer); sse_encode_u_8(self.coordinator, serializer); @@ -9736,8 +8808,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_contact_match( - List self, SseSerializer serializer) { + void sse_encode_list_contact_match(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9746,8 +8817,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_db_account_preview( - List self, SseSerializer serializer) { + void sse_encode_list_db_account_preview(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9765,8 +8835,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_list_prim_u_8_strict( - List self, SseSerializer serializer) { + void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9793,8 +8862,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_memo_cell( - List self, SseSerializer serializer) { + void sse_encode_list_memo_cell(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9812,8 +8880,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_memo_section( - List self, SseSerializer serializer) { + void sse_encode_list_memo_section(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9822,8 +8889,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_mempool_amount( - List self, SseSerializer serializer) { + void sse_encode_list_mempool_amount(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9832,8 +8898,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_mempool_note( - List self, SseSerializer serializer) { + void sse_encode_list_mempool_note(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9842,8 +8907,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_plugin_info( - List self, SseSerializer serializer) { + void sse_encode_list_plugin_info(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9852,58 +8916,49 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_prim_u_32_loose( - List self, SseSerializer serializer) { + void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer - .putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); + serializer.buffer.putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); } @protected - void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer) { + void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint32List(self); } @protected - void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer) { + void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); } @protected - void sse_encode_list_prim_u_8_loose( - List self, SseSerializer serializer) { + void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer - .putUint8List(self is Uint8List ? self : Uint8List.fromList(self)); + serializer.buffer.putUint8List(self is Uint8List ? self : Uint8List.fromList(self)); } @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer) { + void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint8List(self); } @protected - void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer) { + void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); } @protected - void sse_encode_list_recipient( - List self, SseSerializer serializer) { + void sse_encode_list_recipient(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9912,8 +8967,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer) { + void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9922,8 +8976,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer) { + void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9932,8 +8985,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_restored_account( - List self, SseSerializer serializer) { + void sse_encode_list_restored_account(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9942,8 +8994,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_t_address_tx_count( - List self, SseSerializer serializer) { + void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9979,8 +9030,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_output( - List self, SseSerializer serializer) { + void sse_encode_list_tx_output(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9989,8 +9039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_plan_in( - List self, SseSerializer serializer) { + void sse_encode_list_tx_plan_in(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9999,8 +9048,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_plan_out( - List self, SseSerializer serializer) { + void sse_encode_list_tx_plan_out(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -10018,8 +9066,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_zsa_holding( - List self, SseSerializer serializer) { + void sse_encode_list_zsa_holding(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -10128,8 +9175,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer) { + void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs switch (self) { case MigrationEvent_SplitComplete(fee: final fee): @@ -10149,8 +9195,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer) { + void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.phase, serializer); sse_encode_u_64(self.splitFees, serializer); @@ -10183,8 +9228,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer) { + void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_recipient(self.recipients, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -10221,8 +9265,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer) { + void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -10242,8 +9285,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer) { + void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -10293,8 +9335,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_String( - List? self, SseSerializer serializer) { + void sse_encode_opt_list_String(List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -10304,8 +9345,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer) { + void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -10315,8 +9355,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_recipient( - List? self, SseSerializer serializer) { + void sse_encode_opt_list_recipient(List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -10326,8 +9365,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer) { + void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.srcPools, serializer); sse_encode_bool(self.recipientPaysFee, serializer); @@ -10370,8 +9408,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_raptor_q_params( - RaptorQParams self, SseSerializer serializer) { + void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.version, serializer); sse_encode_u_8(self.ecLevel, serializer); @@ -10379,8 +9416,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer) { + void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_String(self.records, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -10408,8 +9444,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer) { + void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.$1, serializer); sse_encode_f_64(self.$2, serializer); @@ -10417,16 +9452,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer) { + void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.$1, serializer); sse_encode_f_64(self.$2, serializer); } @protected - void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer) { + void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.timestamp, serializer); sse_encode_String(self.name, serializer); @@ -10437,8 +9470,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer) { + void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self.downloaded, serializer); } @@ -10508,8 +9540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer) { + void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.pool, serializer); sse_encode_String(self.address, serializer); @@ -10691,58 +9722,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @sealed class DartVaultImpl extends RustOpaque implements DartVault { // Not to be used by end users - DartVaultImpl.frbInternalDcoDecode(List wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + DartVaultImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - DartVaultImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + DartVaultImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: - RustLib.instance.api.rust_arc_increment_strong_count_DartVault, - rustArcDecrementStrongCount: - RustLib.instance.api.rust_arc_decrement_strong_count_DartVault, - rustArcDecrementStrongCountPtr: - RustLib.instance.api.rust_arc_decrement_strong_count_DartVaultPtr, + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_DartVault, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_DartVault, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_DartVaultPtr, ); - Future> recover( - {required List vaultBytes, required String masterPassword}) => - RustLib.instance.api.crateApiVaultDartVaultRecover( - that: this, vaultBytes: vaultBytes, masterPassword: masterPassword); - - Future> recoverWithPrf( - {required List vaultBytes, - required String deviceIdStr, - required List prfOutput}) => - RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf( - that: this, - vaultBytes: vaultBytes, - deviceIdStr: deviceIdStr, - prfOutput: prfOutput); - - Future registerDevice( - {required List initBytes, - required String masterPassword, - required String deviceIdStr, - required List prfOutput}) => + Future> recover({required List vaultBytes, required String masterPassword}) => + RustLib.instance.api.crateApiVaultDartVaultRecover(that: this, vaultBytes: vaultBytes, masterPassword: masterPassword); + + Future> recoverWithPrf({required List vaultBytes, required String deviceIdStr, required List prfOutput}) => + RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf(that: this, vaultBytes: vaultBytes, deviceIdStr: deviceIdStr, prfOutput: prfOutput); + + Future registerDevice({required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}) => RustLib.instance.api.crateApiVaultDartVaultRegisterDevice( - that: this, - initBytes: initBytes, - masterPassword: masterPassword, - deviceIdStr: deviceIdStr, - prfOutput: prfOutput); - - Future setMasterPassword( - {String? oldPassword, - required String newPassword, - Uint8List? oldBytes}) => - RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword( - that: this, - oldPassword: oldPassword, - newPassword: newPassword, - oldBytes: oldBytes); + that: this, initBytes: initBytes, masterPassword: masterPassword, deviceIdStr: deviceIdStr, prfOutput: prfOutput); + + Future setMasterPassword({String? oldPassword, required String newPassword, Uint8List? oldBytes}) => + RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword(that: this, oldPassword: oldPassword, newPassword: newPassword, oldBytes: oldBytes); Future storeAccount( {required int timestamp, @@ -10753,14 +9755,7 @@ class DartVaultImpl extends RustOpaque implements DartVault { required int birthHeight, required List pk}) => RustLib.instance.api.crateApiVaultDartVaultStoreAccount( - that: this, - timestamp: timestamp, - name: name, - seed: seed, - aindex: aindex, - useInternal: useInternal, - birthHeight: birthHeight, - pk: pk); + that: this, timestamp: timestamp, name: name, seed: seed, aindex: aindex, useInternal: useInternal, birthHeight: birthHeight, pk: pk); Future test() => RustLib.instance.api.crateApiVaultDartVaultTest( that: this, @@ -10770,86 +9765,64 @@ class DartVaultImpl extends RustOpaque implements DartVault { @sealed class MempoolImpl extends RustOpaque implements Mempool { // Not to be used by end users - MempoolImpl.frbInternalDcoDecode(List wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + MempoolImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - MempoolImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + MempoolImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: - RustLib.instance.api.rust_arc_increment_strong_count_Mempool, - rustArcDecrementStrongCount: - RustLib.instance.api.rust_arc_decrement_strong_count_Mempool, - rustArcDecrementStrongCountPtr: - RustLib.instance.api.rust_arc_decrement_strong_count_MempoolPtr, + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_Mempool, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_Mempool, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_MempoolPtr, ); Future cancel() => RustLib.instance.api.crateApiMempoolMempoolCancel( that: this, ); - Stream run({required Coin c}) => - RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); + Stream run({required Coin c}) => RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); } @sealed class NoteMigrationImpl extends RustOpaque implements NoteMigration { // Not to be used by end users - NoteMigrationImpl.frbInternalDcoDecode(List wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + NoteMigrationImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: - RustLib.instance.api.rust_arc_increment_strong_count_NoteMigration, - rustArcDecrementStrongCount: - RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigration, - rustArcDecrementStrongCountPtr: - RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigrationPtr, + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_NoteMigration, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigration, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigrationPtr, ); - Future cancel() => - RustLib.instance.api.crateApiMigrateNoteMigrationCancel( + Future cancel() => RustLib.instance.api.crateApiMigrateNoteMigrationCancel( that: this, ); Stream run({required Coin c, required BigInt meanDelayMs}) => - RustLib.instance.api.crateApiMigrateNoteMigrationRun( - that: this, c: c, meanDelayMs: meanDelayMs); + RustLib.instance.api.crateApiMigrateNoteMigrationRun(that: this, c: c, meanDelayMs: meanDelayMs); } @sealed class TransparentScannerImpl extends RustOpaque implements TransparentScanner { // Not to be used by end users - TransparentScannerImpl.frbInternalDcoDecode(List wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + TransparentScannerImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - TransparentScannerImpl.frbInternalSseDecode( - BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + TransparentScannerImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: - RustLib.instance.api.rust_arc_increment_strong_count_TransparentScanner, - rustArcDecrementStrongCount: - RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScanner, - rustArcDecrementStrongCountPtr: RustLib - .instance.api.rust_arc_decrement_strong_count_TransparentScannerPtr, + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_TransparentScanner, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScanner, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScannerPtr, ); - Future cancel() => - RustLib.instance.api.crateApiSweepTransparentScannerCancel( + Future cancel() => RustLib.instance.api.crateApiSweepTransparentScannerCancel( that: this, ); - Stream run( - {required int endHeight, required int gapLimit, required Coin c}) => - RustLib.instance.api.crateApiSweepTransparentScannerRun( - that: this, endHeight: endHeight, gapLimit: gapLimit, c: c); + Stream run({required int endHeight, required int gapLimit, required Coin c}) => + RustLib.instance.api.crateApiSweepTransparentScannerRun(that: this, endHeight: endHeight, gapLimit: gapLimit, c: c); } diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 54fd0b567..cc41236b5 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -44,92 +44,62 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected - DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - FutureOr Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw); + FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw); @protected Object dco_decode_DartOpaque(dynamic raw); @protected - DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); @@ -144,20 +114,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -340,8 +306,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List dco_decode_list_recipient(dynamic raw); @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw); + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -566,104 +531,70 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); @protected - DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected - DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer); @protected String sse_decode_String(SseDeserializer deserializer); @@ -681,8 +612,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { bool sse_decode_bool(SseDeserializer deserializer); @protected - AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer); + AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -712,22 +642,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_box_autoadd_new_account(SseDeserializer deserializer); @protected - PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer); + PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer); + RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected - SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer); + SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -793,19 +720,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_contact(SseDeserializer deserializer); @protected - List sse_decode_list_contact_match( - SseDeserializer deserializer); + List sse_decode_list_contact_match(SseDeserializer deserializer); @protected - List sse_decode_list_db_account_preview( - SseDeserializer deserializer); + List sse_decode_list_db_account_preview(SseDeserializer deserializer); @protected List sse_decode_list_folder(SseDeserializer deserializer); @protected - List sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer); + List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer); @protected List sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -823,8 +747,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_memo_section(SseDeserializer deserializer); @protected - List sse_decode_list_mempool_amount( - SseDeserializer deserializer); + List sse_decode_list_mempool_amount(SseDeserializer deserializer); @protected List sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -854,20 +777,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_recipient(SseDeserializer deserializer); @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer); + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer); @protected - List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer); + List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer); @protected - List sse_decode_list_restored_account( - SseDeserializer deserializer); + List sse_decode_list_restored_account(SseDeserializer deserializer); @protected - List sse_decode_list_t_address_tx_count( - SseDeserializer deserializer); + List sse_decode_list_t_address_tx_count(SseDeserializer deserializer); @protected List sse_decode_list_tx(SseDeserializer deserializer); @@ -933,8 +852,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_new_account(SseDeserializer deserializer); @protected - OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer); + OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -946,8 +864,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { double? sse_decode_opt_box_autoadd_f_64(SseDeserializer deserializer); @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer); + FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -992,8 +909,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RaptorQParams sse_decode_raptor_q_params(SseDeserializer deserializer); @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer); + RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -1002,8 +918,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { Recipient sse_decode_recipient(SseDeserializer deserializer); @protected - (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer); + (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -1012,8 +927,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RestoredAccount sse_decode_restored_account(SseDeserializer deserializer); @protected - SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer); + SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -1085,113 +999,78 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected - void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer); + void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr Function(Uint8List) self, SseSerializer serializer); + void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_StreamSink_String_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_log_message_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1209,8 +1088,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_bool(bool self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer); + void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1225,42 +1103,34 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_box_autoadd_f_64(double self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer); + void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer); + void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer); + void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer); + void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer); + void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer); + void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer); + void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer); + void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1284,8 +1154,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_contact_match(ContactMatch self, SseSerializer serializer); @protected - void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer); + void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1303,8 +1172,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_frost_params(FrostParams self, SseSerializer serializer); @protected - void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer); + void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1328,19 +1196,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_contact(List self, SseSerializer serializer); @protected - void sse_encode_list_contact_match( - List self, SseSerializer serializer); + void sse_encode_list_contact_match(List self, SseSerializer serializer); @protected - void sse_encode_list_db_account_preview( - List self, SseSerializer serializer); + void sse_encode_list_db_account_preview(List self, SseSerializer serializer); @protected void sse_encode_list_folder(List self, SseSerializer serializer); @protected - void sse_encode_list_list_prim_u_8_strict( - List self, SseSerializer serializer); + void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer); @protected void sse_encode_list_lwd_info(List self, SseSerializer serializer); @@ -1355,63 +1220,49 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_memo_row(List self, SseSerializer serializer); @protected - void sse_encode_list_memo_section( - List self, SseSerializer serializer); + void sse_encode_list_memo_section(List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_amount( - List self, SseSerializer serializer); + void sse_encode_list_mempool_amount(List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_note( - List self, SseSerializer serializer); + void sse_encode_list_mempool_note(List self, SseSerializer serializer); @protected - void sse_encode_list_plugin_info( - List self, SseSerializer serializer); + void sse_encode_list_plugin_info(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_loose( - List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer); + void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer); @protected - void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer); @protected - void sse_encode_list_recipient( - List self, SseSerializer serializer); + void sse_encode_list_recipient(List self, SseSerializer serializer); @protected - void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer); + void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer); @protected - void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer); + void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer); @protected - void sse_encode_list_restored_account( - List self, SseSerializer serializer); + void sse_encode_list_restored_account(List self, SseSerializer serializer); @protected - void sse_encode_list_t_address_tx_count( - List self, SseSerializer serializer); + void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer); @protected void sse_encode_list_tx(List self, SseSerializer serializer); @@ -1426,19 +1277,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_tx_output(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_in( - List self, SseSerializer serializer); + void sse_encode_list_tx_plan_in(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_out( - List self, SseSerializer serializer); + void sse_encode_list_tx_plan_out(List self, SseSerializer serializer); @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); @protected - void sse_encode_list_zsa_holding( - List self, SseSerializer serializer); + void sse_encode_list_zsa_holding(List self, SseSerializer serializer); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -1471,19 +1319,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer); + void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer); @protected - void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer); + void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer); + void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1495,15 +1340,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_box_autoadd_f_64(double? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -1521,16 +1364,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_list_String(List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer); + void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_recipient( - List? self, SseSerializer serializer); + void sse_encode_opt_list_recipient(List? self, SseSerializer serializer); @protected - void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer); + void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -1545,8 +1385,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected - void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer); + void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -1555,20 +1394,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_recipient(Recipient self, SseSerializer serializer); @protected - void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer); + void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer); @protected - void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer); + void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer); @protected - void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer); + void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer); @protected - void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer); + void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -1586,8 +1421,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_sync_progress(SyncProgress self, SseSerializer serializer); @protected - void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer); + void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -1644,19 +1478,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { // Section: wire_class class RustLibWire implements BaseWire { - factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => - RustLibWire(lib.ffiDynamicLibrary); + factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => RustLibWire(lib.ffiDynamicLibrary); /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; + final ffi.Pointer Function(String symbolName) _lookup; /// The symbols are looked up in [dynamicLibrary]. - RustLibWire(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; + RustLibWire(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -1671,8 +1501,7 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction)>(); - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -1687,8 +1516,7 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction)>(); - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -1703,8 +1531,7 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction)>(); - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -1719,8 +1546,7 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction)>(); - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -1735,8 +1561,7 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction)>(); - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -1751,8 +1576,7 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction)>(); - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1767,8 +1591,7 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr .asFunction)>(); - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 85135bd8a..8d88cb206 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -46,92 +46,62 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected - DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected - FutureOr Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw); + FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw); @protected Object dco_decode_DartOpaque(dynamic raw); @protected - DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); @protected - Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); @protected - NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); @protected - TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); @protected RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); @@ -146,20 +116,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse( - dynamic raw); + RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -342,8 +308,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List dco_decode_list_recipient(dynamic raw); @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw); + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -568,104 +533,70 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); @protected - DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected - DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); @protected - Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); @protected - NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); @protected - TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer); @protected String sse_decode_String(SseDeserializer deserializer); @@ -683,8 +614,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { bool sse_decode_bool(SseDeserializer deserializer); @protected - AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer); + AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -714,22 +644,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_box_autoadd_new_account(SseDeserializer deserializer); @protected - PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer); + PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer); + RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected - SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer); + SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -795,19 +722,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_contact(SseDeserializer deserializer); @protected - List sse_decode_list_contact_match( - SseDeserializer deserializer); + List sse_decode_list_contact_match(SseDeserializer deserializer); @protected - List sse_decode_list_db_account_preview( - SseDeserializer deserializer); + List sse_decode_list_db_account_preview(SseDeserializer deserializer); @protected List sse_decode_list_folder(SseDeserializer deserializer); @protected - List sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer); + List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer); @protected List sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -825,8 +749,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_memo_section(SseDeserializer deserializer); @protected - List sse_decode_list_mempool_amount( - SseDeserializer deserializer); + List sse_decode_list_mempool_amount(SseDeserializer deserializer); @protected List sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -856,20 +779,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_recipient(SseDeserializer deserializer); @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer); + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer); @protected - List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer); + List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer); @protected - List sse_decode_list_restored_account( - SseDeserializer deserializer); + List sse_decode_list_restored_account(SseDeserializer deserializer); @protected - List sse_decode_list_t_address_tx_count( - SseDeserializer deserializer); + List sse_decode_list_t_address_tx_count(SseDeserializer deserializer); @protected List sse_decode_list_tx(SseDeserializer deserializer); @@ -935,8 +854,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_new_account(SseDeserializer deserializer); @protected - OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer); + OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -948,8 +866,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { double? sse_decode_opt_box_autoadd_f_64(SseDeserializer deserializer); @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer); + FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -994,8 +911,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RaptorQParams sse_decode_raptor_q_params(SseDeserializer deserializer); @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer); + RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -1004,8 +920,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { Recipient sse_decode_recipient(SseDeserializer deserializer); @protected - (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer); + (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -1014,8 +929,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RestoredAccount sse_decode_restored_account(SseDeserializer deserializer); @protected - SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer); + SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -1087,113 +1001,78 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected - void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer); + void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); @protected - void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr Function(Uint8List) self, SseSerializer serializer); + void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_StreamSink_String_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_log_message_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1211,8 +1090,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_bool(bool self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer); + void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1227,42 +1105,34 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_box_autoadd_f_64(double self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer); + void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer); + void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer); + void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer); + void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer); + void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer); + void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer); + void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer); + void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1286,8 +1156,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_contact_match(ContactMatch self, SseSerializer serializer); @protected - void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer); + void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1305,8 +1174,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_frost_params(FrostParams self, SseSerializer serializer); @protected - void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer); + void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1330,19 +1198,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_contact(List self, SseSerializer serializer); @protected - void sse_encode_list_contact_match( - List self, SseSerializer serializer); + void sse_encode_list_contact_match(List self, SseSerializer serializer); @protected - void sse_encode_list_db_account_preview( - List self, SseSerializer serializer); + void sse_encode_list_db_account_preview(List self, SseSerializer serializer); @protected void sse_encode_list_folder(List self, SseSerializer serializer); @protected - void sse_encode_list_list_prim_u_8_strict( - List self, SseSerializer serializer); + void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer); @protected void sse_encode_list_lwd_info(List self, SseSerializer serializer); @@ -1357,63 +1222,49 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_memo_row(List self, SseSerializer serializer); @protected - void sse_encode_list_memo_section( - List self, SseSerializer serializer); + void sse_encode_list_memo_section(List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_amount( - List self, SseSerializer serializer); + void sse_encode_list_mempool_amount(List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_note( - List self, SseSerializer serializer); + void sse_encode_list_mempool_note(List self, SseSerializer serializer); @protected - void sse_encode_list_plugin_info( - List self, SseSerializer serializer); + void sse_encode_list_plugin_info(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_loose( - List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer); + void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer); @protected - void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer); @protected - void sse_encode_list_recipient( - List self, SseSerializer serializer); + void sse_encode_list_recipient(List self, SseSerializer serializer); @protected - void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer); + void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer); @protected - void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer); + void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer); @protected - void sse_encode_list_restored_account( - List self, SseSerializer serializer); + void sse_encode_list_restored_account(List self, SseSerializer serializer); @protected - void sse_encode_list_t_address_tx_count( - List self, SseSerializer serializer); + void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer); @protected void sse_encode_list_tx(List self, SseSerializer serializer); @@ -1428,19 +1279,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_tx_output(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_in( - List self, SseSerializer serializer); + void sse_encode_list_tx_plan_in(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_out( - List self, SseSerializer serializer); + void sse_encode_list_tx_plan_out(List self, SseSerializer serializer); @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); @protected - void sse_encode_list_zsa_holding( - List self, SseSerializer serializer); + void sse_encode_list_zsa_holding(List self, SseSerializer serializer); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -1473,19 +1321,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer); + void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer); @protected - void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer); + void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer); + void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1497,15 +1342,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_box_autoadd_f_64(double? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -1523,16 +1366,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_list_String(List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer); + void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_recipient( - List? self, SseSerializer serializer); + void sse_encode_opt_list_recipient(List? self, SseSerializer serializer); @protected - void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer); + void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -1547,8 +1387,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected - void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer); + void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -1557,20 +1396,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_recipient(Recipient self, SseSerializer serializer); @protected - void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer); + void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer); @protected - void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer); + void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer); @protected - void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer); + void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer); @protected - void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer); + void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -1588,8 +1423,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_sync_progress(SyncProgress self, SseSerializer serializer); @protected - void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer); + void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -1648,53 +1482,29 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { class RustLibWire implements BaseWire { RustLibWire.fromExternalLibrary(ExternalLibrary lib); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr) => + wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr) => + wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr) => + wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr) => + wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr) => + wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr) => + wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr) => + wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr) => + wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(ptr); } @JS('wasm_bindgen') @@ -1703,35 +1513,19 @@ external RustLibWasmModule get wasmModule; @JS() @anonymous extension type RustLibWasmModule._(JSObject _) implements JSObject { - external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr); - external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr); + external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr); - external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr); - external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr); + external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr); - external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr); - external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr); + external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr); - external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr); - external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr); + external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr); } diff --git a/lib/src/rust/io.dart b/lib/src/rust/io.dart index 0d15c9d3e..c130d0c3d 100644 --- a/lib/src/rust/io.dart +++ b/lib/src/rust/io.dart @@ -22,10 +22,5 @@ class SyncHeight { @override bool operator ==(Object other) => - identical(this, other) || - other is SyncHeight && - runtimeType == other.runtimeType && - pool == other.pool && - height == other.height && - time == other.time; + identical(this, other) || other is SyncHeight && runtimeType == other.runtimeType && pool == other.pool && height == other.height && time == other.time; } diff --git a/lib/src/rust/pay.dart b/lib/src/rust/pay.dart index 4c52e5bf3..54f62655c 100644 --- a/lib/src/rust/pay.dart +++ b/lib/src/rust/pay.dart @@ -29,14 +29,7 @@ class Recipient { @override int get hashCode => - address.hashCode ^ - amount.hashCode ^ - pools.hashCode ^ - userMemo.hashCode ^ - memoBytes.hashCode ^ - price.hashCode ^ - assetBase.hashCode ^ - assetName.hashCode; + address.hashCode ^ amount.hashCode ^ pools.hashCode ^ userMemo.hashCode ^ memoBytes.hashCode ^ price.hashCode ^ assetBase.hashCode ^ assetName.hashCode; @override bool operator ==(Object other) => @@ -71,13 +64,7 @@ class TxPlan { }); @override - int get hashCode => - height.hashCode ^ - inputs.hashCode ^ - outputs.hashCode ^ - fee.hashCode ^ - canSign.hashCode ^ - canBroadcast.hashCode; + int get hashCode => height.hashCode ^ inputs.hashCode ^ outputs.hashCode ^ fee.hashCode ^ canSign.hashCode ^ canBroadcast.hashCode; @override bool operator ==(Object other) => @@ -109,11 +96,7 @@ class TxPlanIn { @override bool operator ==(Object other) => identical(this, other) || - other is TxPlanIn && - runtimeType == other.runtimeType && - pool == other.pool && - amount == other.amount && - assetName == other.assetName; + other is TxPlanIn && runtimeType == other.runtimeType && pool == other.pool && amount == other.amount && assetName == other.assetName; } class TxPlanOut { @@ -130,8 +113,7 @@ class TxPlanOut { }); @override - int get hashCode => - pool.hashCode ^ amount.hashCode ^ address.hashCode ^ assetName.hashCode; + int get hashCode => pool.hashCode ^ amount.hashCode ^ address.hashCode ^ assetName.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/pay/error.freezed.dart b/lib/src/rust/pay/error.freezed.dart index 8be139e33..77ae697d0 100644 --- a/lib/src/rust/pay/error.freezed.dart +++ b/lib/src/rust/pay/error.freezed.dart @@ -16,8 +16,7 @@ T _$identity(T value) => value; mixin _$Error { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is Error); + return identical(this, other) || (other.runtimeType == runtimeType && other is Error); } @override @@ -266,8 +265,7 @@ class Error_InvalidPoolMask extends Error { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is Error_InvalidPoolMask); + return identical(this, other) || (other.runtimeType == runtimeType && other is Error_InvalidPoolMask); } @override @@ -290,16 +288,12 @@ class Error_NotEnoughFunds extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_NotEnoughFundsCopyWith get copyWith => - _$Error_NotEnoughFundsCopyWithImpl( - this, _$identity); + $Error_NotEnoughFundsCopyWith get copyWith => _$Error_NotEnoughFundsCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is Error_NotEnoughFunds && - (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && other is Error_NotEnoughFunds && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -312,18 +306,14 @@ class Error_NotEnoughFunds extends Error { } /// @nodoc -abstract mixin class $Error_NotEnoughFundsCopyWith<$Res> - implements $ErrorCopyWith<$Res> { - factory $Error_NotEnoughFundsCopyWith(Error_NotEnoughFunds value, - $Res Function(Error_NotEnoughFunds) _then) = - _$Error_NotEnoughFundsCopyWithImpl; +abstract mixin class $Error_NotEnoughFundsCopyWith<$Res> implements $ErrorCopyWith<$Res> { + factory $Error_NotEnoughFundsCopyWith(Error_NotEnoughFunds value, $Res Function(Error_NotEnoughFunds) _then) = _$Error_NotEnoughFundsCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$Error_NotEnoughFundsCopyWithImpl<$Res> - implements $Error_NotEnoughFundsCopyWith<$Res> { +class _$Error_NotEnoughFundsCopyWithImpl<$Res> implements $Error_NotEnoughFundsCopyWith<$Res> { _$Error_NotEnoughFundsCopyWithImpl(this._self, this._then); final Error_NotEnoughFunds _self; @@ -351,8 +341,7 @@ class Error_NoSigningKey extends Error { @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && other is Error_NoSigningKey); + return identical(this, other) || (other.runtimeType == runtimeType && other is Error_NoSigningKey); } @override @@ -375,15 +364,11 @@ class Error_Sqlx extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_SqlxCopyWith get copyWith => - _$Error_SqlxCopyWithImpl(this, _$identity); + $Error_SqlxCopyWith get copyWith => _$Error_SqlxCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is Error_Sqlx && - (identical(other.field0, field0) || other.field0 == field0)); + return identical(this, other) || (other.runtimeType == runtimeType && other is Error_Sqlx && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -397,9 +382,7 @@ class Error_Sqlx extends Error { /// @nodoc abstract mixin class $Error_SqlxCopyWith<$Res> implements $ErrorCopyWith<$Res> { - factory $Error_SqlxCopyWith( - Error_Sqlx value, $Res Function(Error_Sqlx) _then) = - _$Error_SqlxCopyWithImpl; + factory $Error_SqlxCopyWith(Error_Sqlx value, $Res Function(Error_Sqlx) _then) = _$Error_SqlxCopyWithImpl; @useResult $Res call({Error field0}); @@ -449,15 +432,11 @@ class Error_Other extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_OtherCopyWith get copyWith => - _$Error_OtherCopyWithImpl(this, _$identity); + $Error_OtherCopyWith get copyWith => _$Error_OtherCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is Error_Other && - (identical(other.field0, field0) || other.field0 == field0)); + return identical(this, other) || (other.runtimeType == runtimeType && other is Error_Other && (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -470,11 +449,8 @@ class Error_Other extends Error { } /// @nodoc -abstract mixin class $Error_OtherCopyWith<$Res> - implements $ErrorCopyWith<$Res> { - factory $Error_OtherCopyWith( - Error_Other value, $Res Function(Error_Other) _then) = - _$Error_OtherCopyWithImpl; +abstract mixin class $Error_OtherCopyWith<$Res> implements $ErrorCopyWith<$Res> { + factory $Error_OtherCopyWith(Error_Other value, $Res Function(Error_Other) _then) = _$Error_OtherCopyWithImpl; @useResult $Res call({Error field0}); diff --git a/lib/store.dart b/lib/store.dart index a9f9d7316..30fc99f23 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -539,8 +539,7 @@ class CurrentHeight extends _$CurrentHeight { } if (!force) { final now = DateTime.now(); - if (_cachedHeight != null && _lastFetch != null && - now.difference(_lastFetch!) < _ttl) { + if (_cachedHeight != null && _lastFetch != null && now.difference(_lastFetch!) < _ttl) { return _cachedHeight; } } @@ -799,8 +798,7 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } await Future.delayed(Duration(seconds: delay)); - } - finally { + } finally { syncInProgress = false; } } @@ -1172,4 +1170,3 @@ Future> pluginMemoSections( final ironwoodActiveProvider = FutureProvider((ref) async { return await isIronwoodActive(c: coinContext.coin); }); - diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index 02f94f519..ff87e7ba0 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -24,8 +24,7 @@ mixin _$SyncState { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SyncStateCopyWith get copyWith => - _$SyncStateCopyWithImpl(this as SyncState, _$identity); + $SyncStateCopyWith get copyWith => _$SyncStateCopyWithImpl(this as SyncState, _$identity); @override bool operator ==(Object other) { @@ -40,8 +39,7 @@ mixin _$SyncState { } @override - int get hashCode => Object.hash(runtimeType, start, end, height, time, - const DeepCollectionEquality().hash(accounts)); + int get hashCode => Object.hash(runtimeType, start, end, height, time, const DeepCollectionEquality().hash(accounts)); @override String toString() { @@ -51,8 +49,7 @@ mixin _$SyncState { /// @nodoc abstract mixin class $SyncStateCopyWith<$Res> { - factory $SyncStateCopyWith(SyncState value, $Res Function(SyncState) _then) = - _$SyncStateCopyWithImpl; + factory $SyncStateCopyWith(SyncState value, $Res Function(SyncState) _then) = _$SyncStateCopyWithImpl; @useResult $Res call({int start, int end, int height, int time, List accounts}); } @@ -191,16 +188,13 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult maybeWhen( - TResult Function( - int start, int end, int height, int time, List accounts)? - $default, { + TResult Function(int start, int end, int height, int time, List accounts)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _SyncState() when $default != null: - return $default( - _that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); case _: return orElse(); } @@ -221,15 +215,12 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult when( - TResult Function( - int start, int end, int height, int time, List accounts) - $default, + TResult Function(int start, int end, int height, int time, List accounts) $default, ) { final _that = this; switch (_that) { case _SyncState(): - return $default( - _that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); } } @@ -247,15 +238,12 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int start, int end, int height, int time, List accounts)? - $default, + TResult? Function(int start, int end, int height, int time, List accounts)? $default, ) { final _that = this; switch (_that) { case _SyncState() when $default != null: - return $default( - _that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); case _: return null; } @@ -265,13 +253,7 @@ extension SyncStatePatterns on SyncState { /// @nodoc class _SyncState implements SyncState { - _SyncState( - {required this.start, - required this.end, - required this.height, - required this.time, - required final List accounts}) - : _accounts = accounts; + _SyncState({required this.start, required this.end, required this.height, required this.time, required final List accounts}) : _accounts = accounts; @override final int start; @@ -294,8 +276,7 @@ class _SyncState implements SyncState { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SyncStateCopyWith<_SyncState> get copyWith => - __$SyncStateCopyWithImpl<_SyncState>(this, _$identity); + _$SyncStateCopyWith<_SyncState> get copyWith => __$SyncStateCopyWithImpl<_SyncState>(this, _$identity); @override bool operator ==(Object other) { @@ -310,8 +291,7 @@ class _SyncState implements SyncState { } @override - int get hashCode => Object.hash(runtimeType, start, end, height, time, - const DeepCollectionEquality().hash(_accounts)); + int get hashCode => Object.hash(runtimeType, start, end, height, time, const DeepCollectionEquality().hash(_accounts)); @override String toString() { @@ -320,11 +300,8 @@ class _SyncState implements SyncState { } /// @nodoc -abstract mixin class _$SyncStateCopyWith<$Res> - implements $SyncStateCopyWith<$Res> { - factory _$SyncStateCopyWith( - _SyncState value, $Res Function(_SyncState) _then) = - __$SyncStateCopyWithImpl; +abstract mixin class _$SyncStateCopyWith<$Res> implements $SyncStateCopyWith<$Res> { + factory _$SyncStateCopyWith(_SyncState value, $Res Function(_SyncState) _then) = __$SyncStateCopyWithImpl; @override @useResult $Res call({int start, int end, int height, int time, List accounts}); @@ -386,8 +363,7 @@ mixin _$SyncProgressAccount { @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') $SyncProgressAccountCopyWith get copyWith => - _$SyncProgressAccountCopyWithImpl( - this as SyncProgressAccount, _$identity); + _$SyncProgressAccountCopyWithImpl(this as SyncProgressAccount, _$identity); @override bool operator ==(Object other) { @@ -402,8 +378,7 @@ mixin _$SyncProgressAccount { } @override - int get hashCode => - Object.hash(runtimeType, account, start, end, height, time); + int get hashCode => Object.hash(runtimeType, account, start, end, height, time); @override String toString() { @@ -413,9 +388,7 @@ mixin _$SyncProgressAccount { /// @nodoc abstract mixin class $SyncProgressAccountCopyWith<$Res> { - factory $SyncProgressAccountCopyWith( - SyncProgressAccount value, $Res Function(SyncProgressAccount) _then) = - _$SyncProgressAccountCopyWithImpl; + factory $SyncProgressAccountCopyWith(SyncProgressAccount value, $Res Function(SyncProgressAccount) _then) = _$SyncProgressAccountCopyWithImpl; @useResult $Res call({Account account, int start, int end, int height, int time}); @@ -423,8 +396,7 @@ abstract mixin class $SyncProgressAccountCopyWith<$Res> { } /// @nodoc -class _$SyncProgressAccountCopyWithImpl<$Res> - implements $SyncProgressAccountCopyWith<$Res> { +class _$SyncProgressAccountCopyWithImpl<$Res> implements $SyncProgressAccountCopyWith<$Res> { _$SyncProgressAccountCopyWithImpl(this._self, this._then); final SyncProgressAccount _self; @@ -567,15 +539,13 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult maybeWhen( - TResult Function(Account account, int start, int end, int height, int time)? - $default, { + TResult Function(Account account, int start, int end, int height, int time)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _SyncProgressAccount() when $default != null: - return $default( - _that.account, _that.start, _that.end, _that.height, _that.time); + return $default(_that.account, _that.start, _that.end, _that.height, _that.time); case _: return orElse(); } @@ -596,14 +566,12 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult when( - TResult Function(Account account, int start, int end, int height, int time) - $default, + TResult Function(Account account, int start, int end, int height, int time) $default, ) { final _that = this; switch (_that) { case _SyncProgressAccount(): - return $default( - _that.account, _that.start, _that.end, _that.height, _that.time); + return $default(_that.account, _that.start, _that.end, _that.height, _that.time); } } @@ -621,15 +589,12 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Account account, int start, int end, int height, int time)? - $default, + TResult? Function(Account account, int start, int end, int height, int time)? $default, ) { final _that = this; switch (_that) { case _SyncProgressAccount() when $default != null: - return $default( - _that.account, _that.start, _that.end, _that.height, _that.time); + return $default(_that.account, _that.start, _that.end, _that.height, _that.time); case _: return null; } @@ -639,13 +604,7 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { /// @nodoc class _SyncProgressAccount extends SyncProgressAccount { - _SyncProgressAccount( - {required this.account, - required this.start, - required this.end, - required this.height, - required this.time}) - : super._(); + _SyncProgressAccount({required this.account, required this.start, required this.end, required this.height, required this.time}) : super._(); @override final Account account; @@ -663,9 +622,7 @@ class _SyncProgressAccount extends SyncProgressAccount { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SyncProgressAccountCopyWith<_SyncProgressAccount> get copyWith => - __$SyncProgressAccountCopyWithImpl<_SyncProgressAccount>( - this, _$identity); + _$SyncProgressAccountCopyWith<_SyncProgressAccount> get copyWith => __$SyncProgressAccountCopyWithImpl<_SyncProgressAccount>(this, _$identity); @override bool operator ==(Object other) { @@ -680,8 +637,7 @@ class _SyncProgressAccount extends SyncProgressAccount { } @override - int get hashCode => - Object.hash(runtimeType, account, start, end, height, time); + int get hashCode => Object.hash(runtimeType, account, start, end, height, time); @override String toString() { @@ -690,11 +646,8 @@ class _SyncProgressAccount extends SyncProgressAccount { } /// @nodoc -abstract mixin class _$SyncProgressAccountCopyWith<$Res> - implements $SyncProgressAccountCopyWith<$Res> { - factory _$SyncProgressAccountCopyWith(_SyncProgressAccount value, - $Res Function(_SyncProgressAccount) _then) = - __$SyncProgressAccountCopyWithImpl; +abstract mixin class _$SyncProgressAccountCopyWith<$Res> implements $SyncProgressAccountCopyWith<$Res> { + factory _$SyncProgressAccountCopyWith(_SyncProgressAccount value, $Res Function(_SyncProgressAccount) _then) = __$SyncProgressAccountCopyWithImpl; @override @useResult $Res call({Account account, int start, int end, int height, int time}); @@ -704,8 +657,7 @@ abstract mixin class _$SyncProgressAccountCopyWith<$Res> } /// @nodoc -class __$SyncProgressAccountCopyWithImpl<$Res> - implements _$SyncProgressAccountCopyWith<$Res> { +class __$SyncProgressAccountCopyWithImpl<$Res> implements _$SyncProgressAccountCopyWith<$Res> { __$SyncProgressAccountCopyWithImpl(this._self, this._then); final _SyncProgressAccount _self; @@ -772,8 +724,7 @@ mixin _$AccountData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountDataCopyWith get copyWith => - _$AccountDataCopyWithImpl(this as AccountData, _$identity); + $AccountDataCopyWith get copyWith => _$AccountDataCopyWithImpl(this as AccountData, _$identity); @override bool operator ==(Object other) { @@ -783,26 +734,16 @@ mixin _$AccountData { (identical(other.account, account) || other.account == account) && (identical(other.pool, pool) || other.pool == pool) && (identical(other.balance, balance) || other.balance == balance) && - const DeepCollectionEquality() - .equals(other.transactions, transactions) && + const DeepCollectionEquality().equals(other.transactions, transactions) && const DeepCollectionEquality().equals(other.memos, memos) && const DeepCollectionEquality().equals(other.notes, notes) && const DeepCollectionEquality().equals(other.zsas, zsas) && - (identical(other.frostParams, frostParams) || - other.frostParams == frostParams)); + (identical(other.frostParams, frostParams) || other.frostParams == frostParams)); } @override - int get hashCode => Object.hash( - runtimeType, - account, - pool, - balance, - const DeepCollectionEquality().hash(transactions), - const DeepCollectionEquality().hash(memos), - const DeepCollectionEquality().hash(notes), - const DeepCollectionEquality().hash(zsas), - frostParams); + int get hashCode => Object.hash(runtimeType, account, pool, balance, const DeepCollectionEquality().hash(transactions), + const DeepCollectionEquality().hash(memos), const DeepCollectionEquality().hash(notes), const DeepCollectionEquality().hash(zsas), frostParams); @override String toString() { @@ -812,9 +753,7 @@ mixin _$AccountData { /// @nodoc abstract mixin class $AccountDataCopyWith<$Res> { - factory $AccountDataCopyWith( - AccountData value, $Res Function(AccountData) _then) = - _$AccountDataCopyWithImpl; + factory $AccountDataCopyWith(AccountData value, $Res Function(AccountData) _then) = _$AccountDataCopyWithImpl; @useResult $Res call( {Account account, @@ -1003,14 +942,7 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult maybeWhen( - TResult Function( - Account account, - int pool, - PoolBalance balance, - List transactions, - List memos, - List notes, - List zsas, + TResult Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, FrostParams? frostParams)? $default, { required TResult orElse(), @@ -1018,15 +950,7 @@ extension AccountDataPatterns on AccountData { final _that = this; switch (_that) { case _AccountData() when $default != null: - return $default( - _that.account, - _that.pool, - _that.balance, - _that.transactions, - _that.memos, - _that.notes, - _that.zsas, - _that.frostParams); + return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); case _: return orElse(); } @@ -1047,29 +971,14 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult when( - TResult Function( - Account account, - int pool, - PoolBalance balance, - List transactions, - List memos, - List notes, - List zsas, + TResult Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, FrostParams? frostParams) $default, ) { final _that = this; switch (_that) { case _AccountData(): - return $default( - _that.account, - _that.pool, - _that.balance, - _that.transactions, - _that.memos, - _that.notes, - _that.zsas, - _that.frostParams); + return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); } } @@ -1087,29 +996,14 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Account account, - int pool, - PoolBalance balance, - List transactions, - List memos, - List notes, - List zsas, + TResult? Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, FrostParams? frostParams)? $default, ) { final _that = this; switch (_that) { case _AccountData() when $default != null: - return $default( - _that.account, - _that.pool, - _that.balance, - _that.transactions, - _that.memos, - _that.notes, - _that.zsas, - _that.frostParams); + return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); case _: return null; } @@ -1179,8 +1073,7 @@ class _AccountData implements AccountData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountDataCopyWith<_AccountData> get copyWith => - __$AccountDataCopyWithImpl<_AccountData>(this, _$identity); + _$AccountDataCopyWith<_AccountData> get copyWith => __$AccountDataCopyWithImpl<_AccountData>(this, _$identity); @override bool operator ==(Object other) { @@ -1190,26 +1083,16 @@ class _AccountData implements AccountData { (identical(other.account, account) || other.account == account) && (identical(other.pool, pool) || other.pool == pool) && (identical(other.balance, balance) || other.balance == balance) && - const DeepCollectionEquality() - .equals(other._transactions, _transactions) && + const DeepCollectionEquality().equals(other._transactions, _transactions) && const DeepCollectionEquality().equals(other._memos, _memos) && const DeepCollectionEquality().equals(other._notes, _notes) && const DeepCollectionEquality().equals(other._zsas, _zsas) && - (identical(other.frostParams, frostParams) || - other.frostParams == frostParams)); + (identical(other.frostParams, frostParams) || other.frostParams == frostParams)); } @override - int get hashCode => Object.hash( - runtimeType, - account, - pool, - balance, - const DeepCollectionEquality().hash(_transactions), - const DeepCollectionEquality().hash(_memos), - const DeepCollectionEquality().hash(_notes), - const DeepCollectionEquality().hash(_zsas), - frostParams); + int get hashCode => Object.hash(runtimeType, account, pool, balance, const DeepCollectionEquality().hash(_transactions), + const DeepCollectionEquality().hash(_memos), const DeepCollectionEquality().hash(_notes), const DeepCollectionEquality().hash(_zsas), frostParams); @override String toString() { @@ -1218,11 +1101,8 @@ class _AccountData implements AccountData { } /// @nodoc -abstract mixin class _$AccountDataCopyWith<$Res> - implements $AccountDataCopyWith<$Res> { - factory _$AccountDataCopyWith( - _AccountData value, $Res Function(_AccountData) _then) = - __$AccountDataCopyWithImpl; +abstract mixin class _$AccountDataCopyWith<$Res> implements $AccountDataCopyWith<$Res> { + factory _$AccountDataCopyWith(_AccountData value, $Res Function(_AccountData) _then) = __$AccountDataCopyWithImpl; @override @useResult $Res call( @@ -1352,8 +1232,7 @@ mixin _$AppSettings { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AppSettingsCopyWith get copyWith => - _$AppSettingsCopyWithImpl(this as AppSettings, _$identity); + $AppSettingsCopyWith get copyWith => _$AppSettingsCopyWithImpl(this as AppSettings, _$identity); @override bool operator ==(Object other) { @@ -1362,39 +1241,26 @@ mixin _$AppSettings { other is AppSettings && (identical(other.dbName, dbName) || other.dbName == dbName) && (identical(other.net, net) || other.net == net) && - (identical(other.isLightNode, isLightNode) || - other.isLightNode == isLightNode) && + (identical(other.isLightNode, isLightNode) || other.isLightNode == isLightNode) && (identical(other.lwd, lwd) || other.lwd == lwd) && - (identical(other.blockExplorer, blockExplorer) || - other.blockExplorer == blockExplorer) && - (identical(other.syncInterval, syncInterval) || - other.syncInterval == syncInterval) && - (identical(other.actionsPerSync, actionsPerSync) || - other.actionsPerSync == actionsPerSync) && + (identical(other.blockExplorer, blockExplorer) || other.blockExplorer == blockExplorer) && + (identical(other.syncInterval, syncInterval) || other.syncInterval == syncInterval) && + (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy) && - (identical(other.coingecko, coingecko) || - other.coingecko == coingecko) && - (identical(other.recovery, recovery) || - other.recovery == recovery) && + (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && + (identical(other.recovery, recovery) || other.recovery == recovery) && (identical(other.needPin, needPin) || other.needPin == needPin) && - (identical(other.pinUnlockedAt, pinUnlockedAt) || - other.pinUnlockedAt == pinUnlockedAt) && + (identical(other.pinUnlockedAt, pinUnlockedAt) || other.pinUnlockedAt == pinUnlockedAt) && (identical(other.offline, offline) || other.offline == offline) && (identical(other.getFx, getFx) || other.getFx == getFx) && - (identical(other.qrSettings, qrSettings) || - other.qrSettings == qrSettings) && + (identical(other.qrSettings, qrSettings) || other.qrSettings == qrSettings) && (identical(other.vault, vault) || other.vault == vault) && - (identical(other.expertMode, expertMode) || - other.expertMode == expertMode) && - (identical(other.paletteName, paletteName) || - other.paletteName == paletteName) && - (identical(other.darkMode, darkMode) || - other.darkMode == darkMode) && - (identical(other.transactionTableMode, transactionTableMode) || - other.transactionTableMode == transactionTableMode) && - (identical(other.currency, currency) || - other.currency == currency)); + (identical(other.expertMode, expertMode) || other.expertMode == expertMode) && + (identical(other.paletteName, paletteName) || other.paletteName == paletteName) && + (identical(other.darkMode, darkMode) || other.darkMode == darkMode) && + (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && + (identical(other.currency, currency) || other.currency == currency)); } @override @@ -1432,9 +1298,7 @@ mixin _$AppSettings { /// @nodoc abstract mixin class $AppSettingsCopyWith<$Res> { - factory $AppSettingsCopyWith( - AppSettings value, $Res Function(AppSettings) _then) = - _$AppSettingsCopyWithImpl; + factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl; @useResult $Res call( {String dbName, @@ -1967,8 +1831,7 @@ class _AppSettings implements AppSettings { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AppSettingsCopyWith<_AppSettings> get copyWith => - __$AppSettingsCopyWithImpl<_AppSettings>(this, _$identity); + _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_AppSettings>(this, _$identity); @override bool operator ==(Object other) { @@ -1977,39 +1840,26 @@ class _AppSettings implements AppSettings { other is _AppSettings && (identical(other.dbName, dbName) || other.dbName == dbName) && (identical(other.net, net) || other.net == net) && - (identical(other.isLightNode, isLightNode) || - other.isLightNode == isLightNode) && + (identical(other.isLightNode, isLightNode) || other.isLightNode == isLightNode) && (identical(other.lwd, lwd) || other.lwd == lwd) && - (identical(other.blockExplorer, blockExplorer) || - other.blockExplorer == blockExplorer) && - (identical(other.syncInterval, syncInterval) || - other.syncInterval == syncInterval) && - (identical(other.actionsPerSync, actionsPerSync) || - other.actionsPerSync == actionsPerSync) && + (identical(other.blockExplorer, blockExplorer) || other.blockExplorer == blockExplorer) && + (identical(other.syncInterval, syncInterval) || other.syncInterval == syncInterval) && + (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy) && - (identical(other.coingecko, coingecko) || - other.coingecko == coingecko) && - (identical(other.recovery, recovery) || - other.recovery == recovery) && + (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && + (identical(other.recovery, recovery) || other.recovery == recovery) && (identical(other.needPin, needPin) || other.needPin == needPin) && - (identical(other.pinUnlockedAt, pinUnlockedAt) || - other.pinUnlockedAt == pinUnlockedAt) && + (identical(other.pinUnlockedAt, pinUnlockedAt) || other.pinUnlockedAt == pinUnlockedAt) && (identical(other.offline, offline) || other.offline == offline) && (identical(other.getFx, getFx) || other.getFx == getFx) && - (identical(other.qrSettings, qrSettings) || - other.qrSettings == qrSettings) && + (identical(other.qrSettings, qrSettings) || other.qrSettings == qrSettings) && (identical(other.vault, vault) || other.vault == vault) && - (identical(other.expertMode, expertMode) || - other.expertMode == expertMode) && - (identical(other.paletteName, paletteName) || - other.paletteName == paletteName) && - (identical(other.darkMode, darkMode) || - other.darkMode == darkMode) && - (identical(other.transactionTableMode, transactionTableMode) || - other.transactionTableMode == transactionTableMode) && - (identical(other.currency, currency) || - other.currency == currency)); + (identical(other.expertMode, expertMode) || other.expertMode == expertMode) && + (identical(other.paletteName, paletteName) || other.paletteName == paletteName) && + (identical(other.darkMode, darkMode) || other.darkMode == darkMode) && + (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && + (identical(other.currency, currency) || other.currency == currency)); } @override @@ -2046,11 +1896,8 @@ class _AppSettings implements AppSettings { } /// @nodoc -abstract mixin class _$AppSettingsCopyWith<$Res> - implements $AppSettingsCopyWith<$Res> { - factory _$AppSettingsCopyWith( - _AppSettings value, $Res Function(_AppSettings) _then) = - __$AppSettingsCopyWithImpl; +abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith<$Res> { + factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl; @override @useResult $Res call( @@ -2229,9 +2076,7 @@ mixin _$MempoolState { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolStateCopyWith get copyWith => - _$MempoolStateCopyWithImpl( - this as MempoolState, _$identity); + $MempoolStateCopyWith get copyWith => _$MempoolStateCopyWithImpl(this as MempoolState, _$identity); @override bool operator ==(Object other) { @@ -2239,18 +2084,13 @@ mixin _$MempoolState { (other.runtimeType == runtimeType && other is MempoolState && (identical(other.running, running) || other.running == running) && - const DeepCollectionEquality() - .equals(other.unconfirmedFunds, unconfirmedFunds) && - const DeepCollectionEquality() - .equals(other.unconfirmedTx, unconfirmedTx)); + const DeepCollectionEquality().equals(other.unconfirmedFunds, unconfirmedFunds) && + const DeepCollectionEquality().equals(other.unconfirmedTx, unconfirmedTx)); } @override - int get hashCode => Object.hash( - runtimeType, - running, - const DeepCollectionEquality().hash(unconfirmedFunds), - const DeepCollectionEquality().hash(unconfirmedTx)); + int get hashCode => + Object.hash(runtimeType, running, const DeepCollectionEquality().hash(unconfirmedFunds), const DeepCollectionEquality().hash(unconfirmedTx)); @override String toString() { @@ -2260,14 +2100,9 @@ mixin _$MempoolState { /// @nodoc abstract mixin class $MempoolStateCopyWith<$Res> { - factory $MempoolStateCopyWith( - MempoolState value, $Res Function(MempoolState) _then) = - _$MempoolStateCopyWithImpl; + factory $MempoolStateCopyWith(MempoolState value, $Res Function(MempoolState) _then) = _$MempoolStateCopyWithImpl; @useResult - $Res call( - {bool running, - Map unconfirmedFunds, - List<(String, String, int)> unconfirmedTx}); + $Res call({bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx}); } /// @nodoc @@ -2394,16 +2229,13 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult maybeWhen( - TResult Function(bool running, Map unconfirmedFunds, - List<(String, String, int)> unconfirmedTx)? - $default, { + TResult Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _MempoolState() when $default != null: - return $default( - _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); case _: return orElse(); } @@ -2424,15 +2256,12 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult when( - TResult Function(bool running, Map unconfirmedFunds, - List<(String, String, int)> unconfirmedTx) - $default, + TResult Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx) $default, ) { final _that = this; switch (_that) { case _MempoolState(): - return $default( - _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); } } @@ -2450,15 +2279,12 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(bool running, Map unconfirmedFunds, - List<(String, String, int)> unconfirmedTx)? - $default, + TResult? Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx)? $default, ) { final _that = this; switch (_that) { case _MempoolState() when $default != null: - return $default( - _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); case _: return null; } @@ -2468,10 +2294,7 @@ extension MempoolStatePatterns on MempoolState { /// @nodoc class _MempoolState implements MempoolState { - _MempoolState( - {required this.running, - required this.unconfirmedFunds, - required this.unconfirmedTx}); + _MempoolState({required this.running, required this.unconfirmedFunds, required this.unconfirmedTx}); @override final bool running; @@ -2485,8 +2308,7 @@ class _MempoolState implements MempoolState { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MempoolStateCopyWith<_MempoolState> get copyWith => - __$MempoolStateCopyWithImpl<_MempoolState>(this, _$identity); + _$MempoolStateCopyWith<_MempoolState> get copyWith => __$MempoolStateCopyWithImpl<_MempoolState>(this, _$identity); @override bool operator ==(Object other) { @@ -2494,18 +2316,13 @@ class _MempoolState implements MempoolState { (other.runtimeType == runtimeType && other is _MempoolState && (identical(other.running, running) || other.running == running) && - const DeepCollectionEquality() - .equals(other.unconfirmedFunds, unconfirmedFunds) && - const DeepCollectionEquality() - .equals(other.unconfirmedTx, unconfirmedTx)); + const DeepCollectionEquality().equals(other.unconfirmedFunds, unconfirmedFunds) && + const DeepCollectionEquality().equals(other.unconfirmedTx, unconfirmedTx)); } @override - int get hashCode => Object.hash( - runtimeType, - running, - const DeepCollectionEquality().hash(unconfirmedFunds), - const DeepCollectionEquality().hash(unconfirmedTx)); + int get hashCode => + Object.hash(runtimeType, running, const DeepCollectionEquality().hash(unconfirmedFunds), const DeepCollectionEquality().hash(unconfirmedTx)); @override String toString() { @@ -2514,22 +2331,15 @@ class _MempoolState implements MempoolState { } /// @nodoc -abstract mixin class _$MempoolStateCopyWith<$Res> - implements $MempoolStateCopyWith<$Res> { - factory _$MempoolStateCopyWith( - _MempoolState value, $Res Function(_MempoolState) _then) = - __$MempoolStateCopyWithImpl; +abstract mixin class _$MempoolStateCopyWith<$Res> implements $MempoolStateCopyWith<$Res> { + factory _$MempoolStateCopyWith(_MempoolState value, $Res Function(_MempoolState) _then) = __$MempoolStateCopyWithImpl; @override @useResult - $Res call( - {bool running, - Map unconfirmedFunds, - List<(String, String, int)> unconfirmedTx}); + $Res call({bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx}); } /// @nodoc -class __$MempoolStateCopyWithImpl<$Res> - implements _$MempoolStateCopyWith<$Res> { +class __$MempoolStateCopyWithImpl<$Res> implements _$MempoolStateCopyWith<$Res> { __$MempoolStateCopyWithImpl(this._self, this._then); final _MempoolState _self; @@ -2572,26 +2382,21 @@ mixin _$AccountsPageData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountsPageDataCopyWith get copyWith => - _$AccountsPageDataCopyWithImpl( - this as AccountsPageData, _$identity); + $AccountsPageDataCopyWith get copyWith => _$AccountsPageDataCopyWithImpl(this as AccountsPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is AccountsPageData && - (identical(other.settings, settings) || - other.settings == settings) && + (identical(other.settings, settings) || other.settings == settings) && const DeepCollectionEquality().equals(other.accounts, accounts) && (identical(other.price, price) || other.price == price) && - (identical(other.selectedFolder, selectedFolder) || - other.selectedFolder == selectedFolder)); + (identical(other.selectedFolder, selectedFolder) || other.selectedFolder == selectedFolder)); } @override - int get hashCode => Object.hash(runtimeType, settings, - const DeepCollectionEquality().hash(accounts), price, selectedFolder); + int get hashCode => Object.hash(runtimeType, settings, const DeepCollectionEquality().hash(accounts), price, selectedFolder); @override String toString() { @@ -2601,23 +2406,16 @@ mixin _$AccountsPageData { /// @nodoc abstract mixin class $AccountsPageDataCopyWith<$Res> { - factory $AccountsPageDataCopyWith( - AccountsPageData value, $Res Function(AccountsPageData) _then) = - _$AccountsPageDataCopyWithImpl; + factory $AccountsPageDataCopyWith(AccountsPageData value, $Res Function(AccountsPageData) _then) = _$AccountsPageDataCopyWithImpl; @useResult - $Res call( - {AppSettings settings, - List accounts, - double? price, - Folder? selectedFolder}); + $Res call({AppSettings settings, List accounts, double? price, Folder? selectedFolder}); $AppSettingsCopyWith<$Res> get settings; $FolderCopyWith<$Res>? get selectedFolder; } /// @nodoc -class _$AccountsPageDataCopyWithImpl<$Res> - implements $AccountsPageDataCopyWith<$Res> { +class _$AccountsPageDataCopyWithImpl<$Res> implements $AccountsPageDataCopyWith<$Res> { _$AccountsPageDataCopyWithImpl(this._self, this._then); final AccountsPageData _self; @@ -2769,16 +2567,13 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function(AppSettings settings, List accounts, - double? price, Folder? selectedFolder)? - $default, { + TResult Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountsPageData() when $default != null: - return $default( - _that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); case _: return orElse(); } @@ -2799,15 +2594,12 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult when( - TResult Function(AppSettings settings, List accounts, - double? price, Folder? selectedFolder) - $default, + TResult Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder) $default, ) { final _that = this; switch (_that) { case _AccountsPageData(): - return $default( - _that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); } } @@ -2825,15 +2617,12 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(AppSettings settings, List accounts, - double? price, Folder? selectedFolder)? - $default, + TResult? Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder)? $default, ) { final _that = this; switch (_that) { case _AccountsPageData() when $default != null: - return $default( - _that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); case _: return null; } @@ -2843,11 +2632,7 @@ extension AccountsPageDataPatterns on AccountsPageData { /// @nodoc class _AccountsPageData implements AccountsPageData { - const _AccountsPageData( - {required this.settings, - required final List accounts, - required this.price, - required this.selectedFolder}) + const _AccountsPageData({required this.settings, required final List accounts, required this.price, required this.selectedFolder}) : _accounts = accounts; @override @@ -2870,25 +2655,21 @@ class _AccountsPageData implements AccountsPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountsPageDataCopyWith<_AccountsPageData> get copyWith => - __$AccountsPageDataCopyWithImpl<_AccountsPageData>(this, _$identity); + _$AccountsPageDataCopyWith<_AccountsPageData> get copyWith => __$AccountsPageDataCopyWithImpl<_AccountsPageData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _AccountsPageData && - (identical(other.settings, settings) || - other.settings == settings) && + (identical(other.settings, settings) || other.settings == settings) && const DeepCollectionEquality().equals(other._accounts, _accounts) && (identical(other.price, price) || other.price == price) && - (identical(other.selectedFolder, selectedFolder) || - other.selectedFolder == selectedFolder)); + (identical(other.selectedFolder, selectedFolder) || other.selectedFolder == selectedFolder)); } @override - int get hashCode => Object.hash(runtimeType, settings, - const DeepCollectionEquality().hash(_accounts), price, selectedFolder); + int get hashCode => Object.hash(runtimeType, settings, const DeepCollectionEquality().hash(_accounts), price, selectedFolder); @override String toString() { @@ -2897,18 +2678,11 @@ class _AccountsPageData implements AccountsPageData { } /// @nodoc -abstract mixin class _$AccountsPageDataCopyWith<$Res> - implements $AccountsPageDataCopyWith<$Res> { - factory _$AccountsPageDataCopyWith( - _AccountsPageData value, $Res Function(_AccountsPageData) _then) = - __$AccountsPageDataCopyWithImpl; +abstract mixin class _$AccountsPageDataCopyWith<$Res> implements $AccountsPageDataCopyWith<$Res> { + factory _$AccountsPageDataCopyWith(_AccountsPageData value, $Res Function(_AccountsPageData) _then) = __$AccountsPageDataCopyWithImpl; @override @useResult - $Res call( - {AppSettings settings, - List accounts, - double? price, - Folder? selectedFolder}); + $Res call({AppSettings settings, List accounts, double? price, Folder? selectedFolder}); @override $AppSettingsCopyWith<$Res> get settings; @@ -2917,8 +2691,7 @@ abstract mixin class _$AccountsPageDataCopyWith<$Res> } /// @nodoc -class __$AccountsPageDataCopyWithImpl<$Res> - implements _$AccountsPageDataCopyWith<$Res> { +class __$AccountsPageDataCopyWithImpl<$Res> implements _$AccountsPageDataCopyWith<$Res> { __$AccountsPageDataCopyWithImpl(this._self, this._then); final _AccountsPageData _self; @@ -2988,24 +2761,19 @@ mixin _$BasicAccountData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $BasicAccountDataCopyWith get copyWith => - _$BasicAccountDataCopyWithImpl( - this as BasicAccountData, _$identity); + $BasicAccountDataCopyWith get copyWith => _$BasicAccountDataCopyWithImpl(this as BasicAccountData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is BasicAccountData && - const DeepCollectionEquality() - .equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount)); + const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount)); } @override - int get hashCode => Object.hash(runtimeType, - const DeepCollectionEquality().hash(allAccounts), currentAccount); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount); @override String toString() { @@ -3015,9 +2783,7 @@ mixin _$BasicAccountData { /// @nodoc abstract mixin class $BasicAccountDataCopyWith<$Res> { - factory $BasicAccountDataCopyWith( - BasicAccountData value, $Res Function(BasicAccountData) _then) = - _$BasicAccountDataCopyWithImpl; + factory $BasicAccountDataCopyWith(BasicAccountData value, $Res Function(BasicAccountData) _then) = _$BasicAccountDataCopyWithImpl; @useResult $Res call({List allAccounts, AccountData? currentAccount}); @@ -3025,8 +2791,7 @@ abstract mixin class $BasicAccountDataCopyWith<$Res> { } /// @nodoc -class _$BasicAccountDataCopyWithImpl<$Res> - implements $BasicAccountDataCopyWith<$Res> { +class _$BasicAccountDataCopyWithImpl<$Res> implements $BasicAccountDataCopyWith<$Res> { _$BasicAccountDataCopyWithImpl(this._self, this._then); final BasicAccountData _self; @@ -3158,8 +2923,7 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult maybeWhen( - TResult Function(List allAccounts, AccountData? currentAccount)? - $default, { + TResult Function(List allAccounts, AccountData? currentAccount)? $default, { required TResult orElse(), }) { final _that = this; @@ -3186,8 +2950,7 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount) - $default, + TResult Function(List allAccounts, AccountData? currentAccount) $default, ) { final _that = this; switch (_that) { @@ -3210,8 +2973,7 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(List allAccounts, AccountData? currentAccount)? - $default, + TResult? Function(List allAccounts, AccountData? currentAccount)? $default, ) { final _that = this; switch (_that) { @@ -3226,9 +2988,7 @@ extension BasicAccountDataPatterns on BasicAccountData { /// @nodoc class _BasicAccountData implements BasicAccountData { - const _BasicAccountData( - {required final List allAccounts, required this.currentAccount}) - : _allAccounts = allAccounts; + const _BasicAccountData({required final List allAccounts, required this.currentAccount}) : _allAccounts = allAccounts; final List _allAccounts; @override @@ -3246,23 +3006,19 @@ class _BasicAccountData implements BasicAccountData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$BasicAccountDataCopyWith<_BasicAccountData> get copyWith => - __$BasicAccountDataCopyWithImpl<_BasicAccountData>(this, _$identity); + _$BasicAccountDataCopyWith<_BasicAccountData> get copyWith => __$BasicAccountDataCopyWithImpl<_BasicAccountData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _BasicAccountData && - const DeepCollectionEquality() - .equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount)); + const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount)); } @override - int get hashCode => Object.hash(runtimeType, - const DeepCollectionEquality().hash(_allAccounts), currentAccount); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount); @override String toString() { @@ -3271,11 +3027,8 @@ class _BasicAccountData implements BasicAccountData { } /// @nodoc -abstract mixin class _$BasicAccountDataCopyWith<$Res> - implements $BasicAccountDataCopyWith<$Res> { - factory _$BasicAccountDataCopyWith( - _BasicAccountData value, $Res Function(_BasicAccountData) _then) = - __$BasicAccountDataCopyWithImpl; +abstract mixin class _$BasicAccountDataCopyWith<$Res> implements $BasicAccountDataCopyWith<$Res> { + factory _$BasicAccountDataCopyWith(_BasicAccountData value, $Res Function(_BasicAccountData) _then) = __$BasicAccountDataCopyWithImpl; @override @useResult $Res call({List allAccounts, AccountData? currentAccount}); @@ -3285,8 +3038,7 @@ abstract mixin class _$BasicAccountDataCopyWith<$Res> } /// @nodoc -class __$BasicAccountDataCopyWithImpl<$Res> - implements _$BasicAccountDataCopyWith<$Res> { +class __$BasicAccountDataCopyWithImpl<$Res> implements _$BasicAccountDataCopyWith<$Res> { __$BasicAccountDataCopyWithImpl(this._self, this._then); final _BasicAccountData _self; @@ -3337,29 +3089,20 @@ mixin _$AccountPageData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountPageDataCopyWith get copyWith => - _$AccountPageDataCopyWithImpl( - this as AccountPageData, _$identity); + $AccountPageDataCopyWith get copyWith => _$AccountPageDataCopyWithImpl(this as AccountPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is AccountPageData && - const DeepCollectionEquality() - .equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || - other.syncState == syncState)); + const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || other.syncState == syncState)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(allAccounts), - currentAccount, - syncState); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount, syncState); @override String toString() { @@ -3369,22 +3112,16 @@ mixin _$AccountPageData { /// @nodoc abstract mixin class $AccountPageDataCopyWith<$Res> { - factory $AccountPageDataCopyWith( - AccountPageData value, $Res Function(AccountPageData) _then) = - _$AccountPageDataCopyWithImpl; + factory $AccountPageDataCopyWith(AccountPageData value, $Res Function(AccountPageData) _then) = _$AccountPageDataCopyWithImpl; @useResult - $Res call( - {List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState}); + $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState}); $AccountDataCopyWith<$Res>? get currentAccount; $SyncProgressAccountCopyWith<$Res>? get syncState; } /// @nodoc -class _$AccountPageDataCopyWithImpl<$Res> - implements $AccountPageDataCopyWith<$Res> { +class _$AccountPageDataCopyWithImpl<$Res> implements $AccountPageDataCopyWith<$Res> { _$AccountPageDataCopyWithImpl(this._self, this._then); final AccountPageData _self; @@ -3535,16 +3272,13 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function(List allAccounts, AccountData? currentAccount, - SyncProgressAccount? syncState)? - $default, { + TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountPageData() when $default != null: - return $default( - _that.allAccounts, _that.currentAccount, _that.syncState); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState); case _: return orElse(); } @@ -3565,15 +3299,12 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount, - SyncProgressAccount? syncState) - $default, + TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState) $default, ) { final _that = this; switch (_that) { case _AccountPageData(): - return $default( - _that.allAccounts, _that.currentAccount, _that.syncState); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState); } } @@ -3591,15 +3322,12 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(List allAccounts, AccountData? currentAccount, - SyncProgressAccount? syncState)? - $default, + TResult? Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState)? $default, ) { final _that = this; switch (_that) { case _AccountPageData() when $default != null: - return $default( - _that.allAccounts, _that.currentAccount, _that.syncState); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState); case _: return null; } @@ -3609,11 +3337,7 @@ extension AccountPageDataPatterns on AccountPageData { /// @nodoc class _AccountPageData implements AccountPageData { - const _AccountPageData( - {required final List allAccounts, - required this.currentAccount, - required this.syncState}) - : _allAccounts = allAccounts; + const _AccountPageData({required final List allAccounts, required this.currentAccount, required this.syncState}) : _allAccounts = allAccounts; final List _allAccounts; @override @@ -3633,28 +3357,20 @@ class _AccountPageData implements AccountPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountPageDataCopyWith<_AccountPageData> get copyWith => - __$AccountPageDataCopyWithImpl<_AccountPageData>(this, _$identity); + _$AccountPageDataCopyWith<_AccountPageData> get copyWith => __$AccountPageDataCopyWithImpl<_AccountPageData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _AccountPageData && - const DeepCollectionEquality() - .equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || - other.syncState == syncState)); + const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || other.syncState == syncState)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_allAccounts), - currentAccount, - syncState); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount, syncState); @override String toString() { @@ -3663,17 +3379,11 @@ class _AccountPageData implements AccountPageData { } /// @nodoc -abstract mixin class _$AccountPageDataCopyWith<$Res> - implements $AccountPageDataCopyWith<$Res> { - factory _$AccountPageDataCopyWith( - _AccountPageData value, $Res Function(_AccountPageData) _then) = - __$AccountPageDataCopyWithImpl; +abstract mixin class _$AccountPageDataCopyWith<$Res> implements $AccountPageDataCopyWith<$Res> { + factory _$AccountPageDataCopyWith(_AccountPageData value, $Res Function(_AccountPageData) _then) = __$AccountPageDataCopyWithImpl; @override @useResult - $Res call( - {List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState}); + $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState}); @override $AccountDataCopyWith<$Res>? get currentAccount; @@ -3682,8 +3392,7 @@ abstract mixin class _$AccountPageDataCopyWith<$Res> } /// @nodoc -class __$AccountPageDataCopyWithImpl<$Res> - implements _$AccountPageDataCopyWith<$Res> { +class __$AccountPageDataCopyWithImpl<$Res> implements _$AccountPageDataCopyWith<$Res> { __$AccountPageDataCopyWithImpl(this._self, this._then); final _AccountPageData _self; @@ -3756,32 +3465,22 @@ mixin _$FullAccountPageData { @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') $FullAccountPageDataCopyWith get copyWith => - _$FullAccountPageDataCopyWithImpl( - this as FullAccountPageData, _$identity); + _$FullAccountPageDataCopyWithImpl(this as FullAccountPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is FullAccountPageData && - const DeepCollectionEquality() - .equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || - other.syncState == syncState) && + const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || other.syncState == syncState) && (identical(other.price, price) || other.price == price) && (identical(other.mempool, mempool) || other.mempool == mempool)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(allAccounts), - currentAccount, - syncState, - price, - mempool); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount, syncState, price, mempool); @override String toString() { @@ -3791,16 +3490,9 @@ mixin _$FullAccountPageData { /// @nodoc abstract mixin class $FullAccountPageDataCopyWith<$Res> { - factory $FullAccountPageDataCopyWith( - FullAccountPageData value, $Res Function(FullAccountPageData) _then) = - _$FullAccountPageDataCopyWithImpl; + factory $FullAccountPageDataCopyWith(FullAccountPageData value, $Res Function(FullAccountPageData) _then) = _$FullAccountPageDataCopyWithImpl; @useResult - $Res call( - {List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState, - double? price, - MempoolState mempool}); + $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool}); $AccountDataCopyWith<$Res>? get currentAccount; $SyncProgressAccountCopyWith<$Res>? get syncState; @@ -3808,8 +3500,7 @@ abstract mixin class $FullAccountPageDataCopyWith<$Res> { } /// @nodoc -class _$FullAccountPageDataCopyWithImpl<$Res> - implements $FullAccountPageDataCopyWith<$Res> { +class _$FullAccountPageDataCopyWithImpl<$Res> implements $FullAccountPageDataCopyWith<$Res> { _$FullAccountPageDataCopyWithImpl(this._self, this._then); final FullAccountPageData _self; @@ -3980,20 +3671,13 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function( - List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState, - double? price, - MempoolState mempool)? - $default, { + TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _FullAccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, - _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); case _: return orElse(); } @@ -4014,15 +3698,12 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount, - SyncProgressAccount? syncState, double? price, MempoolState mempool) - $default, + TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool) $default, ) { final _that = this; switch (_that) { case _FullAccountPageData(): - return $default(_that.allAccounts, _that.currentAccount, - _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); } } @@ -4040,19 +3721,12 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState, - double? price, - MempoolState mempool)? - $default, + TResult? Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool)? $default, ) { final _that = this; switch (_that) { case _FullAccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, - _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); case _: return null; } @@ -4063,11 +3737,7 @@ extension FullAccountPageDataPatterns on FullAccountPageData { class _FullAccountPageData implements FullAccountPageData { const _FullAccountPageData( - {required final List allAccounts, - required this.currentAccount, - required this.syncState, - required this.price, - required this.mempool}) + {required final List allAccounts, required this.currentAccount, required this.syncState, required this.price, required this.mempool}) : _allAccounts = allAccounts; final List _allAccounts; @@ -4092,33 +3762,22 @@ class _FullAccountPageData implements FullAccountPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FullAccountPageDataCopyWith<_FullAccountPageData> get copyWith => - __$FullAccountPageDataCopyWithImpl<_FullAccountPageData>( - this, _$identity); + _$FullAccountPageDataCopyWith<_FullAccountPageData> get copyWith => __$FullAccountPageDataCopyWithImpl<_FullAccountPageData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _FullAccountPageData && - const DeepCollectionEquality() - .equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || - other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || - other.syncState == syncState) && + const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || other.syncState == syncState) && (identical(other.price, price) || other.price == price) && (identical(other.mempool, mempool) || other.mempool == mempool)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_allAccounts), - currentAccount, - syncState, - price, - mempool); + int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount, syncState, price, mempool); @override String toString() { @@ -4127,19 +3786,11 @@ class _FullAccountPageData implements FullAccountPageData { } /// @nodoc -abstract mixin class _$FullAccountPageDataCopyWith<$Res> - implements $FullAccountPageDataCopyWith<$Res> { - factory _$FullAccountPageDataCopyWith(_FullAccountPageData value, - $Res Function(_FullAccountPageData) _then) = - __$FullAccountPageDataCopyWithImpl; +abstract mixin class _$FullAccountPageDataCopyWith<$Res> implements $FullAccountPageDataCopyWith<$Res> { + factory _$FullAccountPageDataCopyWith(_FullAccountPageData value, $Res Function(_FullAccountPageData) _then) = __$FullAccountPageDataCopyWithImpl; @override @useResult - $Res call( - {List allAccounts, - AccountData? currentAccount, - SyncProgressAccount? syncState, - double? price, - MempoolState mempool}); + $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool}); @override $AccountDataCopyWith<$Res>? get currentAccount; @@ -4150,8 +3801,7 @@ abstract mixin class _$FullAccountPageDataCopyWith<$Res> } /// @nodoc -class __$FullAccountPageDataCopyWithImpl<$Res> - implements _$FullAccountPageDataCopyWith<$Res> { +class __$FullAccountPageDataCopyWithImpl<$Res> implements _$FullAccountPageDataCopyWith<$Res> { __$FullAccountPageDataCopyWithImpl(this._self, this._then); final _FullAccountPageData _self; @@ -4243,8 +3893,7 @@ mixin _$QRSettings { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $QRSettingsCopyWith get copyWith => - _$QRSettingsCopyWithImpl(this as QRSettings, _$identity); + $QRSettingsCopyWith get copyWith => _$QRSettingsCopyWithImpl(this as QRSettings, _$identity); @override bool operator ==(Object other) { @@ -4259,8 +3908,7 @@ mixin _$QRSettings { } @override - int get hashCode => - Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); + int get hashCode => Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); @override String toString() { @@ -4270,9 +3918,7 @@ mixin _$QRSettings { /// @nodoc abstract mixin class $QRSettingsCopyWith<$Res> { - factory $QRSettingsCopyWith( - QRSettings value, $Res Function(QRSettings) _then) = - _$QRSettingsCopyWithImpl; + factory $QRSettingsCopyWith(QRSettings value, $Res Function(QRSettings) _then) = _$QRSettingsCopyWithImpl; @useResult $Res call({bool enabled, double size, int ecLevel, int delay, int repair}); } @@ -4411,16 +4057,13 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult maybeWhen( - TResult Function( - bool enabled, double size, int ecLevel, int delay, int repair)? - $default, { + TResult Function(bool enabled, double size, int ecLevel, int delay, int repair)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _QRSettings() when $default != null: - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, - _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); case _: return orElse(); } @@ -4441,15 +4084,12 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult when( - TResult Function( - bool enabled, double size, int ecLevel, int delay, int repair) - $default, + TResult Function(bool enabled, double size, int ecLevel, int delay, int repair) $default, ) { final _that = this; switch (_that) { case _QRSettings(): - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, - _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); } } @@ -4467,15 +4107,12 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - bool enabled, double size, int ecLevel, int delay, int repair)? - $default, + TResult? Function(bool enabled, double size, int ecLevel, int delay, int repair)? $default, ) { final _that = this; switch (_that) { case _QRSettings() when $default != null: - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, - _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); case _: return null; } @@ -4485,12 +4122,7 @@ extension QRSettingsPatterns on QRSettings { /// @nodoc class _QRSettings implements QRSettings { - _QRSettings( - {required this.enabled, - required this.size, - required this.ecLevel, - required this.delay, - required this.repair}); + _QRSettings({required this.enabled, required this.size, required this.ecLevel, required this.delay, required this.repair}); @override final bool enabled; @@ -4508,8 +4140,7 @@ class _QRSettings implements QRSettings { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$QRSettingsCopyWith<_QRSettings> get copyWith => - __$QRSettingsCopyWithImpl<_QRSettings>(this, _$identity); + _$QRSettingsCopyWith<_QRSettings> get copyWith => __$QRSettingsCopyWithImpl<_QRSettings>(this, _$identity); @override bool operator ==(Object other) { @@ -4524,8 +4155,7 @@ class _QRSettings implements QRSettings { } @override - int get hashCode => - Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); + int get hashCode => Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); @override String toString() { @@ -4534,11 +4164,8 @@ class _QRSettings implements QRSettings { } /// @nodoc -abstract mixin class _$QRSettingsCopyWith<$Res> - implements $QRSettingsCopyWith<$Res> { - factory _$QRSettingsCopyWith( - _QRSettings value, $Res Function(_QRSettings) _then) = - __$QRSettingsCopyWithImpl; +abstract mixin class _$QRSettingsCopyWith<$Res> implements $QRSettingsCopyWith<$Res> { + factory _$QRSettingsCopyWith(_QRSettings value, $Res Function(_QRSettings) _then) = __$QRSettingsCopyWithImpl; @override @useResult $Res call({bool enabled, double size, int ecLevel, int delay, int repair}); diff --git a/lib/store.g.dart b/lib/store.g.dart index 97f75efc8..fb1041d50 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -49,8 +49,7 @@ abstract class _$HasDb extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, bool, Object?, Object?>; + final element = ref.element as $ClassProviderElement, bool, Object?, Object?>; element.handleValue(ref, created); } } @@ -58,8 +57,7 @@ abstract class _$HasDb extends $Notifier { @ProviderFor(SelectedAccountId) const selectedAccountIdProvider = SelectedAccountIdProvider._(); -final class SelectedAccountIdProvider - extends $NotifierProvider { +final class SelectedAccountIdProvider extends $NotifierProvider { const SelectedAccountIdProvider._() : super( from: null, @@ -96,8 +94,7 @@ abstract class _$SelectedAccountId extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element - as $ClassProviderElement, int, Object?, Object?>; + final element = ref.element as $ClassProviderElement, int, Object?, Object?>; element.handleValue(ref, created); } } @@ -105,10 +102,8 @@ abstract class _$SelectedAccountId extends $Notifier { @ProviderFor(SyncStateAccount) const syncStateAccountProvider = SyncStateAccountFamily._(); -final class SyncStateAccountProvider - extends $AsyncNotifierProvider { - const SyncStateAccountProvider._( - {required SyncStateAccountFamily super.from, required int super.argument}) +final class SyncStateAccountProvider extends $AsyncNotifierProvider { + const SyncStateAccountProvider._({required SyncStateAccountFamily super.from, required int super.argument}) : super( retry: null, name: r'syncStateAccountProvider', @@ -145,9 +140,7 @@ final class SyncStateAccountProvider String _$syncStateAccountHash() => r'cb3d58d81b59192492c0aab60de138055b823f7f'; final class SyncStateAccountFamily extends $Family - with - $ClassFamilyOverride, - SyncProgressAccount, FutureOr, int> { + with $ClassFamilyOverride, SyncProgressAccount, FutureOr, int> { const SyncStateAccountFamily._() : super( retry: null, @@ -179,13 +172,9 @@ abstract class _$SyncStateAccount extends $AsyncNotifier { final created = build( _$args, ); - final ref = - this.ref as $Ref, SyncProgressAccount>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, SyncProgressAccount>, - AsyncValue, - Object?, - Object?>; + final ref = this.ref as $Ref, SyncProgressAccount>; + final element = ref.element + as $ClassProviderElement, SyncProgressAccount>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -193,8 +182,7 @@ abstract class _$SyncStateAccount extends $AsyncNotifier { @ProviderFor(selectedAccount) const selectedAccountProvider = SelectedAccountProvider._(); -final class SelectedAccountProvider extends $FunctionalProvider< - AsyncValue, Account?, FutureOr> +final class SelectedAccountProvider extends $FunctionalProvider, Account?, FutureOr> with $FutureModifier, $FutureProvider { const SelectedAccountProvider._() : super( @@ -212,8 +200,7 @@ final class SelectedAccountProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement($ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -226,8 +213,7 @@ String _$selectedAccountHash() => r'8fe4c0fb33769599d1a69f1efc302dd70f6b7aa7'; @ProviderFor(SelectedFolder) const selectedFolderProvider = SelectedFolderProvider._(); -final class SelectedFolderProvider - extends $NotifierProvider { +final class SelectedFolderProvider extends $NotifierProvider { const SelectedFolderProvider._() : super( from: null, @@ -264,8 +250,7 @@ abstract class _$SelectedFolder extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, Folder?, Object?, Object?>; + final element = ref.element as $ClassProviderElement, Folder?, Object?, Object?>; element.handleValue(ref, created); } } @@ -273,8 +258,7 @@ abstract class _$SelectedFolder extends $Notifier { @ProviderFor(getAccounts) const getAccountsProvider = GetAccountsProvider._(); -final class GetAccountsProvider extends $FunctionalProvider< - AsyncValue>, List, FutureOr>> +final class GetAccountsProvider extends $FunctionalProvider>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetAccountsProvider._() : super( @@ -292,9 +276,7 @@ final class GetAccountsProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -307,8 +289,7 @@ String _$getAccountsHash() => r'4628dce465555f59311a5f3232bb00fbfb6e428c'; @ProviderFor(getFolders) const getFoldersProvider = GetFoldersProvider._(); -final class GetFoldersProvider extends $FunctionalProvider< - AsyncValue>, List, FutureOr>> +final class GetFoldersProvider extends $FunctionalProvider>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetFoldersProvider._() : super( @@ -326,9 +307,7 @@ final class GetFoldersProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -341,8 +320,7 @@ String _$getFoldersHash() => r'2458237b23db05d19a7b49856e9987542680249e'; @ProviderFor(getCategories) const getCategoriesProvider = GetCategoriesProvider._(); -final class GetCategoriesProvider extends $FunctionalProvider< - AsyncValue>, List, FutureOr>> +final class GetCategoriesProvider extends $FunctionalProvider>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetCategoriesProvider._() : super( @@ -360,9 +338,7 @@ final class GetCategoriesProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -375,8 +351,7 @@ String _$getCategoriesHash() => r'b936c571d89ff2ede483f5239881ba90219af321'; @ProviderFor(getContacts) const getContactsProvider = GetContactsProvider._(); -final class GetContactsProvider extends $FunctionalProvider< - AsyncValue>, List, FutureOr>> +final class GetContactsProvider extends $FunctionalProvider>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetContactsProvider._() : super( @@ -394,9 +369,7 @@ final class GetContactsProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -409,16 +382,9 @@ String _$getContactsHash() => r'e751c15648be7db79565969c43b1be3a0ac566de'; @ProviderFor(contactsForAddress) const contactsForAddressProvider = ContactsForAddressFamily._(); -final class ContactsForAddressProvider extends $FunctionalProvider< - AsyncValue>, - List, - FutureOr>> - with - $FutureModifier>, - $FutureProvider> { - const ContactsForAddressProvider._( - {required ContactsForAddressFamily super.from, - required String super.argument}) +final class ContactsForAddressProvider extends $FunctionalProvider>, List, FutureOr>> + with $FutureModifier>, $FutureProvider> { + const ContactsForAddressProvider._({required ContactsForAddressFamily super.from, required String super.argument}) : super( retry: null, name: r'contactsForAddressProvider', @@ -439,9 +405,7 @@ final class ContactsForAddressProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -463,11 +427,9 @@ final class ContactsForAddressProvider extends $FunctionalProvider< } } -String _$contactsForAddressHash() => - r'3154c6f4ddf9d4e141da6f70d5a086d79afdc348'; +String _$contactsForAddressHash() => r'3154c6f4ddf9d4e141da6f70d5a086d79afdc348'; -final class ContactsForAddressFamily extends $Family - with $FunctionalFamilyOverride>, String> { +final class ContactsForAddressFamily extends $Family with $FunctionalFamilyOverride>, String> { const ContactsForAddressFamily._() : super( retry: null, @@ -489,11 +451,9 @@ final class ContactsForAddressFamily extends $Family @ProviderFor(account) const accountProvider = AccountFamily._(); -final class AccountProvider extends $FunctionalProvider, - AccountData, FutureOr> +final class AccountProvider extends $FunctionalProvider, AccountData, FutureOr> with $FutureModifier, $FutureProvider { - const AccountProvider._( - {required AccountFamily super.from, required int super.argument}) + const AccountProvider._({required AccountFamily super.from, required int super.argument}) : super( retry: null, name: r'accountProvider', @@ -514,9 +474,7 @@ final class AccountProvider extends $FunctionalProvider, @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -540,8 +498,7 @@ final class AccountProvider extends $FunctionalProvider, String _$accountHash() => r'b5b61dba595b61fd82e1ba3777a9084c1c546457'; -final class AccountFamily extends $Family - with $FunctionalFamilyOverride, int> { +final class AccountFamily extends $Family with $FunctionalFamilyOverride, int> { const AccountFamily._() : super( retry: null, @@ -563,8 +520,7 @@ final class AccountFamily extends $Family @ProviderFor(getCurrentAccount) const getCurrentAccountProvider = GetCurrentAccountProvider._(); -final class GetCurrentAccountProvider extends $FunctionalProvider< - AsyncValue, AccountData?, FutureOr> +final class GetCurrentAccountProvider extends $FunctionalProvider, AccountData?, FutureOr> with $FutureModifier, $FutureProvider { const GetCurrentAccountProvider._() : super( @@ -582,9 +538,7 @@ final class GetCurrentAccountProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -597,8 +551,7 @@ String _$getCurrentAccountHash() => r'fb9e03f8c767fe77e0f33e71495c3bf0c167c7a1'; @ProviderFor(AppSettingsNotifier) const appSettingsProvider = AppSettingsNotifierProvider._(); -final class AppSettingsNotifierProvider - extends $AsyncNotifierProvider { +final class AppSettingsNotifierProvider extends $AsyncNotifierProvider { const AppSettingsNotifierProvider._() : super( from: null, @@ -618,8 +571,7 @@ final class AppSettingsNotifierProvider AppSettingsNotifier create() => AppSettingsNotifier(); } -String _$appSettingsNotifierHash() => - r'bc2222bf4d3206176cf3b8888aee624034d51fe8'; +String _$appSettingsNotifierHash() => r'bc2222bf4d3206176cf3b8888aee624034d51fe8'; abstract class _$AppSettingsNotifier extends $AsyncNotifier { FutureOr build(); @@ -628,11 +580,7 @@ abstract class _$AppSettingsNotifier extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, AppSettings>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, AppSettings>, - AsyncValue, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, AppSettings>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -640,8 +588,7 @@ abstract class _$AppSettingsNotifier extends $AsyncNotifier { @ProviderFor(PriceNotifier) const priceProvider = PriceNotifierProvider._(); -final class PriceNotifierProvider - extends $NotifierProvider { +final class PriceNotifierProvider extends $NotifierProvider { const PriceNotifierProvider._() : super( from: null, @@ -678,8 +625,7 @@ abstract class _$PriceNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, double?, Object?, Object?>; + final element = ref.element as $ClassProviderElement, double?, Object?, Object?>; element.handleValue(ref, created); } } @@ -687,8 +633,7 @@ abstract class _$PriceNotifier extends $Notifier { @ProviderFor(SupportedCurrenciesNotifier) const supportedCurrenciesProvider = SupportedCurrenciesNotifierProvider._(); -final class SupportedCurrenciesNotifierProvider - extends $AsyncNotifierProvider> { +final class SupportedCurrenciesNotifierProvider extends $AsyncNotifierProvider> { const SupportedCurrenciesNotifierProvider._() : super( from: null, @@ -708,22 +653,16 @@ final class SupportedCurrenciesNotifierProvider SupportedCurrenciesNotifier create() => SupportedCurrenciesNotifier(); } -String _$supportedCurrenciesNotifierHash() => - r'6f0ef88efa8e2e0b124b8880bea1e8620df43f27'; +String _$supportedCurrenciesNotifierHash() => r'6f0ef88efa8e2e0b124b8880bea1e8620df43f27'; -abstract class _$SupportedCurrenciesNotifier - extends $AsyncNotifier> { +abstract class _$SupportedCurrenciesNotifier extends $AsyncNotifier> { FutureOr> build(); @$mustCallSuper @override void runBuild() { final created = build(); final ref = this.ref as $Ref>, List>; - final element = ref.element as $ClassProviderElement< - AnyNotifier>, List>, - AsyncValue>, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement>, List>, AsyncValue>, Object?, Object?>; element.handleValue(ref, created); } } @@ -731,8 +670,7 @@ abstract class _$SupportedCurrenciesNotifier @ProviderFor(LogNotifier) const logProvider = LogNotifierProvider._(); -final class LogNotifierProvider - extends $NotifierProvider> { +final class LogNotifierProvider extends $NotifierProvider> { const LogNotifierProvider._() : super( from: null, @@ -769,11 +707,7 @@ abstract class _$LogNotifier extends $Notifier> { void runBuild() { final created = build(); final ref = this.ref as $Ref, List>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, List>, - List, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, List>, List, Object?, Object?>; element.handleValue(ref, created); } } @@ -781,8 +715,7 @@ abstract class _$LogNotifier extends $Notifier> { @ProviderFor(CurrentHeight) const currentHeightProvider = CurrentHeightProvider._(); -final class CurrentHeightProvider - extends $AsyncNotifierProvider { +final class CurrentHeightProvider extends $AsyncNotifierProvider { const CurrentHeightProvider._() : super( from: null, @@ -811,11 +744,7 @@ abstract class _$CurrentHeight extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, int?>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, int?>, - AsyncValue, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, int?>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -823,8 +752,7 @@ abstract class _$CurrentHeight extends $AsyncNotifier { @ProviderFor(MempoolNotifier) const mempoolProvider = MempoolNotifierProvider._(); -final class MempoolNotifierProvider - extends $NotifierProvider { +final class MempoolNotifierProvider extends $NotifierProvider { const MempoolNotifierProvider._() : super( from: null, @@ -861,11 +789,7 @@ abstract class _$MempoolNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, - MempoolState, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, MempoolState, Object?, Object?>; element.handleValue(ref, created); } } @@ -873,8 +797,7 @@ abstract class _$MempoolNotifier extends $Notifier { @ProviderFor(SynchronizerNotifier) const synchronizerProvider = SynchronizerNotifierProvider._(); -final class SynchronizerNotifierProvider - extends $NotifierProvider { +final class SynchronizerNotifierProvider extends $NotifierProvider { const SynchronizerNotifierProvider._() : super( from: null, @@ -902,8 +825,7 @@ final class SynchronizerNotifierProvider } } -String _$synchronizerNotifierHash() => - r'049414ae8378414353563749d26326461231fee4'; +String _$synchronizerNotifierHash() => r'049414ae8378414353563749d26326461231fee4'; abstract class _$SynchronizerNotifier extends $Notifier { SyncState build(); @@ -912,8 +834,7 @@ abstract class _$SynchronizerNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, SyncState, Object?, Object?>; + final element = ref.element as $ClassProviderElement, SyncState, Object?, Object?>; element.handleValue(ref, created); } } @@ -921,8 +842,7 @@ abstract class _$SynchronizerNotifier extends $Notifier { @ProviderFor(TransparentScan) const transparentScanProvider = TransparentScanProvider._(); -final class TransparentScanProvider - extends $NotifierProvider { +final class TransparentScanProvider extends $NotifierProvider { const TransparentScanProvider._() : super( from: null, @@ -959,8 +879,7 @@ abstract class _$TransparentScan extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement< - AnyNotifier, String, Object?, Object?>; + final element = ref.element as $ClassProviderElement, String, Object?, Object?>; element.handleValue(ref, created); } } @@ -968,10 +887,8 @@ abstract class _$TransparentScan extends $Notifier { @ProviderFor(GetTxDetails) const getTxDetailsProvider = GetTxDetailsFamily._(); -final class GetTxDetailsProvider - extends $AsyncNotifierProvider { - const GetTxDetailsProvider._( - {required GetTxDetailsFamily super.from, required int super.argument}) +final class GetTxDetailsProvider extends $AsyncNotifierProvider { + const GetTxDetailsProvider._({required GetTxDetailsFamily super.from, required int super.argument}) : super( retry: null, name: r'getTxDetailsProvider', @@ -1007,10 +924,7 @@ final class GetTxDetailsProvider String _$getTxDetailsHash() => r'67175e914e53d2de8944db85e0f9225374cba276'; -final class GetTxDetailsFamily extends $Family - with - $ClassFamilyOverride, TxAccount, - FutureOr, int> { +final class GetTxDetailsFamily extends $Family with $ClassFamilyOverride, TxAccount, FutureOr, int> { const GetTxDetailsFamily._() : super( retry: null, @@ -1043,11 +957,7 @@ abstract class _$GetTxDetails extends $AsyncNotifier { _$args, ); final ref = this.ref as $Ref, TxAccount>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, TxAccount>, - AsyncValue, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, TxAccount>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -1084,11 +994,7 @@ abstract class _$Lifecycle extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, bool>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, bool>, - AsyncValue, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, bool>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -1096,10 +1002,7 @@ abstract class _$Lifecycle extends $AsyncNotifier { @ProviderFor(accountsPageData) const accountsPageDataProvider = AccountsPageDataProvider._(); -final class AccountsPageDataProvider extends $FunctionalProvider< - AsyncValue, - AccountsPageData, - FutureOr> +final class AccountsPageDataProvider extends $FunctionalProvider, AccountsPageData, FutureOr> with $FutureModifier, $FutureProvider { const AccountsPageDataProvider._() : super( @@ -1117,9 +1020,7 @@ final class AccountsPageDataProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1132,10 +1033,7 @@ String _$accountsPageDataHash() => r'e37b6e048a3a3938c9c2b03ae41328036271956d'; @ProviderFor(basicAccountData) const basicAccountDataProvider = BasicAccountDataProvider._(); -final class BasicAccountDataProvider extends $FunctionalProvider< - AsyncValue, - BasicAccountData, - FutureOr> +final class BasicAccountDataProvider extends $FunctionalProvider, BasicAccountData, FutureOr> with $FutureModifier, $FutureProvider { const BasicAccountDataProvider._() : super( @@ -1153,9 +1051,7 @@ final class BasicAccountDataProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1168,8 +1064,7 @@ String _$basicAccountDataHash() => r'5f755167b7edd069b07888af935e53d49e425a16'; @ProviderFor(accountPageData) const accountPageDataProvider = AccountPageDataProvider._(); -final class AccountPageDataProvider extends $FunctionalProvider< - AsyncValue, AccountPageData, FutureOr> +final class AccountPageDataProvider extends $FunctionalProvider, AccountPageData, FutureOr> with $FutureModifier, $FutureProvider { const AccountPageDataProvider._() : super( @@ -1187,9 +1082,7 @@ final class AccountPageDataProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1202,13 +1095,8 @@ String _$accountPageDataHash() => r'be356fdedbc8bf660c5ff2d19eaec87577045d47'; @ProviderFor(fullAccountPageData) const fullAccountPageDataProvider = FullAccountPageDataProvider._(); -final class FullAccountPageDataProvider extends $FunctionalProvider< - AsyncValue, - FullAccountPageData, - FutureOr> - with - $FutureModifier, - $FutureProvider { +final class FullAccountPageDataProvider extends $FunctionalProvider, FullAccountPageData, FutureOr> + with $FutureModifier, $FutureProvider { const FullAccountPageDataProvider._() : super( from: null, @@ -1225,9 +1113,7 @@ final class FullAccountPageDataProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1235,14 +1121,12 @@ final class FullAccountPageDataProvider extends $FunctionalProvider< } } -String _$fullAccountPageDataHash() => - r'742c766717c6b4f146d1f6fa7c6a5aa2512fa0b6'; +String _$fullAccountPageDataHash() => r'742c766717c6b4f146d1f6fa7c6a5aa2512fa0b6'; @ProviderFor(VaultNotifier) const vaultProvider = VaultNotifierProvider._(); -final class VaultNotifierProvider - extends $AsyncNotifierProvider { +final class VaultNotifierProvider extends $AsyncNotifierProvider { const VaultNotifierProvider._() : super( from: null, @@ -1271,11 +1155,7 @@ abstract class _$VaultNotifier extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, Vault>; - final element = ref.element as $ClassProviderElement< - AnyNotifier, Vault>, - AsyncValue, - Object?, - Object?>; + final element = ref.element as $ClassProviderElement, Vault>, AsyncValue, Object?, Object?>; element.handleValue(ref, created); } } @@ -1283,13 +1163,9 @@ abstract class _$VaultNotifier extends $AsyncNotifier { @ProviderFor(pluginList) const pluginListProvider = PluginListProvider._(); -final class PluginListProvider extends $FunctionalProvider< - AsyncValue>, - List, - FutureOr>> - with - $FutureModifier>, - $FutureProvider> { +final class PluginListProvider + extends $FunctionalProvider>, List, FutureOr>> + with $FutureModifier>, $FutureProvider> { const PluginListProvider._() : super( from: null, @@ -1306,9 +1182,7 @@ final class PluginListProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -1321,13 +1195,9 @@ String _$pluginListHash() => r'f396f236f61820f586848210e153f83881ad09c1'; @ProviderFor(pluginMemoSections) const pluginMemoSectionsProvider = PluginMemoSectionsFamily._(); -final class PluginMemoSectionsProvider extends $FunctionalProvider< - AsyncValue>, - List, - FutureOr>> - with - $FutureModifier>, - $FutureProvider> { +final class PluginMemoSectionsProvider + extends $FunctionalProvider>, List, FutureOr>> + with $FutureModifier>, $FutureProvider> { const PluginMemoSectionsProvider._( {required PluginMemoSectionsFamily super.from, required ( @@ -1355,9 +1225,7 @@ final class PluginMemoSectionsProvider extends $FunctionalProvider< @$internal @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer) => - $FutureProviderElement(pointer); + $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -1383,8 +1251,7 @@ final class PluginMemoSectionsProvider extends $FunctionalProvider< } } -String _$pluginMemoSectionsHash() => - r'ecd47c3bc96fdf29a00b04a6d8b8f97742208824'; +String _$pluginMemoSectionsHash() => r'ecd47c3bc96fdf29a00b04a6d8b8f97742208824'; final class PluginMemoSectionsFamily extends $Family with diff --git a/lib/widgets/contact_picker.dart b/lib/widgets/contact_picker.dart index 192dd8152..40e6e9e08 100644 --- a/lib/widgets/contact_picker.dart +++ b/lib/widgets/contact_picker.dart @@ -24,8 +24,7 @@ Future?> showContactPicker( final status = await fc.FlutterContacts.permissions.request( fc.PermissionType.read, ); - if (status != fc.PermissionStatus.granted && - status != fc.PermissionStatus.limited) { + if (status != fc.PermissionStatus.granted && status != fc.PermissionStatus.limited) { if (context.mounted) { await showMessage( context, @@ -194,9 +193,7 @@ class _ContactPickerDialogState extends State<_ContactPickerDialog> { List get _filtered { if (_query.isEmpty) return widget.candidates; final q = _query.toLowerCase(); - return widget.candidates - .where((c) => c.name.toLowerCase().contains(q)) - .toList(); + return widget.candidates.where((c) => c.name.toLowerCase().contains(q)).toList(); } @override @@ -232,20 +229,13 @@ class _ContactPickerDialogState extends State<_ContactPickerDialog> { mainAxisSize: MainAxisSize.min, children: [ Icon( - _query.isEmpty - ? Icons.contact_phone - : Icons.search_off, + _query.isEmpty ? Icons.contact_phone : Icons.search_off, size: 64, - color: Theme.of(context) - .colorScheme - .onSurface - .withAlpha(100), + color: Theme.of(context).colorScheme.onSurface.withAlpha(100), ), Gap(16), Text( - _query.isEmpty - ? "No contacts available" - : "No contacts matching \"$_query\"", + _query.isEmpty ? "No contacts available" : "No contacts matching \"$_query\"", style: Theme.of(context).textTheme.bodyLarge, ), ], @@ -273,9 +263,7 @@ class _ContactPickerDialogState extends State<_ContactPickerDialog> { : const Icon(Icons.person), title: Text(candidate.name), subtitle: Text( - candidate.addresses.length == 1 - ? "1 Zcash address found" - : "${candidate.addresses.length} Zcash addresses found", + candidate.addresses.length == 1 ? "1 Zcash address found" : "${candidate.addresses.length} Zcash addresses found", ), onTap: () { if (widget.multiSelect) { @@ -287,8 +275,7 @@ class _ContactPickerDialogState extends State<_ContactPickerDialog> { } }); } else { - Navigator.of(context) - .pop([candidate]); + Navigator.of(context).pop([candidate]); } }, ); diff --git a/lib/widgets/plugin_memo_view.dart b/lib/widgets/plugin_memo_view.dart index 5321f488c..2faf31dad 100644 --- a/lib/widgets/plugin_memo_view.dart +++ b/lib/widgets/plugin_memo_view.dart @@ -21,8 +21,7 @@ class PluginMemoView extends ConsumerWidget { } final c = coinContext.coin; - final sectionsAsync = - ref.watch(pluginMemoSectionsProvider(memoBytes, c)); + final sectionsAsync = ref.watch(pluginMemoSectionsProvider(memoBytes, c)); return sectionsAsync.when( data: (sections) { @@ -61,15 +60,13 @@ class PluginMemoView extends ConsumerWidget { headingTextStyle: t.textTheme.labelMedium, dataTextStyle: t.textTheme.bodySmall, columns: [ - for (final header in section.headers) - DataColumn(label: Text(header)), + for (final header in section.headers) DataColumn(label: Text(header)), ], rows: [ for (final row in section.rows) DataRow( cells: [ - for (final cell in row.cells) - DataCell(_renderCell(cell, t)), + for (final cell in row.cells) DataCell(_renderCell(cell, t)), ], ), ], @@ -103,8 +100,7 @@ class PluginMemoView extends ConsumerWidget { case 'date': final ts = int.tryParse(cell.value); if (ts != null) { - final dt = - DateTime.fromMillisecondsSinceEpoch(ts * 1000).toLocal(); + final dt = DateTime.fromMillisecondsSinceEpoch(ts * 1000).toLocal(); return Text( '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} ' '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}', diff --git a/lib/widgets/vault_account_picker.dart b/lib/widgets/vault_account_picker.dart index ccb4caae2..e8009b676 100644 --- a/lib/widgets/vault_account_picker.dart +++ b/lib/widgets/vault_account_picker.dart @@ -9,8 +9,7 @@ Future?> showVaultAccountPicker( }) async { if (accounts.isEmpty) { if (context.mounted) { - await showMessage(context, "No accounts found in the vault backup.", - title: "Recovery"); + await showMessage(context, "No accounts found in the vault backup.", title: "Recovery"); } return null; } @@ -29,8 +28,7 @@ class _VaultAccountPickerDialog extends StatefulWidget { const _VaultAccountPickerDialog({required this.accounts}); @override - State<_VaultAccountPickerDialog> createState() => - _VaultAccountPickerDialogState(); + State<_VaultAccountPickerDialog> createState() => _VaultAccountPickerDialogState(); } class _VaultAccountPickerDialogState extends State<_VaultAccountPickerDialog> { @@ -56,9 +54,7 @@ class _VaultAccountPickerDialogState extends State<_VaultAccountPickerDialog> { List get _filtered { if (_query.isEmpty) return widget.accounts; final q = _query.toLowerCase(); - return widget.accounts - .where((a) => a.name.toLowerCase().contains(q)) - .toList(); + return widget.accounts.where((a) => a.name.toLowerCase().contains(q)).toList(); } void _toggleAll() { @@ -116,17 +112,13 @@ class _VaultAccountPickerDialogState extends State<_VaultAccountPickerDialog> { mainAxisSize: MainAxisSize.min, children: [ Icon( - _query.isEmpty - ? Icons.account_balance_wallet_outlined - : Icons.search_off, + _query.isEmpty ? Icons.account_balance_wallet_outlined : Icons.search_off, size: 64, color: cs.onSurface.withAlpha(100), ), const Gap(16), Text( - _query.isEmpty - ? "No accounts available" - : "No accounts matching \"$_query\"", + _query.isEmpty ? "No accounts available" : "No accounts matching \"$_query\"", style: tt.bodyLarge, ), ], @@ -137,25 +129,19 @@ class _VaultAccountPickerDialogState extends State<_VaultAccountPickerDialog> { itemBuilder: (context, index) { final ra = filtered[index]; final isSelected = _selected.contains(ra); - final initialsText = ra.name.length > 1 - ? ra.name.substring(0, 2).toUpperCase() - : ra.name.toUpperCase(); + final initialsText = ra.name.length > 1 ? ra.name.substring(0, 2).toUpperCase() : ra.name.toUpperCase(); return ListTile( leading: CircleAvatar( - backgroundColor: isSelected - ? Colors.blue.shade700 - : cs.primaryContainer, + backgroundColor: isSelected ? Colors.blue.shade700 : cs.primaryContainer, child: isSelected ? const Icon(Icons.check, color: Colors.white) : Text( initialsText, - style: TextStyle( - color: cs.onPrimaryContainer), + style: TextStyle(color: cs.onPrimaryContainer), ), ), - title: Text(ra.name, - overflow: TextOverflow.ellipsis), + title: Text(ra.name, overflow: TextOverflow.ellipsis), subtitle: Text( "Birth height: ${ra.birthHeight}", style: tt.bodySmall, diff --git a/linux/runner/main.cc b/linux/runner/main.cc index e7c5c5437..26cd225d9 100644 --- a/linux/runner/main.cc +++ b/linux/runner/main.cc @@ -1,6 +1,6 @@ #include "my_application.h" -int main(int argc, char** argv) { +int main(int argc, char **argv) { g_autoptr(MyApplication) app = my_application_new(); return g_application_run(G_APPLICATION(app), argc, argv); } diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc index 7fedb36c0..9209a83a6 100644 --- a/linux/runner/my_application.cc +++ b/linux/runner/my_application.cc @@ -9,15 +9,15 @@ struct _MyApplication { GtkApplication parent_instance; - char** dart_entrypoint_arguments; + char **dart_entrypoint_arguments; }; G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) // Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = +static void my_application_activate(GApplication *application) { + MyApplication *self = MY_APPLICATION(application); + GtkWindow *window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); // Use a header bar when running in GNOME as this is the common style used @@ -29,16 +29,16 @@ static void my_application_activate(GApplication* application) { // if future cases occur). gboolean use_header_bar = TRUE; #ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); + GdkScreen *screen = gtk_window_get_screen(window); if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + const gchar *wm_name = gdk_x11_screen_get_window_manager_name(screen); if (g_strcmp0(wm_name, "GNOME Shell") != 0) { use_header_bar = FALSE; } } #endif if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); gtk_widget_show(GTK_WIDGET(header_bar)); gtk_header_bar_set_title(header_bar, "zkool"); gtk_header_bar_set_show_close_button(header_bar, TRUE); @@ -51,9 +51,10 @@ static void my_application_activate(GApplication* application) { gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); - FlView* view = fl_view_new(project); + FlView *view = fl_view_new(project); gtk_widget_show(GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); @@ -63,16 +64,18 @@ static void my_application_activate(GApplication* application) { } // Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { - MyApplication* self = MY_APPLICATION(application); +static gboolean my_application_local_command_line(GApplication *application, + gchar ***arguments, + int *exit_status) { + MyApplication *self = MY_APPLICATION(application); // Strip out the first argument as it is the binary name. self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); g_autoptr(GError) error = nullptr; if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; } g_application_activate(application); @@ -82,8 +85,8 @@ static gboolean my_application_local_command_line(GApplication* application, gch } // Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); +static void my_application_startup(GApplication *application) { + // MyApplication* self = MY_APPLICATION(object); // Perform any actions required at application startup. @@ -91,8 +94,8 @@ static void my_application_startup(GApplication* application) { } // Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); +static void my_application_shutdown(GApplication *application) { + // MyApplication* self = MY_APPLICATION(object); // Perform any actions required at application shutdown. @@ -100,23 +103,24 @@ static void my_application_shutdown(GApplication* application) { } // Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); +static void my_application_dispose(GObject *object) { + MyApplication *self = MY_APPLICATION(object); g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); G_OBJECT_CLASS(my_application_parent_class)->dispose(object); } -static void my_application_class_init(MyApplicationClass* klass) { +static void my_application_class_init(MyApplicationClass *klass) { G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; G_APPLICATION_CLASS(klass)->startup = my_application_startup; G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; G_OBJECT_CLASS(klass)->dispose = my_application_dispose; } -static void my_application_init(MyApplication* self) {} +static void my_application_init(MyApplication *self) {} -MyApplication* my_application_new() { +MyApplication *my_application_new() { // Set the program name to the application ID, which helps various systems // like GTK and desktop environments map this running application to its // corresponding .desktop file. This ensures better integration by allowing @@ -124,7 +128,6 @@ MyApplication* my_application_new() { g_set_prgname(APPLICATION_ID); return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, - "flags", G_APPLICATION_NON_UNIQUE, - nullptr)); + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); } diff --git a/linux/runner/my_application.h b/linux/runner/my_application.h index 72271d5e4..3258a73cf 100644 --- a/linux/runner/my_application.h +++ b/linux/runner/my_application.h @@ -13,6 +13,6 @@ G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, * * Returns: a new #MyApplication. */ -MyApplication* my_application_new(); +MyApplication *my_application_new(); -#endif // FLUTTER_MY_APPLICATION_H_ +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4795fec64..53b026cd6 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -4,7 +4,6 @@ import FlutterMacOS import Foundation - import device_info_plus import file_picker import file_selector_macos @@ -21,12 +20,15 @@ import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + DeviceInfoPlusMacosPlugin.register( + with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterContactsPlugin.register(with: registry.registrar(forPlugin: "FlutterContactsPlugin")) - InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) - FlutterPasskeyServicePlugin.register(with: registry.registrar(forPlugin: "FlutterPasskeyServicePlugin")) + InAppWebViewFlutterPlugin.register( + with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + FlutterPasskeyServicePlugin.register( + with: registry.registrar(forPlugin: "FlutterPasskeyServicePlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) diff --git a/protos/compact_formats.proto b/protos/compact_formats.proto index d44210f9f..49ae22082 100644 --- a/protos/compact_formats.proto +++ b/protos/compact_formats.proto @@ -6,85 +6,94 @@ syntax = "proto3"; package cash.z.wallet.sdk.rpc; option go_package = "lightwalletd/walletrpc"; option swift_prefix = ""; -// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. -// bytes fields of hashes are in canonical little-endian format. +// Remember that proto3 fields are all optional. A field that is not present +// will be set to its zero value. bytes fields of hashes are in canonical +// little-endian format. // CompactBlock is a packaging of ONLY the data from a block that's needed to: // 1. Detect a payment to your shielded Sapling address // 2. Detect a spend of your shielded Sapling notes // 3. Update your witnesses to generate new Sapling spend proofs. message CompactBlock { - uint32 protoVersion = 1; // the version of this wire format, for storage - uint64 height = 2; // the height of this block - bytes hash = 3; // the ID (hash) of this block, same as in block explorers - bytes prevHash = 4; // the ID (hash) of this block's predecessor - uint32 time = 5; // Unix epoch time when the block was mined - bytes header = 6; // (hash, prevHash, and time) OR (full header) - repeated CompactTx vtx = 7; // zero or more compact transactions from this block + uint32 protoVersion = 1; // the version of this wire format, for storage + uint64 height = 2; // the height of this block + bytes hash = 3; // the ID (hash) of this block, same as in block explorers + bytes prevHash = 4; // the ID (hash) of this block's predecessor + uint32 time = 5; // Unix epoch time when the block was mined + bytes header = 6; // (hash, prevHash, and time) OR (full header) + repeated CompactTx vtx = + 7; // zero or more compact transactions from this block } -// CompactTx contains the minimum information for a wallet to know if this transaction -// is relevant to it (either pays to it or spends from it) via shielded elements -// only. This message will not encode a transparent-to-transparent transaction. +// CompactTx contains the minimum information for a wallet to know if this +// transaction is relevant to it (either pays to it or spends from it) via +// shielded elements only. This message will not encode a +// transparent-to-transparent transaction. message CompactTx { - uint64 index = 1; // the index within the full block - bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers + uint64 index = 1; // the index within the full block + bytes hash = + 2; // the ID (hash) of this transaction, same as in block explorers - // The transaction fee: present if server can provide. In the case of a - // stateless server and a transaction with transparent inputs, this will be - // unset because the calculation requires reference to prior transactions. - // in a pure-Sapling context, the fee will be calculable as: - // valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) - uint32 fee = 3; + // The transaction fee: present if server can provide. In the case of a + // stateless server and a transaction with transparent inputs, this will be + // unset because the calculation requires reference to prior transactions. + // in a pure-Sapling context, the fee will be calculable as: + // valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) + uint32 fee = 3; - repeated CompactSaplingSpend spends = 4; // inputs - repeated CompactSaplingOutput outputs = 5; // outputs - repeated CompactOrchardAction actions = 6; - repeated CompactOrchardAction ironwoodActions = 9; - repeated CompactIssuance issuances = 10; // ZSA issuance actions + repeated CompactSaplingSpend spends = 4; // inputs + repeated CompactSaplingOutput outputs = 5; // outputs + repeated CompactOrchardAction actions = 6; + repeated CompactOrchardAction ironwoodActions = 9; + repeated CompactIssuance issuances = 10; // ZSA issuance actions } // CompactIssueNote carries the unencrypted note fields for a single note // within an IssueAction. message CompactIssueNote { - bytes recipient = 1; // 43 bytes — recipient address encoding - uint64 value = 2; // Note value in asset base units - bytes rho = 3; // [32] Nullifier derivation base - bytes rseed = 4; // [32] Random seed + bytes recipient = 1; // 43 bytes — recipient address encoding + uint64 value = 2; // Note value in asset base units + bytes rho = 3; // [32] Nullifier derivation base + bytes rseed = 4; // [32] Random seed } // CompactIssuance contains the minimal data needed for a light client to // record a ZSA issuance event. Each message corresponds to one IssueAction // within a transaction's IssueBundle (ZIP-227). message CompactIssuance { - bytes assetDescHash = 1; // [32] BLAKE2b-256 hash of the asset description string - bool finalize = 2; // Whether this action finalizes the asset - bytes ik = 3; // [33] Issuer Validating Key (algorithm byte + x-only pubkey) - uint64 issuedAmount = 4; // Sum of all note values in this IssueAction (in asset base units) - repeated CompactIssueNote notes = 5; // Per-note unencrypted data + bytes assetDescHash = + 1; // [32] BLAKE2b-256 hash of the asset description string + bool finalize = 2; // Whether this action finalizes the asset + bytes ik = 3; // [33] Issuer Validating Key (algorithm byte + x-only pubkey) + uint64 issuedAmount = + 4; // Sum of all note values in this IssueAction (in asset base units) + repeated CompactIssueNote notes = 5; // Per-note unencrypted data } -// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash +// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the +// Zcash -// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash -// protocol specification. +// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the +// Zcash protocol specification. message CompactSaplingSpend { - bytes nf = 1; // nullifier (see the Zcash protocol specification) + bytes nf = 1; // nullifier (see the Zcash protocol specification) } // output is a Sapling Output Description as described in section 7.4 of the // Zcash protocol spec. Total size is 948. message CompactSaplingOutput { - bytes cmu = 1; // note commitment u-coordinate - bytes epk = 2; // ephemeral public key - bytes ciphertext = 3; // first 52 bytes of ciphertext + bytes cmu = 1; // note commitment u-coordinate + bytes epk = 2; // ephemeral public key + bytes ciphertext = 3; // first 52 bytes of ciphertext } // https://github.com/zcash/zips/blob/main/zip-0225.rst#orchard-action-description-orchardaction // (but not all fields are needed) message CompactOrchardAction { - bytes nullifier = 1; // [32] The nullifier of the input note - bytes cmx = 2; // [32] The x-coordinate of the note commitment for the output note - bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key - bytes ciphertext = 4; // [52] The note plaintext component of the encCiphertext field + bytes nullifier = 1; // [32] The nullifier of the input note + bytes cmx = + 2; // [32] The x-coordinate of the note commitment for the output note + bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key + bytes ciphertext = + 4; // [52] The note plaintext component of the encCiphertext field } diff --git a/protos/service.proto b/protos/service.proto index 8e685e597..b630066c6 100644 --- a/protos/service.proto +++ b/protos/service.proto @@ -11,41 +11,41 @@ import "compact_formats.proto"; // A BlockID message contains identifiers to select a block: a height or a // hash. Specification by hash is not implemented, but may be in the future. message BlockID { - uint64 height = 1; - bytes hash = 2; + uint64 height = 1; + bytes hash = 2; } // BlockRange specifies a series of blocks from start to end inclusive. // Both BlockIDs must be heights; specification by hash is not yet supported. message BlockRange { - BlockID start = 1; - BlockID end = 2; - uint64 spamFilterThreshold = 3; + BlockID start = 1; + BlockID end = 2; + uint64 spamFilterThreshold = 3; } // A TxFilter contains the information needed to identify a particular // transaction: either a block and an index, or a direct transaction hash. // Currently, only specification by hash is supported. message TxFilter { - BlockID block = 1; // block identifier, height or hash - uint64 index = 2; // index within the block - bytes hash = 3; // transaction ID (hash, txid) + BlockID block = 1; // block identifier, height or hash + uint64 index = 2; // index within the block + bytes hash = 3; // transaction ID (hash, txid) } -// RawTransaction contains the complete transaction data. It also optionally includes -// the block height in which the transaction was included, or, when returned -// by GetMempoolStream(), the latest block height. +// RawTransaction contains the complete transaction data. It also optionally +// includes the block height in which the transaction was included, or, when +// returned by GetMempoolStream(), the latest block height. message RawTransaction { - bytes data = 1; // exact data returned by Zcash 'getrawtransaction' - uint64 height = 2; // height that the transaction was mined (or -1) + bytes data = 1; // exact data returned by Zcash 'getrawtransaction' + uint64 height = 2; // height that the transaction was mined (or -1) } // A SendResponse encodes an error code and a string. It is currently used // only by SendTransaction(). If error code is zero, the operation was // successful; if non-zero, it and the message specify the failure. message SendResponse { - int32 errorCode = 1; - string errorMessage = 2; + int32 errorCode = 1; + string errorMessage = 2; } // Chainspec is a placeholder to allow specification of a particular chain fork. @@ -57,132 +57,128 @@ message Empty {} // LightdInfo returns various information about this lightwalletd instance // and the state of the blockchain. message LightdInfo { - string version = 1; - string vendor = 2; - bool taddrSupport = 3; // true - string chainName = 4; // either "main" or "test" - uint64 saplingActivationHeight = 5; // depends on mainnet or testnet - string consensusBranchId = 6; // protocol identifier, see consensus/upgrades.cpp - uint64 blockHeight = 7; // latest block on the best chain - string gitCommit = 8; - string branch = 9; - string buildDate = 10; - string buildUser = 11; - uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing - string zcashdBuild = 13; // example: "v4.1.1-877212414" - string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/" + string version = 1; + string vendor = 2; + bool taddrSupport = 3; // true + string chainName = 4; // either "main" or "test" + uint64 saplingActivationHeight = 5; // depends on mainnet or testnet + string consensusBranchId = + 6; // protocol identifier, see consensus/upgrades.cpp + uint64 blockHeight = 7; // latest block on the best chain + string gitCommit = 8; + string branch = 9; + string buildDate = 10; + string buildUser = 11; + uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing + string zcashdBuild = 13; // example: "v4.1.1-877212414" + string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/" } // TransparentAddressBlockFilter restricts the results to the given address // or block range. message TransparentAddressBlockFilter { - string address = 1; // t-address - BlockRange range = 2; // start, end heights + string address = 1; // t-address + BlockRange range = 2; // start, end heights } // Duration is currently used only for testing, so that the Ping rpc // can simulate a delay, to create many simultaneous connections. Units // are microseconds. -message Duration { - int64 intervalUs = 1; -} +message Duration { int64 intervalUs = 1; } // PingResponse is used to indicate concurrency, how many Ping rpcs // are executing upon entry and upon exit (after the delay). // This rpc is used for testing only. message PingResponse { - int64 entry = 1; - int64 exit = 2; + int64 entry = 1; + int64 exit = 2; } -message Address { - string address = 1; -} -message AddressList { - repeated string addresses = 1; -} -message Balance { - int64 valueZat = 1; -} +message Address { string address = 1; } +message AddressList { repeated string addresses = 1; } +message Balance { int64 valueZat = 1; } -message Exclude { - repeated bytes txid = 1; -} +message Exclude { repeated bytes txid = 1; } // The TreeState is derived from the Zcash z_gettreestate rpc. message TreeState { - string network = 1; // "main" or "test" - uint64 height = 2; // block height - string hash = 3; // block id - uint32 time = 4; // Unix epoch time when the block was mined - string saplingTree = 5; // sapling commitment tree state - string orchardTree = 6; // orchard commitment tree state - string ironwoodTree = 7; // ironwood commitment tree state + string network = 1; // "main" or "test" + uint64 height = 2; // block height + string hash = 3; // block id + uint32 time = 4; // Unix epoch time when the block was mined + string saplingTree = 5; // sapling commitment tree state + string orchardTree = 6; // orchard commitment tree state + string ironwoodTree = 7; // ironwood commitment tree state } // Results are sorted by height, which makes it easy to issue another // request that picks up from where the previous left off. message GetAddressUtxosArg { - repeated string addresses = 1; - uint64 startHeight = 2; - uint32 maxEntries = 3; // zero means unlimited + repeated string addresses = 1; + uint64 startHeight = 2; + uint32 maxEntries = 3; // zero means unlimited } message GetAddressUtxosReply { - string address = 6; - bytes txid = 1; - int32 index = 2; - bytes script = 3; - int64 valueZat = 4; - uint64 height = 5; + string address = 6; + bytes txid = 1; + int32 index = 2; + bytes script = 3; + int64 valueZat = 4; + uint64 height = 5; } message GetAddressUtxosReplyList { - repeated GetAddressUtxosReply addressUtxos = 1; + repeated GetAddressUtxosReply addressUtxos = 1; } service CompactTxStreamer { - // Return the height of the tip of the best chain - rpc GetLatestBlock(ChainSpec) returns (BlockID) {} - // Return the compact block corresponding to the given block identifier - rpc GetBlock(BlockID) returns (CompactBlock) {} - // Return a list of consecutive compact blocks - rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} - - // Return the requested full (not compact) transaction (as from zcashd) - rpc GetTransaction(TxFilter) returns (RawTransaction) {} - // Submit the given transaction to the Zcash network - rpc SendTransaction(RawTransaction) returns (SendResponse) {} - - // Return the txids corresponding to the given t-address within the given block range - rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {} - rpc GetTaddressBalance(AddressList) returns (Balance) {} - rpc GetTaddressBalanceStream(stream Address) returns (Balance) {} - - // Return the compact transactions currently in the mempool; the results - // can be a few seconds out of date. If the Exclude list is empty, return - // all transactions; otherwise return all *except* those in the Exclude list - // (if any); this allows the client to avoid receiving transactions that it - // already has (from an earlier call to this rpc). The transaction IDs in the - // Exclude list can be shortened to any number of bytes to make the request - // more bandwidth-efficient; if two or more transactions in the mempool - // match a shortened txid, they are all sent (none is excluded). Transactions - // in the exclude list that don't exist in the mempool are ignored. - rpc GetMempoolTx(Exclude) returns (stream CompactTx) {} - - // Return a stream of current Mempool transactions. This will keep the output stream open while - // there are mempool transactions. It will close the returned stream when a new block is mined. - rpc GetMempoolStream(Empty) returns (stream RawTransaction) {} - - // GetTreeState returns the note commitment tree state corresponding to the given block. - // See section 3.7 of the Zcash protocol specification. It returns several other useful - // values also (even though they can be obtained using GetBlock). - // The block can be specified by either height or hash. - rpc GetTreeState(BlockID) returns (TreeState) {} - - rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} - rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {} - - // Return information about this lightwalletd instance and the blockchain - rpc GetLightdInfo(Empty) returns (LightdInfo) {} - // Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) - rpc Ping(Duration) returns (PingResponse) {} + // Return the height of the tip of the best chain + rpc GetLatestBlock(ChainSpec) returns (BlockID) {} + // Return the compact block corresponding to the given block identifier + rpc GetBlock(BlockID) returns (CompactBlock) {} + // Return a list of consecutive compact blocks + rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} + + // Return the requested full (not compact) transaction (as from zcashd) + rpc GetTransaction(TxFilter) returns (RawTransaction) {} + // Submit the given transaction to the Zcash network + rpc SendTransaction(RawTransaction) returns (SendResponse) {} + + // Return the txids corresponding to the given t-address within the given + // block range + rpc GetTaddressTxids(TransparentAddressBlockFilter) + returns (stream RawTransaction) {} + rpc GetTaddressBalance(AddressList) returns (Balance) {} + rpc GetTaddressBalanceStream(stream Address) returns (Balance) {} + + // Return the compact transactions currently in the mempool; the results + // can be a few seconds out of date. If the Exclude list is empty, return + // all transactions; otherwise return all *except* those in the Exclude list + // (if any); this allows the client to avoid receiving transactions that it + // already has (from an earlier call to this rpc). The transaction IDs in the + // Exclude list can be shortened to any number of bytes to make the request + // more bandwidth-efficient; if two or more transactions in the mempool + // match a shortened txid, they are all sent (none is excluded). Transactions + // in the exclude list that don't exist in the mempool are ignored. + rpc GetMempoolTx(Exclude) returns (stream CompactTx) {} + + // Return a stream of current Mempool transactions. This will keep the output + // stream open while there are mempool transactions. It will close the + // returned stream when a new block is mined. + rpc GetMempoolStream(Empty) returns (stream RawTransaction) {} + + // GetTreeState returns the note commitment tree state corresponding to the + // given block. See section 3.7 of the Zcash protocol specification. It + // returns several other useful values also (even though they can be obtained + // using GetBlock). The block can be specified by either height or hash. + rpc GetTreeState(BlockID) returns (TreeState) {} + + rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} + rpc GetAddressUtxosStream(GetAddressUtxosArg) + returns (stream GetAddressUtxosReply) {} + + // Return information about this lightwalletd instance and the blockchain + rpc GetLightdInfo(Empty) returns (LightdInfo) {} + // Testing-only, requires lightwalletd --ping-very-insecure (do not enable in + // production) + rpc Ping(Duration) returns (PingResponse) {} } diff --git a/rust/src/account.rs b/rust/src/account.rs index d0a3669e9..24de7bec7 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -27,9 +27,7 @@ use crate::{ pay::pool::ALL_POOLS, }; use secp256k1::{PublicKey, SecretKey}; -use zcash_keys::keys::{ - sapling::ExtendedSpendingKey, UnifiedFullViewingKey, UnifiedSpendingKey, -}; +use zcash_keys::keys::{sapling::ExtendedSpendingKey, UnifiedFullViewingKey, UnifiedSpendingKey}; use zcash_transparent::address::TransparentAddress; use anyhow::{anyhow, Context, Result}; @@ -379,8 +377,7 @@ pub async fn new_account( _ => {} } update_dindex(&mut db_tx, account, dindex, true).await?; - } - else { + } else { anyhow::bail!("Unsupported key"); } db_tx.commit().await?; @@ -946,10 +943,7 @@ pub async fn init_sync_heights( account: u32, birth_height: u32, ) -> Result<()> { - let max_pool = if network - .activation_height(NetworkUpgrade::Nu6_3) - .is_some() - { + let max_pool = if network.activation_height(NetworkUpgrade::Nu6_3).is_some() { 4 } else { 3 @@ -981,15 +975,17 @@ pub async fn init_sync_heights( Ok(()) } -pub(crate) fn asset_display(id_asset: Option, asset_name: Option, asset_desc_hash: Option>) -> String { +pub(crate) fn asset_display( + id_asset: Option, + asset_name: Option, + asset_desc_hash: Option>, +) -> String { match id_asset { - Some(_) => asset_name - .filter(|n| !n.is_empty()) - .unwrap_or_else(|| { - asset_desc_hash - .map(|h| hex::encode(&h[..8.min(h.len())])) - .unwrap_or_else(|| "ZSA".to_string()) - }), + Some(_) => asset_name.filter(|n| !n.is_empty()).unwrap_or_else(|| { + asset_desc_hash + .map(|h| hex::encode(&h[..8.min(h.len())])) + .unwrap_or_else(|| "ZSA".to_string()) + }), None => "ZEC".to_string(), } } diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index 126ddbbe8..c5990a8e4 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -1,15 +1,15 @@ use std::collections::HashMap; use std::str::FromStr; +use crate::keys::{SaplingAddressDerivation, ScopeExt}; +use crate::pay::pool::PoolMask; use anyhow::{anyhow, Result}; use bip39::Mnemonic; use csv_async::AsyncWriter; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; use sapling_crypto::{zip32::sapling_derive_internal_fvk, PaymentAddress}; -use crate::keys::{SaplingAddressDerivation, ScopeExt}; -use crate::pay::pool::PoolMask; -use sqlx::{Row, SqliteConnection, sqlite::SqliteRow}; +use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use zcash_address::unified::{Container, Encoding}; use zcash_keys::{ address::UnifiedAddress, @@ -425,7 +425,11 @@ pub async fn fetch_transparent_address_tx_count(c: &Coin) -> Result Result> { +pub async fn fetch_address_tx_count( + c: &Coin, + aggregate: bool, + pool_filter: u8, +) -> Result> { let mut connection = c.get_connection().await?; let network = c.network(); @@ -435,9 +439,23 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) let s_pool = crate::db::select_account_sapling(&network, &mut connection, c.account).await; let o_pool = crate::db::select_account_orchard(&mut connection, c.account).await; - let enabled_pools = (if t_pool.as_ref().map(|t| t.xvk.is_some() || t.address.is_some()).unwrap_or(false) { 1u8 } else { 0u8 }) - | (if s_pool.as_ref().map(|s| s.xvk.is_some()).unwrap_or(false) { 2u8 } else { 0u8 }) - | (if o_pool.as_ref().map(|o| o.xvk.is_some()).unwrap_or(false) { 4u8 } else { 0u8 }); + let enabled_pools = (if t_pool + .as_ref() + .map(|t| t.xvk.is_some() || t.address.is_some()) + .unwrap_or(false) + { + 1u8 + } else { + 0u8 + }) | (if s_pool.as_ref().map(|s| s.xvk.is_some()).unwrap_or(false) { + 2u8 + } else { + 0u8 + }) | (if o_pool.as_ref().map(|o| o.xvk.is_some()).unwrap_or(false) { + 4u8 + } else { + 0u8 + }); // Only derive addresses for pools that are both selected and enabled let selected = PoolMask(pool_filter).intersect(&PoolMask(enabled_pools)); @@ -447,7 +465,8 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) let okeys = o_pool?; // Fetch per-slot stats for transparent and shielded pools - let transparent_stats = crate::db::fetch_transparent_slot_stats(&mut connection, c.account).await?; + let transparent_stats = + crate::db::fetch_transparent_slot_stats(&mut connection, c.account).await?; let shielded_stats = crate::db::fetch_shielded_slot_stats(&mut connection, c.account).await?; // Per-pool stats lookups (kept separate, not merged) @@ -461,16 +480,17 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) .collect(); // Pre-compute internal Sapling IVK - let internal_sap_ivk: Option = skeys.xvk.as_ref().and_then(|dfvk| { - let dfvk_bytes = dfvk.to_bytes(); - let dk_bytes: [u8; 32] = dfvk_bytes[96..128].try_into().ok()?; - let dk = sapling_crypto::zip32::DiversifierKey::from_bytes(dk_bytes); - let (int_fvk, int_dk) = sapling_derive_internal_fvk(dfvk.fvk(), &dk); - let mut ivk_bytes = [0u8; 64]; - ivk_bytes[..32].copy_from_slice(int_dk.as_bytes()); - ivk_bytes[32..].copy_from_slice(&int_fvk.vk.ivk().to_repr()); - sapling_crypto::zip32::IncomingViewingKey::from_bytes(&ivk_bytes).into_option() - }); + let internal_sap_ivk: Option = + skeys.xvk.as_ref().and_then(|dfvk| { + let dfvk_bytes = dfvk.to_bytes(); + let dk_bytes: [u8; 32] = dfvk_bytes[96..128].try_into().ok()?; + let dk = sapling_crypto::zip32::DiversifierKey::from_bytes(dk_bytes); + let (int_fvk, int_dk) = sapling_derive_internal_fvk(dfvk.fvk(), &dk); + let mut ivk_bytes = [0u8; 64]; + ivk_bytes[..32].copy_from_slice(int_dk.as_bytes()); + ivk_bytes[32..].copy_from_slice(&int_fvk.vk.ivk().to_repr()); + sapling_crypto::zip32::IncomingViewingKey::from_bytes(&ivk_bytes).into_option() + }); let mut results = Vec::new(); @@ -498,19 +518,33 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) let mut t_addr_raw: Option = None; let t_str = if selected.has_pool(0) { if let Some(tvk) = &tkeys.xvk { - let (_, taddr) = crate::account::derive_transparent_address(tvk, scope as u32, d, false)?; + let (_, taddr) = crate::account::derive_transparent_address( + tvk, + scope as u32, + d, + false, + )?; t_addr_raw = Some(taddr); Some(taddr.encode(&network)) - } else { None } - } else { None }; + } else { + None + } + } else { + None + }; let mut s_addr_raw: Option = None; let s_str = if selected.has_pool(1) { if let Some(dfvk) = &skeys.xvk { - s_addr_raw = dfvk.sapling_address_at(scope, d as u64, internal_sap_ivk.as_ref()); + s_addr_raw = + dfvk.sapling_address_at(scope, d as u64, internal_sap_ivk.as_ref()); s_addr_raw.as_ref().map(|pa| pa.encode(&network)) - } else { None } - } else { None }; + } else { + None + } + } else { + None + }; let mut o_addr_raw: Option = None; let o_str = if selected.has_pool(2) { @@ -518,14 +552,27 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) let s = scope.orchard_scope(); let addr = fvk.address_at(d as u64, s); o_addr_raw = Some(addr); - Some(UnifiedAddress::from_receivers(Some(addr), None, None).unwrap().encode(&network)) - } else { None } - } else { None }; + Some( + UnifiedAddress::from_receivers(Some(addr), None, None) + .unwrap() + .encode(&network), + ) + } else { + None + } + } else { + None + }; if aggregate { - if let Some(ua) = UnifiedAddress::from_receivers(o_addr_raw, s_addr_raw, t_addr_raw) { + if let Some(ua) = + UnifiedAddress::from_receivers(o_addr_raw, s_addr_raw, t_addr_raw) + { results.push(TAddressTxCount { - pool: 0, address: ua.encode(&network), scope, dindex: d, + pool: 0, + address: ua.encode(&network), + scope, + dindex: d, amount: t_st.0.wrapping_add(s_st.0).wrapping_add(o_st.0), tx_count: t_st.1.wrapping_add(s_st.1).wrapping_add(o_st.1), time: t_st.2.max(s_st.2).max(o_st.2), @@ -533,13 +580,37 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) } } else { if let Some(addr) = t_str { - results.push(TAddressTxCount { pool: 0, address: addr, scope, dindex: d, amount: t_st.0, tx_count: t_st.1, time: t_st.2 }); + results.push(TAddressTxCount { + pool: 0, + address: addr, + scope, + dindex: d, + amount: t_st.0, + tx_count: t_st.1, + time: t_st.2, + }); } if let Some(addr) = s_str { - results.push(TAddressTxCount { pool: 1, address: addr, scope, dindex: d, amount: s_st.0, tx_count: s_st.1, time: s_st.2 }); + results.push(TAddressTxCount { + pool: 1, + address: addr, + scope, + dindex: d, + amount: s_st.0, + tx_count: s_st.1, + time: s_st.2, + }); } if let Some(addr) = o_str { - results.push(TAddressTxCount { pool: 2, address: addr, scope, dindex: d, amount: o_st.0, tx_count: o_st.1, time: o_st.2 }); + results.push(TAddressTxCount { + pool: 2, + address: addr, + scope, + dindex: d, + amount: o_st.0, + tx_count: o_st.1, + time: o_st.2, + }); } } } else if d == 0 && selected.has_pool(0) { @@ -548,24 +619,35 @@ pub async fn fetch_address_tx_count(c: &Coin, aggregate: bool, pool_filter: u8) let t_st = t_stats.get(&(scope, 0)).copied().unwrap_or((0, 0, 0)); let t_str = if let Some(tvk) = &tkeys.xvk { - let (_, taddr) = crate::account::derive_transparent_address( - tvk, scope as u32, 0, false, - )?; + let (_, taddr) = + crate::account::derive_transparent_address(tvk, scope as u32, 0, false)?; Some(taddr.encode(&network)) - } else { None }; + } else { + None + }; // Aggregate of 1 taddr is the taddr itself. if let Some(addr) = t_str { results.push(TAddressTxCount { - pool: 0, address: addr, scope, dindex: 0, - amount: t_st.0, tx_count: t_st.1, time: t_st.2, + pool: 0, + address: addr, + scope, + dindex: 0, + amount: t_st.0, + tx_count: t_st.1, + time: t_st.2, }); } } } } - results.sort_by(|a, b| a.scope.cmp(&b.scope).then(a.dindex.cmp(&b.dindex)).then(a.pool.cmp(&b.pool))); + results.sort_by(|a, b| { + a.scope + .cmp(&b.scope) + .then(a.dindex.cmp(&b.dindex)) + .then(a.pool.cmp(&b.pool)) + }); Ok(results) } @@ -611,7 +693,6 @@ pub async fn print_keys(id: u32, c: &Coin) -> Result<()> { .fetch_one(&mut *connection) .await?; - let seed = seed.unwrap(); let memo = Mnemonic::from_str(&seed).unwrap(); let seed = memo.to_seed(""); @@ -753,7 +834,9 @@ pub async fn max_spendable(c: &Coin) -> Result { pub async fn show_ledger_sapling_address(c: &Coin) -> Result { let mut connection = c.get_connection().await?; let ledger = get_ledger(&mut connection, c.account).await?; - let r = ledger.show_sapling_address(&c.network(), &mut connection, c.account).await?; + let r = ledger + .show_sapling_address(&c.network(), &mut connection, c.account) + .await?; Ok(r) } @@ -761,7 +844,9 @@ pub async fn show_ledger_sapling_address(c: &Coin) -> Result { pub async fn show_ledger_transparent_address(c: &Coin) -> Result { let mut connection = c.get_connection().await?; let ledger = get_ledger(&mut connection, c.account).await?; - let r = ledger.show_transparent_address(&c.network(), &mut connection, c.account).await?; + let r = ledger + .show_transparent_address(&c.network(), &mut connection, c.account) + .await?; Ok(r) } @@ -838,7 +923,10 @@ pub struct TxMemo { pub memo_bytes: Vec, } -pub(crate) async fn get_ledger(connection: &mut SqliteConnection, account: u32) -> Result> { +pub(crate) async fn get_ledger( + connection: &mut SqliteConnection, + account: u32, +) -> Result> { let hw = get_account_hw(connection, account).await?; let r: Box = if hw == 1 { #[cfg(feature = "ledger")] diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index a1220ad44..c41992b8d 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -4,7 +4,7 @@ use std::sync::{LazyLock, OnceLock}; use anyhow::Result; use arti_client::config::TorClientConfigBuilder; use arti_client::TorClient; -#[cfg(feature="flutter")] +#[cfg(feature = "flutter")] use flutter_rust_bridge::frb; use hyper_util::rt::TokioIo; use sqlx::pool::PoolConnection; @@ -22,7 +22,6 @@ use crate::lwd::compact_tx_streamer_client::CompactTxStreamerClient; use crate::net::zebra::ZebraClient; use crate::{Client, IntoAnyhow}; - #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] #[derive(Clone)] pub struct Coin { @@ -45,7 +44,11 @@ impl Coin { ) -> Result { let network = self.network(); - let hint_coin = if self.coin != 0 { Some(self.coin) } else { None }; + let hint_coin = if self.coin != 0 { + Some(self.coin) + } else { + None + }; let pool = try_open(&db_filepath, &password, hint_coin).await?; { let mut pools = POOLS.lock().unwrap(); @@ -92,22 +95,20 @@ impl Coin { match self.coin { 0 => Network::Main, 1 => Network::Test, - 2 => { - Network::Regtest(LocalNetwork { - overwinter: Some(BlockHeight::from_u32(1)), - sapling: Some(BlockHeight::from_u32(1)), - blossom: Some(BlockHeight::from_u32(1)), - heartwood: Some(BlockHeight::from_u32(1)), - canopy: Some(BlockHeight::from_u32(1)), - nu5: Some(BlockHeight::from_u32(1)), - nu6: Some(BlockHeight::from_u32(1)), - nu6_1: Some(BlockHeight::from_u32(1)), - nu6_2: Some(BlockHeight::from_u32(1)), - nu6_3: Some(BlockHeight::from_u32(250)), - nu7: None, - orchard_mode: OrchardMode::Normal, - }) - } + 2 => Network::Regtest(LocalNetwork { + overwinter: Some(BlockHeight::from_u32(1)), + sapling: Some(BlockHeight::from_u32(1)), + blossom: Some(BlockHeight::from_u32(1)), + heartwood: Some(BlockHeight::from_u32(1)), + canopy: Some(BlockHeight::from_u32(1)), + nu5: Some(BlockHeight::from_u32(1)), + nu6: Some(BlockHeight::from_u32(1)), + nu6_1: Some(BlockHeight::from_u32(1)), + nu6_2: Some(BlockHeight::from_u32(1)), + nu6_3: Some(BlockHeight::from_u32(250)), + nu7: None, + orchard_mode: OrchardMode::Normal, + }), 3 => { // ZSA regtest: NU7 active, no Ironwood (NU6.3 not active). // Orchard protocol V2 with cross-address transfers enabled. @@ -145,18 +146,12 @@ impl Coin { pub async fn set_account(self, account: u32) -> Result { let mut conn = self.get_connection().await?; put_prop(&mut *conn, "account", &account.to_string()).await?; - Ok(Coin { - account, - ..self - }) + Ok(Coin { account, ..self }) } #[cfg_attr(feature = "flutter", frb)] pub fn set_use_tor(self, use_tor: bool) -> Result { - Ok(Coin { - use_tor, - ..self - }) + Ok(Coin { use_tor, ..self }) } #[cfg_attr(feature = "flutter", frb(sync))] @@ -369,16 +364,12 @@ pub(crate) async fn open_proxied_stream( // proxy. We resolve here explicitly so the distinction from socks5h is // honoured even though tokio-socks would otherwise defer to the proxy. "socks5" => { - let mut addrs = - tokio::net::lookup_host((target_host, target_port)).await?; + let mut addrs = tokio::net::lookup_host((target_host, target_port)).await?; let target_addr = addrs .next() .ok_or_else(|| anyhow::anyhow!("could not resolve {target_host}"))?; - let stream = tokio_socks::tcp::Socks5Stream::connect( - (phost, pport), - target_addr, - ) - .await?; + let stream = + tokio_socks::tcp::Socks5Stream::connect((phost, pport), target_addr).await?; Ok(stream.into_inner()) } "http" | "https" => http_connect_tunnel(phost, pport, target_host, target_port).await, diff --git a/rust/src/api/contacts.rs b/rust/src/api/contacts.rs index 59cba0d91..d3cf17a05 100644 --- a/rust/src/api/contacts.rs +++ b/rust/src/api/contacts.rs @@ -35,7 +35,8 @@ pub async fn create_contact( ) -> Result { let mut connection = c.get_connection().await?; let network = c.network(); - let result = contacts::create_contact(&mut connection, name, &addresses, notes, &network).await?; + let result = + contacts::create_contact(&mut connection, name, &addresses, notes, &network).await?; Ok(result.into()) } @@ -83,8 +84,7 @@ pub async fn find_contacts_for_address(address: &str, c: &Coin) -> Result Result Err(_) => return Ok(vec![]), }; - let rows = match sqlx::query( - "SELECT id_account, name FROM accounts ORDER BY position", - ) - .fetch_all(&mut *connection) - .await + let rows = match sqlx::query("SELECT id_account, name FROM accounts ORDER BY position") + .fetch_all(&mut *connection) + .await { Ok(rows) => rows, Err(_) => return Ok(vec![]), diff --git a/rust/src/api/frost.rs b/rust/src/api/frost.rs index f97c3f748..6f45c71f5 100644 --- a/rust/src/api/frost.rs +++ b/rust/src/api/frost.rs @@ -1,6 +1,6 @@ -use anyhow::{Ok, Result}; #[cfg(feature = "flutter")] use crate::frb_generated::StreamSink; +use anyhow::{Ok, Result}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; use serde::{Deserialize, Serialize}; diff --git a/rust/src/api/issuance.rs b/rust/src/api/issuance.rs index d36436897..57f61aff4 100644 --- a/rust/src/api/issuance.rs +++ b/rust/src/api/issuance.rs @@ -87,7 +87,8 @@ pub async fn issue_asset( // ── 2. Compute or use provided asset description hash ──────────────── let is_reissuance = desc_hash.is_some(); let desc_hash: [u8; 32] = if let Some(hash) = desc_hash { - hash.clone().try_into() + hash.clone() + .try_into() .map_err(|_| anyhow!("desc_hash must be exactly 32 bytes"))? } else { let name_bytes = asset_name.as_bytes().to_vec(); @@ -118,15 +119,15 @@ pub async fn issue_asset( &mut client, account, ALL_POOLS, - &[], // no recipients — issuance output goes to issuer - false, // recipient_pays_fee - None, // confirmations - false, // smart_transparent - None, // category + &[], // no recipients — issuance output goes to issuer + false, // recipient_pays_fee + None, // confirmations + false, // smart_transparent + None, // category Some(&issuance_info), - false, // migration - None, // preselected - None, // anchor_height + false, // migration + None, // preselected + None, // anchor_height ) .await?; diff --git a/rust/src/api/key.rs b/rust/src/api/key.rs index 477e7a984..f670a146b 100644 --- a/rust/src/api/key.rs +++ b/rust/src/api/key.rs @@ -1,11 +1,12 @@ use anyhow::Result; -use rand_core::{OsRng, RngCore as _}; -use zcash_keys::keys::UnifiedFullViewingKey; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; +use rand_core::{OsRng, RngCore as _}; +use zcash_keys::keys::UnifiedFullViewingKey; use crate::{ - api::coin::Coin, key::{is_valid_sapling_key, is_valid_transparent_key} + api::coin::Coin, + key::{is_valid_sapling_key, is_valid_transparent_key}, }; #[cfg_attr(feature = "flutter", frb(sync))] @@ -94,10 +95,17 @@ pub fn get_key_pools(key: &str, c: &Coin) -> Result { if crate::key::is_valid_ufvk(network, key) { let mut pools = 0; - let ufvk = UnifiedFullViewingKey::decode(network, key).map_err(|_| anyhow::anyhow!("Invalid UFVK"))?; - if ufvk.transparent().is_some() { pools |= 1; } - if ufvk.sapling().is_some() { pools |= 2; } - if ufvk.orchard().is_some() { pools |= 4; } + let ufvk = UnifiedFullViewingKey::decode(network, key) + .map_err(|_| anyhow::anyhow!("Invalid UFVK"))?; + if ufvk.transparent().is_some() { + pools |= 1; + } + if ufvk.sapling().is_some() { + pools |= 2; + } + if ufvk.orchard().is_some() { + pools |= 4; + } return Ok(pools); } diff --git a/rust/src/api/mempool.rs b/rust/src/api/mempool.rs index d64959a8b..d0a9b496f 100644 --- a/rust/src/api/mempool.rs +++ b/rust/src/api/mempool.rs @@ -2,7 +2,7 @@ use anyhow::Result; use tokio::runtime::Runtime; pub use tokio_util::sync::CancellationToken; -use crate::{api::coin::Coin}; +use crate::api::coin::Coin; #[cfg(feature = "flutter")] use crate::frb_generated::StreamSink; #[cfg(feature = "flutter")] @@ -12,7 +12,7 @@ use flutter_rust_bridge::frb; async fn run_mempool( mempool_sink: StreamSink, cancel_token: CancellationToken, - c: &Coin + c: &Coin, ) -> Result<()> { let mut connection = c.get_connection().await?; let r = crate::mempool::run_mempool( diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index e474eb7a6..ee1538929 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -53,13 +53,7 @@ impl NoteMigration { c: &Coin, mean_delay_ms: u64, ) -> Result<()> { - run_migration( - sink, - c, - mean_delay_ms, - self.cancellation_token.clone(), - ) - .await + run_migration(sink, c, mean_delay_ms, self.cancellation_token.clone()).await } pub fn cancel(&self) { @@ -72,8 +66,12 @@ impl NoteMigration { pub async fn step_migration(c: &Coin) -> Result { let (event, _status) = do_step(c, 0, 0, true, true).await?; Ok(match event { - crate::migrate::MigrationEvent::SplitComplete { fee } => MigrationEvent::SplitComplete { fee }, - crate::migrate::MigrationEvent::MigrateComplete { fee } => MigrationEvent::MigrateComplete { fee }, + crate::migrate::MigrationEvent::SplitComplete { fee } => { + MigrationEvent::SplitComplete { fee } + } + crate::migrate::MigrationEvent::MigrateComplete { fee } => { + MigrationEvent::MigrateComplete { fee } + } crate::migrate::MigrationEvent::Complete => MigrationEvent::Complete, crate::migrate::MigrationEvent::NothingToDo => MigrationEvent::NothingToDo, }) @@ -102,11 +100,17 @@ async fn run_migration( if !network.is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height)) { sink.add(MigrationStatus { phase: "complete".into(), - split_fees: 0, migrate_fees: 0, total_fees: 0, - sd_notes_count: 0, non_sd_notes_count: 0, ironwood_sd_count: 0, + split_fees: 0, + migrate_fees: 0, + total_fees: 0, + sd_notes_count: 0, + non_sd_notes_count: 0, + ironwood_sd_count: 0, progress: 1.0, - next_action: String::new(), work_summary: String::new(), - }).ok(); + next_action: String::new(), + work_summary: String::new(), + }) + .ok(); return Ok(()); } @@ -130,7 +134,9 @@ async fn run_migration( tracing::info!( "Migration delay: {}ms (mean={}ms, u={:.6})", - delay_ms, mean_delay_ms, u + delay_ms, + mean_delay_ms, + u ); status.next_action = format!("Waiting {}s...", delay_secs); @@ -273,12 +279,16 @@ async fn current_migration_status( acc_migrate: u64, ) -> Result { let mut connection = c.get_connection().await?; - let all_notes = crate::pay::plan::fetch_unspent_notes_grouped_by_pool(&mut connection, c.account).await?; + let all_notes = + crate::pay::plan::fetch_unspent_notes_grouped_by_pool(&mut connection, c.account).await?; let orchard_zec: Vec<&crate::pay::InputNote> = all_notes .iter() .filter(|n| n.pool == 2 && n.asset_base == vec![0u8; 32]) .collect(); - let sd_count = orchard_zec.iter().filter(|n| crate::migrate::is_sd(n.amount)).count() as u32; + let sd_count = orchard_zec + .iter() + .filter(|n| crate::migrate::is_sd(n.amount)) + .count() as u32; let non_sd_vals: Vec = orchard_zec .iter() .filter(|n| !crate::migrate::is_sd(n.amount)) @@ -294,7 +304,9 @@ async fn current_migration_status( // Count Ironwood SD notes for phase 2 progress (amount is value - SD_FEE_PAD). let ironwood_sd = all_notes .iter() - .filter(|n| n.pool == 3 && n.asset_base == vec![0u8; 32] && crate::migrate::is_iw_sd(n.amount)) + .filter(|n| { + n.pool == 3 && n.asset_base == vec![0u8; 32] && crate::migrate::is_iw_sd(n.amount) + }) .count() as u32; let total_sd = sd_count + ironwood_sd; @@ -308,9 +320,7 @@ async fn current_migration_status( "splitting" if sd_count + effective_non_sd > 0 => { sd_count as f64 / (sd_count + effective_non_sd) as f64 } - "migrating" if total_sd > 0 => { - ironwood_sd as f64 / total_sd as f64 - } + "migrating" if total_sd > 0 => ironwood_sd as f64 / total_sd as f64, _ => 1.0, }; @@ -351,13 +361,11 @@ async fn wait_for_anchor_boundary( client: &mut crate::Client, status: &MigrationStatus, ) -> Result<()> { - const HEIGHT_POLL_INTERVAL: std::time::Duration = - std::time::Duration::from_secs(10); + const HEIGHT_POLL_INTERVAL: std::time::Duration = std::time::Duration::from_secs(10); let observed_height = client.latest_height().await?; let db_height = wallet_height(c).await?; - let mut boundary = - crate::migrate::next_anchor_bucket_height(observed_height.max(db_height)); + let mut boundary = crate::migrate::next_anchor_bucket_height(observed_height.max(db_height)); let mut waiting = status.clone(); waiting.next_action = format!("Waiting for anchor block {}...", boundary); @@ -369,9 +377,7 @@ async fn wait_for_anchor_boundary( // If height polling missed the boundary, do not fetch its // historical tree state. Wait for a boundary that is observed as // the current tip. - boundary = crate::migrate::next_anchor_bucket_height( - tip.saturating_add(1), - ); + boundary = crate::migrate::next_anchor_bucket_height(tip.saturating_add(1)); let mut waiting = status.clone(); waiting.next_action = format!("Waiting for anchor block {}...", boundary); sink.add(waiting).ok(); @@ -398,8 +404,7 @@ async fn wait_for_anchor_boundary( tip.max(synced_height).saturating_add(1), ); let mut waiting = status.clone(); - waiting.next_action = - format!("Waiting for anchor block {}...", boundary); + waiting.next_action = format!("Waiting for anchor block {}...", boundary); sink.add(waiting).ok(); continue; } diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index 2e17e4574..d926119e0 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -1,6 +1,5 @@ -pub mod coin; pub mod account; -pub mod migrate; +pub mod coin; pub mod contacts; pub mod db; pub mod frost; @@ -8,14 +7,15 @@ pub mod init; pub mod issuance; pub mod key; pub mod mempool; +pub mod migrate; pub mod network; pub mod openalias; pub mod pay; pub mod plugin; -pub mod sync; -pub mod transaction; -pub mod sweep; pub mod raptor; pub mod sapling; +pub mod sweep; +pub mod sync; +pub mod transaction; pub mod vault; pub mod zsa; diff --git a/rust/src/api/openalias.rs b/rust/src/api/openalias.rs index 233d0a902..55815d212 100644 --- a/rust/src/api/openalias.rs +++ b/rust/src/api/openalias.rs @@ -38,10 +38,7 @@ fn status_to_string(status: DnssecStatus) -> String { /// Performs DNS TXT lookup, parses OA1 records, filters for Zcash /// addresses, and validates them against the wallet's network type. #[cfg_attr(feature = "flutter", frb)] -pub async fn resolve_openalias( - alias: String, - c: &Coin, -) -> Result { +pub async fn resolve_openalias(alias: String, c: &Coin) -> Result { let net = c.network().network_type(); let (recipients, status) = openalias::resolve_zcash_for_network(&alias, net).await?; Ok(OpenAliasResolution { diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index f5aae9459..3bc00448e 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -1,7 +1,10 @@ use anyhow::Result; use bincode::{config::legacy, Decode, Encode}; -use crate::{api::coin::Coin, pay::{Recipient, TxPlan, plan::plan_transaction}}; +use crate::{ + api::coin::Coin, + pay::{plan::plan_transaction, Recipient, TxPlan}, +}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; @@ -18,7 +21,11 @@ pub async fn build_puri(recipients: &[Recipient]) -> Result { } #[cfg_attr(feature = "flutter", frb)] -pub async fn prepare(recipients: &[Recipient], options: PaymentOptions, c: &Coin) -> Result { +pub async fn prepare( + recipients: &[Recipient], + options: PaymentOptions, + c: &Coin, +) -> Result { let account = c.account; let network = &c.network(); let mut connection = c.get_connection().await?; @@ -35,7 +42,7 @@ pub async fn prepare(recipients: &[Recipient], options: PaymentOptions, c: &Coin None, options.smart_transparent, options.category, - None, // issuance — normal sends have no issuance + None, // issuance — normal sends have no issuance false, // migration — only used by note migration None, // preselected None, // anchor_height @@ -64,13 +71,13 @@ pub async fn prepare_migration( src_pools, recipients, false, // recipient_pays_fee - None, // confirmations - false, // smart_transparent - None, // category - None, // issuance - true, // migration - None, // preselected - None, // anchor_height + None, // confirmations + false, // smart_transparent + None, // category + None, // issuance + true, // migration + None, // preselected + None, // anchor_height ) .await } @@ -146,8 +153,13 @@ pub async fn send(height: u32, data: &[u8], c: &Coin) -> Result { } #[cfg_attr(feature = "flutter", frb)] -pub async fn store_pending_tx(height: u32, txid: &[u8], - price: Option, category: Option, c: &Coin) -> Result<()> { +pub async fn store_pending_tx( + height: u32, + txid: &[u8], + price: Option, + category: Option, + c: &Coin, +) -> Result<()> { let mut connection = c.get_connection().await?; crate::db::store_pending_tx(&mut connection, c.account, height, txid, price, category).await?; diff --git a/rust/src/api/plugin.rs b/rust/src/api/plugin.rs index c6394d94e..3cbbe8882 100644 --- a/rust/src/api/plugin.rs +++ b/rust/src/api/plugin.rs @@ -1,6 +1,6 @@ -use anyhow::Result; use crate::api::coin::Coin; use crate::plugin; +use anyhow::Result; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; diff --git a/rust/src/api/raptor.rs b/rust/src/api/raptor.rs index 51a924ff5..37ccbd9b0 100644 --- a/rust/src/api/raptor.rs +++ b/rust/src/api/raptor.rs @@ -1,10 +1,14 @@ -use std::{fs::File, io::Read, sync::{LazyLock, Mutex}}; +use std::{ + fs::File, + io::Read, + sync::{LazyLock, Mutex}, +}; use anyhow::Result; -use qrcode::{bits::Bits, EcLevel}; -use raptorq::{Decoder, Encoder, EncodingPacket, ObjectTransmissionInformation}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; +use qrcode::{bits::Bits, EcLevel}; +use raptorq::{Decoder, Encoder, EncodingPacket, ObjectTransmissionInformation}; pub struct RaptorQParams { pub version: u16, @@ -87,13 +91,11 @@ fn ec_level_of(level: u8) -> EcLevel { } } -#[cfg(feature="flutter")] +#[cfg(feature = "flutter")] #[frb(init)] pub fn init_app() { // Default utilities - feel free to customize flutter_rust_bridge::setup_default_user_utils(); } -pub static DECODER: LazyLock>> = - LazyLock::new(|| Mutex::new(None)); - +pub static DECODER: LazyLock>> = LazyLock::new(|| Mutex::new(None)); diff --git a/rust/src/api/sapling.rs b/rust/src/api/sapling.rs index e80059df4..629b34fa2 100644 --- a/rust/src/api/sapling.rs +++ b/rust/src/api/sapling.rs @@ -52,10 +52,7 @@ pub struct SaplingParamsStatus { pub fn check_sapling_params() -> SaplingParamsStatus { let params_dir = resolve_params_dir(); let downloaded = params_dir - .map(|dir| { - dir.join(SAPLING_SPEND_NAME).exists() - && dir.join(SAPLING_OUTPUT_NAME).exists() - }) + .map(|dir| dir.join(SAPLING_SPEND_NAME).exists() && dir.join(SAPLING_OUTPUT_NAME).exists()) .unwrap_or(false); SaplingParamsStatus { downloaded } } @@ -66,20 +63,30 @@ pub fn check_sapling_params() -> SaplingParamsStatus { /// Safe to call even if they are already downloaded (no-op if valid). #[cfg_attr(feature = "flutter", frb)] pub async fn download_sapling_params() -> Result<()> { - let params_dir = resolve_params_dir() - .context("Could not resolve Sapling parameters directory")?; + let params_dir = + resolve_params_dir().context("Could not resolve Sapling parameters directory")?; // Ensure the params directory exists. std::fs::create_dir_all(¶ms_dir) .with_context(|| format!("Failed to create params directory: {:?}", params_dir))?; - download_and_verify(¶ms_dir, SAPLING_SPEND_NAME, SAPLING_SPEND_HASH, SAPLING_SPEND_BYTES) - .await - .context("Failed to download/verify sapling-spend.params")?; - - download_and_verify(¶ms_dir, SAPLING_OUTPUT_NAME, SAPLING_OUTPUT_HASH, SAPLING_OUTPUT_BYTES) - .await - .context("Failed to download/verify sapling-output.params")?; + download_and_verify( + ¶ms_dir, + SAPLING_SPEND_NAME, + SAPLING_SPEND_HASH, + SAPLING_SPEND_BYTES, + ) + .await + .context("Failed to download/verify sapling-spend.params")?; + + download_and_verify( + ¶ms_dir, + SAPLING_OUTPUT_NAME, + SAPLING_OUTPUT_HASH, + SAPLING_OUTPUT_BYTES, + ) + .await + .context("Failed to download/verify sapling-output.params")?; Ok(()) } diff --git a/rust/src/api/sync.rs b/rust/src/api/sync.rs index ad2602785..9a5d3faa1 100644 --- a/rust/src/api/sync.rs +++ b/rust/src/api/sync.rs @@ -39,8 +39,6 @@ pub async fn synchronize( .await } - - #[cfg_attr(feature = "flutter", frb)] pub async fn balance(c: &Coin) -> Result { let mut connection = c.get_connection().await?; diff --git a/rust/src/api/transaction.rs b/rust/src/api/transaction.rs index deb539f4b..bc9233021 100644 --- a/rust/src/api/transaction.rs +++ b/rust/src/api/transaction.rs @@ -1,5 +1,5 @@ -use anyhow::Result; use crate::api::coin::Coin; +use anyhow::Result; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; @@ -11,7 +11,11 @@ pub async fn fill_missing_tx_prices(api: String, currency: String, c: &Coin) -> } #[cfg_attr(feature = "flutter", frb)] -pub async fn update_historical_prices(currency: String, exchange_rate: f64, c: &Coin) -> Result<()> { +pub async fn update_historical_prices( + currency: String, + exchange_rate: f64, + c: &Coin, +) -> Result<()> { let mut connection = c.get_connection().await?; crate::budget::update_historical_prices(&mut connection, ¤cy, exchange_rate).await?; Ok(()) @@ -39,13 +43,22 @@ pub async fn set_tx_price(id: u32, price: Option, c: &Coin) -> Result<()> { } #[cfg_attr(feature = "flutter", frb)] -pub async fn fetch_category_amounts(from: Option, to: Option, c: &Coin) -> Result> { +pub async fn fetch_category_amounts( + from: Option, + to: Option, + c: &Coin, +) -> Result> { let mut connection = c.get_connection().await?; crate::budget::fetch_category_amounts(&mut connection, c.account, from, to).await } #[cfg_attr(feature = "flutter", frb)] -pub async fn fetch_amounts(from: Option, to: Option, category: u32, c: &Coin) -> Result> { +pub async fn fetch_amounts( + from: Option, + to: Option, + category: u32, + c: &Coin, +) -> Result> { let mut connection = c.get_connection().await?; crate::budget::fetch_amounts(&mut connection, c.account, from, to, category).await } diff --git a/rust/src/api/vault.rs b/rust/src/api/vault.rs index b87600625..ddc7e1d19 100644 --- a/rust/src/api/vault.rs +++ b/rust/src/api/vault.rs @@ -1,6 +1,6 @@ use anyhow::Result; -use flutter_rust_bridge::{DartFnFuture, frb}; +use flutter_rust_bridge::{frb, DartFnFuture}; use crate::vault::{DartVaultIO, Vault}; @@ -44,7 +44,9 @@ impl DartVault { ) -> Result<()> { let prf = <[u8; 32]>::try_from(prf_output) .map_err(|_| anyhow::anyhow!("Invalid PRF output length, expected 32 bytes"))?; - self.0.register_device(init_bytes, master_password, device_id_str, prf).await + self.0 + .register_device(init_bytes, master_password, device_id_str, prf) + .await } #[frb] @@ -58,11 +60,25 @@ impl DartVault { birth_height: u32, pk: Vec, ) -> Result<()> { - self.0.store_account(timestamp, name, seed, aindex, use_internal, birth_height, pk).await + self.0 + .store_account( + timestamp, + name, + seed, + aindex, + use_internal, + birth_height, + pk, + ) + .await } #[frb] - pub fn recover(&self, vault_bytes: Vec, master_password: String) -> Result> { + pub fn recover( + &self, + vault_bytes: Vec, + master_password: String, + ) -> Result> { let accounts = crate::vault::crypto::recover(&vault_bytes, &master_password)?; Ok(accounts) } diff --git a/rust/src/contacts.rs b/rust/src/contacts.rs index 37daaa6a9..8d6676f81 100644 --- a/rust/src/contacts.rs +++ b/rust/src/contacts.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Result}; -use sqlx::{Row, SqliteConnection}; use sqlx::sqlite::SqliteRow; +use sqlx::{Row, SqliteConnection}; use tracing::info; use vcard4::property::{AnyProperty, TextProperty}; @@ -78,7 +78,8 @@ pub fn expand_address_to_receivers_with_pool( } // Fallback: single-pool address (transparent, sapling) - let zaddr = ZcashAddress::try_from_encoded(addr).map_err(|e| anyhow!("Invalid address: {e}"))?; + let zaddr = + ZcashAddress::try_from_encoded(addr).map_err(|e| anyhow!("Invalid address: {e}"))?; let pool = if zaddr.can_receive_as(PoolType::Transparent) { 0u8 } else if zaddr.can_receive_as(PoolType::Shielded(ShieldedPool::Sapling)) { @@ -160,11 +161,10 @@ pub async fn create_contact( .execute(&mut *connection) .await?; - let id: u32 = - sqlx::query_scalar("SELECT id_contact FROM contacts WHERE name = ?1") - .bind(name) - .fetch_one(&mut *connection) - .await?; + let id: u32 = sqlx::query_scalar("SELECT id_contact FROM contacts WHERE name = ?1") + .bind(name) + .fetch_one(&mut *connection) + .await?; // Expand each address and store (receiver, pool) rows for (ordinal, addr) in addresses.iter().enumerate() { @@ -325,7 +325,12 @@ pub async fn export_contacts_vcard(connection: &mut SqliteConnection) -> Result< if !contact.addresses.is_empty() { note_parts.push(format!( "Zcash addresses:\n{}", - contact.addresses.iter().map(|a| format!("zcash:{a}")).collect::>().join("\n") + contact + .addresses + .iter() + .map(|a| format!("zcash:{a}")) + .collect::>() + .join("\n") )); } let note = note_parts.join("\n\n"); @@ -439,12 +444,11 @@ pub async fn import_contacts_vcard( } // Check for duplicate name - let existing: Option = sqlx::query_scalar( - "SELECT id_contact FROM contacts WHERE name = ?1", - ) - .bind(&name) - .fetch_optional(&mut *connection) - .await?; + let existing: Option = + sqlx::query_scalar("SELECT id_contact FROM contacts WHERE name = ?1") + .bind(&name) + .fetch_optional(&mut *connection) + .await?; if let Some(id) = existing { // Update existing contact diff --git a/rust/src/db.rs b/rust/src/db.rs index 40a3e0d76..1c3184728 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -1,11 +1,11 @@ use std::fs::File; +use crate::keys::{SaplingDiversifiedAddress, ScopeExt}; use anyhow::{anyhow, Result}; use csv_async::AsyncWriter; use futures::TryStreamExt; use orchard::keys::{FullViewingKey, SpendingKey}; use sapling_crypto::PaymentAddress; -use crate::keys::{SaplingDiversifiedAddress, ScopeExt}; use sqlx::{ sqlite::{SqliteConnectOptions, SqliteRow}, Column, Connection, Row, SqliteConnection, TypeInfo, @@ -256,25 +256,20 @@ pub async fn create_schema(connection: &mut SqliteConnection) -> Result<()> { .await?; // Migration: add id_asset to notes for ZSA note→asset linking - let _ = sqlx::query( - "ALTER TABLE notes ADD COLUMN id_asset INTEGER REFERENCES assets(id_asset)", - ) - .execute(&mut *connection) - .await; + let _ = + sqlx::query("ALTER TABLE notes ADD COLUMN id_asset INTEGER REFERENCES assets(id_asset)") + .execute(&mut *connection) + .await; // Migration: add diversifier_index to notes for per-address shielded tx counts - let _ = sqlx::query( - "ALTER TABLE notes ADD COLUMN diversifier_index INTEGER", - ) - .execute(&mut *connection) - .await; + let _ = sqlx::query("ALTER TABLE notes ADD COLUMN diversifier_index INTEGER") + .execute(&mut *connection) + .await; // Migration: add asset_name to assets for human-readable naming - let _ = sqlx::query( - "ALTER TABLE assets ADD COLUMN asset_name TEXT", - ) - .execute(&mut *connection) - .await; + let _ = sqlx::query("ALTER TABLE assets ADD COLUMN asset_name TEXT") + .execute(&mut *connection) + .await; // Migration: ensure asset_base is unique to prevent duplicate note inserts // caused by duplicate issuances with the same asset_base. @@ -398,9 +393,11 @@ pub async fn create_schema(connection: &mut SqliteConnection) -> Result<()> { let _ = sqlx::query("ALTER TABLE transactions ADD COLUMN zsa_value INTEGER NOT NULL DEFAULT 0") .execute(&mut *connection) .await; - let _ = sqlx::query("ALTER TABLE transactions ADD COLUMN asset_id INTEGER REFERENCES assets(id_asset)") - .execute(&mut *connection) - .await; + let _ = sqlx::query( + "ALTER TABLE transactions ADD COLUMN asset_id INTEGER REFERENCES assets(id_asset)", + ) + .execute(&mut *connection) + .await; if sqlx::query("SELECT 1 FROM sqlite_master WHERE type='table' AND name='categories'") .fetch_optional(&mut *connection) .await? @@ -673,26 +670,24 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re for (account,) in accounts { // Load Sapling DFVK for this account - let sapling_dfvk: Option = sqlx::query_as( - "SELECT xvk FROM sapling_accounts WHERE account = ?", - ) - .bind(account) - .fetch_optional(&mut *connection) - .await? - .map(|(xvk,): (Vec,)| { - DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap() - }); + let sapling_dfvk: Option = + sqlx::query_as("SELECT xvk FROM sapling_accounts WHERE account = ?") + .bind(account) + .fetch_optional(&mut *connection) + .await? + .map(|(xvk,): (Vec,)| { + DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap() + }); // Load Orchard FVK for this account - let orchard_fvk: Option = sqlx::query_as( - "SELECT xvk FROM orchard_accounts WHERE account = ?", - ) - .bind(account) - .fetch_optional(&mut *connection) - .await? - .map(|(xvk,): (Vec,)| { - FullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap() - }); + let orchard_fvk: Option = + sqlx::query_as("SELECT xvk FROM orchard_accounts WHERE account = ?") + .bind(account) + .fetch_optional(&mut *connection) + .await? + .map(|(xvk,): (Vec,)| { + FullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap() + }); // Fetch unbackfilled notes for this account let notes: Vec<(u32, u8, u8, Vec)> = sqlx::query_as( diff --git a/rust/src/frost/dkg.rs b/rust/src/frost/dkg.rs index 81c707392..c0d31383c 100644 --- a/rust/src/frost/dkg.rs +++ b/rust/src/frost/dkg.rs @@ -39,9 +39,14 @@ impl FrostBytes for SigningKey { fn from_bytes(data: &[u8]) -> Result { if data.len() != SECRET_KEY_LENGTH { - anyhow::bail!("Invalid SigningKey length: expected {}, got {}", SECRET_KEY_LENGTH, data.len()); + anyhow::bail!( + "Invalid SigningKey length: expected {}, got {}", + SECRET_KEY_LENGTH, + data.len() + ); } - let arr: [u8; SECRET_KEY_LENGTH] = data[..SECRET_KEY_LENGTH].try_into() + let arr: [u8; SECRET_KEY_LENGTH] = data[..SECRET_KEY_LENGTH] + .try_into() .map_err(|_| anyhow::anyhow!("Failed to convert slice to array"))?; Ok(SigningKey::from_bytes(&arr)) } @@ -54,9 +59,13 @@ impl FrostBytes for VerifyingKey { fn from_bytes(data: &[u8]) -> Result { if data.len() != 32 { - anyhow::bail!("Invalid VerifyingKey length: expected 32, got {}", data.len()); + anyhow::bail!( + "Invalid VerifyingKey length: expected 32, got {}", + data.len() + ); } - let arr: [u8; 32] = data.try_into() + let arr: [u8; 32] = data + .try_into() .map_err(|_| anyhow::anyhow!("Failed to convert slice to array"))?; VerifyingKey::from_bytes(&arr).map_err(|e| anyhow::anyhow!("Invalid VerifyingKey: {}", e)) } @@ -112,10 +121,16 @@ impl Round for DkgRound0 { } fn produce(input: &DkgInit) -> Result<(SigningKey, Broadcast)> { - info!("DKG Round0: generating signing keypair (self_id={}, n={}, t={})", input.self_id, input.n, input.t); + info!( + "DKG Round0: generating signing keypair (self_id={}, n={}, t={})", + input.self_id, input.n, input.t + ); let signing_key = SigningKey::generate(&mut OsRng); let verifying_key = signing_key.verifying_key(); - info!("DKG Round0: signing keypair generated, public key: {}", hex::encode(verifying_key.as_bytes())); + info!( + "DKG Round0: signing keypair generated, public key: {}", + hex::encode(verifying_key.as_bytes()) + ); Ok((signing_key, Broadcast(verifying_key.clone()))) } @@ -127,10 +142,13 @@ impl Round for DkgRound0 { let verifying_key = signing_key.verifying_key().clone(); let peer_verifying_keys: BTreeMap = peers .into_iter() - .filter(|(id, _)| *id != input.self_id) // Skip our own key + .filter(|(id, _)| *id != input.self_id) // Skip our own key .map(|(id, pk)| (id, pk)) .collect(); - info!("DKG Round0: collected {} peer verifying keys", peer_verifying_keys.len()); + info!( + "DKG Round0: collected {} peer verifying keys", + peer_verifying_keys.len() + ); Ok(DkgState0 { init: input, signing_key, @@ -147,9 +165,14 @@ impl Round for DkgRound0 { match result { Some((b,)) => { if b.len() != SECRET_KEY_LENGTH { - anyhow::bail!("Invalid SigningKey length in DB: expected {}, got {}", SECRET_KEY_LENGTH, b.len()); + anyhow::bail!( + "Invalid SigningKey length in DB: expected {}, got {}", + SECRET_KEY_LENGTH, + b.len() + ); } - let arr: [u8; SECRET_KEY_LENGTH] = b.try_into() + let arr: [u8; SECRET_KEY_LENGTH] = b + .try_into() .map_err(|_| anyhow::anyhow!("Failed to convert DB bytes to array"))?; Ok(Some(SigningKey::from_bytes(&arr))) } @@ -169,7 +192,12 @@ impl Round for DkgRound0 { Ok(()) } - async fn store_public(conn: &mut SqliteConnection, account: u32, from_id: u8, p: &VerifyingKey) -> Result<()> { + async fn store_public( + conn: &mut SqliteConnection, + account: u32, + from_id: u8, + p: &VerifyingKey, + ) -> Result<()> { sqlx::query( "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 0, ?2, ?3) ON CONFLICT DO NOTHING", @@ -182,22 +210,35 @@ impl Round for DkgRound0 { Ok(()) } - async fn load_publics(conn: &mut SqliteConnection, account: u32) -> Result> { - let rows = sqlx::query("SELECT from_id, data FROM dkg_peers WHERE account = ? AND round = 0") - .bind(account) - .map(|row: SqliteRow| (row.get::(0), row.get::, _>(1))) - .fetch_all(&mut *conn) - .await?; + async fn load_publics( + conn: &mut SqliteConnection, + account: u32, + ) -> Result> { + let rows = + sqlx::query("SELECT from_id, data FROM dkg_peers WHERE account = ? AND round = 0") + .bind(account) + .map(|row: SqliteRow| (row.get::(0), row.get::, _>(1))) + .fetch_all(&mut *conn) + .await?; let mut result = Vec::new(); for (id, data) in rows { if data.len() != 32 { - anyhow::bail!("Invalid VerifyingKey length for participant {}: expected 32, got {}", id, data.len()); + anyhow::bail!( + "Invalid VerifyingKey length for participant {}: expected 32, got {}", + id, + data.len() + ); } - let arr: [u8; 32] = data.try_into() - .map_err(|_| anyhow::anyhow!("Failed to convert VerifyingKey bytes for participant {}", id))?; - let vk = VerifyingKey::from_bytes(&arr) - .map_err(|e| anyhow::anyhow!("Invalid VerifyingKey for participant {}: {}", id, e))?; + let arr: [u8; 32] = data.try_into().map_err(|_| { + anyhow::anyhow!( + "Failed to convert VerifyingKey bytes for participant {}", + id + ) + })?; + let vk = VerifyingKey::from_bytes(&arr).map_err(|e| { + anyhow::anyhow!("Invalid VerifyingKey for participant {}: {}", id, e) + })?; result.push((id, vk)); } Ok(result) @@ -223,7 +264,10 @@ impl Round for DkgRound1 { } fn produce(input: &DkgState0) -> Result<(round1::SecretPackage, Broadcast)> { - info!("DKG: calling dkg::part1 (self_id={}, n={}, t={})", input.init.self_id, input.init.n, input.init.t); + info!( + "DKG: calling dkg::part1 (self_id={}, n={}, t={})", + input.init.self_id, input.init.n, input.init.t + ); let (spkg1, ppkg1) = dkg::part1( (input.init.self_id as u16).try_into()?, input.init.n as u16, @@ -241,22 +285,35 @@ impl Round for DkgRound1 { ) -> Result { let ppkg1s = peers .into_iter() - .filter(|(id, _)| *id != input.init.self_id) // Skip our own package + .filter(|(id, _)| *id != input.init.self_id) // Skip our own package .map(|(id, pkg)| Ok(((id as u16).try_into()?, pkg))) .collect::>()?; - Ok(DkgState1 { state0: input, spkg1, ppkg1s }) + Ok(DkgState1 { + state0: input, + spkg1, + ppkg1s, + }) } - async fn load_secret(conn: &mut SqliteConnection, account: u32) -> Result> { - sqlx::query_as::<_, (Vec,)>("SELECT spkg1 FROM dkg_state WHERE account = ? AND spkg1 IS NOT NULL") - .bind(account) - .fetch_optional(&mut *conn) - .await? - .map(|(b,)| round1::SecretPackage::from_bytes(&b)) - .transpose() + async fn load_secret( + conn: &mut SqliteConnection, + account: u32, + ) -> Result> { + sqlx::query_as::<_, (Vec,)>( + "SELECT spkg1 FROM dkg_state WHERE account = ? AND spkg1 IS NOT NULL", + ) + .bind(account) + .fetch_optional(&mut *conn) + .await? + .map(|(b,)| round1::SecretPackage::from_bytes(&b)) + .transpose() } - async fn store_secret(conn: &mut SqliteConnection, account: u32, s: &round1::SecretPackage) -> Result<()> { + async fn store_secret( + conn: &mut SqliteConnection, + account: u32, + s: &round1::SecretPackage, + ) -> Result<()> { sqlx::query( "INSERT INTO dkg_state(account, spkg1) VALUES(?1, ?2) ON CONFLICT(account) DO UPDATE SET spkg1 = excluded.spkg1", @@ -268,7 +325,12 @@ impl Round for DkgRound1 { Ok(()) } - async fn store_public(conn: &mut SqliteConnection, account: u32, from_id: u8, p: &round1::Package) -> Result<()> { + async fn store_public( + conn: &mut SqliteConnection, + account: u32, + from_id: u8, + p: &round1::Package, + ) -> Result<()> { sqlx::query( "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 1, ?2, ?3) ON CONFLICT DO NOTHING", @@ -281,7 +343,10 @@ impl Round for DkgRound1 { Ok(()) } - async fn load_publics(conn: &mut SqliteConnection, account: u32) -> Result> { + async fn load_publics( + conn: &mut SqliteConnection, + account: u32, + ) -> Result> { sqlx::query("SELECT from_id, data FROM dkg_peers WHERE account = ? AND round = 1") .bind(account) .map(|row: SqliteRow| (row.get::(0), row.get::, _>(1))) @@ -313,7 +378,10 @@ impl Round for DkgRound2 { fn produce(input: &DkgState1) -> Result<(round2::SecretPackage, PerPeer)> { // part2 takes spkg1 by value — clone since input is borrowed - info!("DKG: calling dkg::part2 (self_id={}, n={}, t={})", input.state0.init.self_id, input.state0.init.n, input.state0.init.t); + info!( + "DKG: calling dkg::part2 (self_id={}, n={}, t={})", + input.state0.init.self_id, input.state0.init.n, input.state0.init.t + ); info!("DKG: have {} peer packages for part2", input.ppkg1s.len()); let (spkg2, ppkg2s) = dkg::part2(input.spkg1.clone(), &input.ppkg1s)?; info!("DKG: dkg::part2 completed successfully"); @@ -335,22 +403,35 @@ impl Round for DkgRound2 { ) -> Result { let ppkg2s = peers .into_iter() - .filter(|(id, _)| *id != state1.state0.init.self_id) // Skip our own package + .filter(|(id, _)| *id != state1.state0.init.self_id) // Skip our own package .map(|(id, pkg)| Ok(((id as u16).try_into()?, pkg))) .collect::>()?; - Ok(DkgState2 { state1, spkg2, ppkg2s }) + Ok(DkgState2 { + state1, + spkg2, + ppkg2s, + }) } - async fn load_secret(conn: &mut SqliteConnection, account: u32) -> Result> { - sqlx::query_as::<_, (Vec,)>("SELECT spkg2 FROM dkg_state WHERE account = ? AND spkg2 IS NOT NULL") - .bind(account) - .fetch_optional(&mut *conn) - .await? - .map(|(b,)| round2::SecretPackage::from_bytes(&b)) - .transpose() + async fn load_secret( + conn: &mut SqliteConnection, + account: u32, + ) -> Result> { + sqlx::query_as::<_, (Vec,)>( + "SELECT spkg2 FROM dkg_state WHERE account = ? AND spkg2 IS NOT NULL", + ) + .bind(account) + .fetch_optional(&mut *conn) + .await? + .map(|(b,)| round2::SecretPackage::from_bytes(&b)) + .transpose() } - async fn store_secret(conn: &mut SqliteConnection, account: u32, s: &round2::SecretPackage) -> Result<()> { + async fn store_secret( + conn: &mut SqliteConnection, + account: u32, + s: &round2::SecretPackage, + ) -> Result<()> { sqlx::query( "INSERT INTO dkg_state(account, spkg2) VALUES(?1, ?2) ON CONFLICT(account) DO UPDATE SET spkg2 = excluded.spkg2", @@ -362,7 +443,12 @@ impl Round for DkgRound2 { Ok(()) } - async fn store_public(conn: &mut SqliteConnection, account: u32, from_id: u8, p: &round2::Package) -> Result<()> { + async fn store_public( + conn: &mut SqliteConnection, + account: u32, + from_id: u8, + p: &round2::Package, + ) -> Result<()> { sqlx::query( "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 2, ?2, ?3) ON CONFLICT DO NOTHING", @@ -375,7 +461,10 @@ impl Round for DkgRound2 { Ok(()) } - async fn load_publics(conn: &mut SqliteConnection, account: u32) -> Result> { + async fn load_publics( + conn: &mut SqliteConnection, + account: u32, + ) -> Result> { sqlx::query("SELECT from_id, data FROM dkg_peers WHERE account = ? AND round = 2") .bind(account) .map(|row: SqliteRow| (row.get::(0), row.get::, _>(1))) @@ -444,11 +533,7 @@ pub async fn set_dkg_address( Ok(()) } -pub async fn is_dkg_ready( - connection: &mut SqliteConnection, - account: u32, - n: u8, -) -> Result { +pub async fn is_dkg_ready(connection: &mut SqliteConnection, account: u32, n: u8) -> Result { let addresses = get_addresses(&mut *connection, account, n).await?; Ok(addresses.iter().all(|a| !a.is_empty())) } @@ -483,30 +568,51 @@ pub async fn in_dkg(connection: &mut SqliteConnection) -> Result { if n == 0 { return Ok(false); } - let (n_addresses,): (u32,) = sqlx::query_as( - "SELECT COUNT(*) FROM dkg_addresses WHERE account = ?1", - ) - .bind(account) - .fetch_one(&mut *connection) - .await?; + let (n_addresses,): (u32,) = + sqlx::query_as("SELECT COUNT(*) FROM dkg_addresses WHERE account = ?1") + .bind(account) + .fetch_one(&mut *connection) + .await?; Ok(n_addresses == n) } pub async fn cancel_dkg(connection: &mut SqliteConnection, account: u32) -> Result<()> { - sqlx::query("DELETE FROM dkg_state WHERE account = ?").bind(account).execute(&mut *connection).await?; - sqlx::query("DELETE FROM dkg_peers WHERE account = ?").bind(account).execute(&mut *connection).await?; - sqlx::query("DELETE FROM dkg_addresses WHERE account = ?").bind(account).execute(&mut *connection).await?; - sqlx::query("DELETE FROM dkg_params WHERE account = ?").bind(account).execute(&mut *connection).await?; - sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'").execute(&mut *connection).await?; + sqlx::query("DELETE FROM dkg_state WHERE account = ?") + .bind(account) + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM dkg_peers WHERE account = ?") + .bind(account) + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM dkg_addresses WHERE account = ?") + .bind(account) + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM dkg_params WHERE account = ?") + .bind(account) + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'") + .execute(&mut *connection) + .await?; delete_frost_state(&mut *connection).await } pub async fn delete_frost_state(connection: &mut SqliteConnection) -> Result<()> { info!("delete_frost_state"); - sqlx::query("DELETE FROM frost_signatures").execute(&mut *connection).await?; - sqlx::query("DELETE FROM frost_commitments").execute(&mut *connection).await?; - sqlx::query("DELETE FROM props WHERE key LIKE 'frost_%'").execute(&mut *connection).await?; - sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'").execute(&mut *connection).await?; + sqlx::query("DELETE FROM frost_signatures") + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM frost_commitments") + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM props WHERE key LIKE 'frost_%'") + .execute(&mut *connection) + .await?; + sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'") + .execute(&mut *connection) + .await?; let frost_accounts = sqlx::query_as::<_, (u32,)>( "SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1", ) @@ -550,7 +656,12 @@ pub async fn do_dkg_impl( return Ok(()); } - let DKGParams { id: self_id, n, t, birth_height } = get_dkg_params(connection, account).await?; + let DKGParams { + id: self_id, + n, + t, + birth_height, + } = get_dkg_params(connection, account).await?; let (mailbox_account, _) = get_mailbox_account(network, connection, account, self_id, birth_height).await?; @@ -569,9 +680,11 @@ pub async fn do_dkg_impl( let Some(state0) = run_round::( connection, account, - n, t, self_id, - account, // funding_account - broadcast_account, // incoming memos arrive at broadcast + n, + t, + self_id, + account, // funding_account + broadcast_account, // incoming memos arrive at broadcast init, &route_ctx, network, @@ -583,15 +696,20 @@ pub async fn do_dkg_impl( status.send(DKGStatus::WaitRound1Pkg).await; // TODO: add WaitRound0Pkg status return Ok(()); }; - info!("Round 0 complete - collected {} peer signing keys", state0.peer_verifying_keys.len()); + info!( + "Round 0 complete - collected {} peer signing keys", + state0.peer_verifying_keys.len() + ); // ── Round 1: everyone broadcasts one package to the shared address ──────── let Some(state1) = run_round::( connection, account, - n, t, self_id, - account, // funding_account - broadcast_account, // incoming memos arrive at broadcast + n, + t, + self_id, + account, // funding_account + broadcast_account, // incoming memos arrive at broadcast state0, &route_ctx, network, @@ -609,9 +727,11 @@ pub async fn do_dkg_impl( let Some(state2) = run_round::( connection, account, - n, t, self_id, - account, // funding_account - mailbox_account, // incoming memos arrive at our private mailbox + n, + t, + self_id, + account, // funding_account + mailbox_account, // incoming memos arrive at our private mailbox state1, &route_ctx, network, @@ -644,16 +764,17 @@ pub async fn do_dkg_impl( .await?; (kp, PublicKeyPackage::from_bytes(&pp_data)?) } else { - info!("DKG: calling dkg::part3 (self_id={}, n={}, t={})", self_id, n, t); + info!( + "DKG: calling dkg::part3 (self_id={}, n={}, t={})", + self_id, n, t + ); let (kp, pp) = dkg::part3(&state2.spkg2, &state2.state1.ppkg1s, &state2.ppkg2s)?; info!("DKG: dkg::part3 completed successfully"); - sqlx::query( - "UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2", - ) - .bind(kp.to_bytes()?) - .bind(account) - .execute(&mut *connection) - .await?; + sqlx::query("UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2") + .bind(kp.to_bytes()?) + .bind(account) + .execute(&mut *connection) + .await?; sqlx::query( "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 3, ?2, ?3) ON CONFLICT DO NOTHING", @@ -691,17 +812,22 @@ pub async fn do_dkg_impl( init_account_orchard(network, connection, frost_account, height).await?; store_account_orchard_vk(connection, frost_account, &shared_fvk).await?; - dkg_finalize(connection, account, frost_account, mailbox_account, broadcast_account).await?; - - // Store key material under the frost account - sqlx::query( - "UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2", + dkg_finalize( + connection, + account, + frost_account, + mailbox_account, + broadcast_account, ) - .bind(key_pkg.to_bytes()?) - .bind(frost_account) - .execute(&mut *connection) .await?; + // Store key material under the frost account + sqlx::query("UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2") + .bind(key_pkg.to_bytes()?) + .bind(frost_account) + .execute(&mut *connection) + .await?; + status.send(DKGStatus::SharedAddress(sua)).await; cancel_dkg(connection, account).await?; @@ -716,21 +842,37 @@ async fn dkg_finalize( broadcast_account: u32, ) -> Result<()> { sqlx::query("UPDATE dkg_params SET account = ?1 WHERE account = ?2") - .bind(frost_account).bind(account).execute(&mut *connection).await?; + .bind(frost_account) + .bind(account) + .execute(&mut *connection) + .await?; sqlx::query("UPDATE dkg_state SET account = ?1 WHERE account = ?2") - .bind(frost_account).bind(account).execute(&mut *connection).await?; + .bind(frost_account) + .bind(account) + .execute(&mut *connection) + .await?; sqlx::query("UPDATE dkg_peers SET account = ?1 WHERE account = ?2") - .bind(frost_account).bind(account).execute(&mut *connection).await?; + .bind(frost_account) + .bind(account) + .execute(&mut *connection) + .await?; sqlx::query("UPDATE dkg_addresses SET account = ?1 WHERE account = ?2") - .bind(frost_account).bind(account).execute(&mut *connection).await?; + .bind(frost_account) + .bind(account) + .execute(&mut *connection) + .await?; sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'") - .execute(&mut *connection).await?; + .execute(&mut *connection) + .await?; let seed = get_account_seed(&mut *connection, mailbox_account) .await? .expect("mailbox seed not found") .mnemonic; sqlx::query("UPDATE dkg_params SET seed = ?1 WHERE account = ?2") - .bind(seed).bind(frost_account).execute(&mut *connection).await?; + .bind(seed) + .bind(frost_account) + .execute(&mut *connection) + .await?; delete_account(&mut *connection, mailbox_account).await?; delete_account(&mut *connection, broadcast_account).await?; Ok(()) diff --git a/rust/src/frost/mod.rs b/rust/src/frost/mod.rs index b26e6b5ba..9c658bd92 100644 --- a/rust/src/frost/mod.rs +++ b/rust/src/frost/mod.rs @@ -4,5 +4,5 @@ pub mod sign; pub use protocol::{ run_round, to_arb_memo, Broadcast, Dispatch, FrostBytes, FrostMessage, FrostSigMessage, - Indexed, NoSend, PerPeer, PK1Map, PK2Map, Round, RouteCtx, ToCoordinator, P, + Indexed, NoSend, PK1Map, PK2Map, PerPeer, Round, RouteCtx, ToCoordinator, P, }; diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index ad9efd92e..33153f658 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -47,59 +47,107 @@ pub trait FrostBytes: Sized { // DKG types — all use the frost library's serialize/deserialize methods impl FrostBytes for round1::SecretPackage { - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for round2::SecretPackage { - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for round1::Package { - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for round2::Package { - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for KeyPackage

{ - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for PublicKeyPackage

{ - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } // SIGN types impl FrostBytes for SigningNonces

{ - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for SigningCommitments

{ - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for SigningPackage

{ - fn to_bytes(&self) -> Result> { self.serialize().map_err(|e| anyhow::anyhow!("{e}")) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + self.serialize().map_err(|e| anyhow::anyhow!("{e}")) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for SignatureShare

{ - fn to_bytes(&self) -> Result> { Ok(self.serialize()) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + Ok(self.serialize()) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize(data).map_err(|e| anyhow::anyhow!("{e}")) + } } impl FrostBytes for Randomizer { - fn to_bytes(&self) -> Result> { Ok(self.serialize().to_vec()) } - fn from_bytes(data: &[u8]) -> Result { Self::deserialize(data.try_into().map_err(|_| anyhow::anyhow!("bad randomizer length"))?).map_err(|e| anyhow::anyhow!("{e}")) } + fn to_bytes(&self) -> Result> { + Ok(self.serialize().to_vec()) + } + fn from_bytes(data: &[u8]) -> Result { + Self::deserialize( + data.try_into() + .map_err(|_| anyhow::anyhow!("bad randomizer length"))?, + ) + .map_err(|e| anyhow::anyhow!("{e}")) + } } impl> FrostBytes for Vec { @@ -123,7 +171,10 @@ pub struct Indexed { impl Indexed { pub fn new(idx: u32, value: &T) -> Result { - Ok(Self { idx, data: value.to_bytes()? }) + Ok(Self { + idx, + data: value.to_bytes()?, + }) } pub fn decode(&self) -> Result { T::from_bytes(&self.data) @@ -198,9 +249,10 @@ impl Dispatch for PerPeer

{ .into_iter() .map(|(from_id, pkg)| { let idx = from_id as usize - 1; - let addr = ctx.peer_addresses.get(idx).ok_or_else(|| { - anyhow::anyhow!("no address for participant {}", from_id) - })?; + let addr = ctx + .peer_addresses + .get(idx) + .ok_or_else(|| anyhow::anyhow!("no address for participant {}", from_id))?; Ok((addr.clone(), pkg.to_bytes()?)) }) .collect() @@ -223,8 +275,12 @@ impl> Dispatch for ToCoord } impl FrostBytes for () { - fn to_bytes(&self) -> Result> { Ok(vec![]) } - fn from_bytes(_: &[u8]) -> Result { Ok(()) } + fn to_bytes(&self) -> Result> { + Ok(vec![]) + } + fn from_bytes(_: &[u8]) -> Result { + Ok(()) + } } // ── Round ───────────────────────────────────────────────────────────────────── @@ -274,10 +330,8 @@ pub trait Round { // ── DB operations (each impl maps to concrete columns / tables) ────────── /// Load our own secret for this round, if already computed. - async fn load_secret( - conn: &mut SqliteConnection, - account: u32, - ) -> Result>; + async fn load_secret(conn: &mut SqliteConnection, account: u32) + -> Result>; /// Persist our secret for this round. async fn store_secret( @@ -364,8 +418,8 @@ pub async fn run_round( // 2. Produce our own secret + outgoing packages if not yet done if R::load_secret(conn, account).await?.is_none() { - let (secret, outgoing) = R::produce(&input) - .context(format!("Round produce failed for account {}", account))?; + let (secret, outgoing) = + R::produce(&input).context(format!("Round produce failed for account {}", account))?; let recipients_raw = outgoing.into_recipients(route_ctx)?; let mut tx = conn.begin().await?; @@ -374,13 +428,18 @@ pub async fn run_round( let recipients: Vec<(String, Vec)> = recipients_raw .into_iter() .map(|(addr, data)| { - let msg = FrostMessage { from_id: self_id, data }; + let msg = FrostMessage { + from_id: self_id, + data, + }; let bytes = msg.encode_with_prefix(&R::PREFIX)?; Ok((addr, bytes)) }) .collect::>()?; - let refs: Vec<(&str, Vec)> = - recipients.iter().map(|(a, d)| (a.as_str(), d.clone())).collect(); + let refs: Vec<(&str, Vec)> = recipients + .iter() + .map(|(a, d)| (a.as_str(), d.clone())) + .collect(); publish(network, &mut *tx, funding_account, client, height, &refs).await?; } tx.commit().await?; @@ -390,7 +449,8 @@ pub async fn run_round( let peers = R::load_publics(conn, account).await?; // Filter out our own package, then check threshold (accounting that we have our own package) let peer_count = peers.iter().filter(|(id, _)| *id != self_id).count(); - if peer_count + 1 < R::threshold(n, t) { // +1 for our own package + if peer_count + 1 < R::threshold(n, t) { + // +1 for our own package return Ok(None); } @@ -486,12 +546,15 @@ pub async fn publish( ) .await .context("plan_transaction in DKG publish")?; - let pczt = sign_transaction(connection, account, network, &pczt).await - .context("sign_transaction in DKG publish")?; - let txb = extract_transaction(&pczt).await - .context("extract_transaction in DKG publish")?; - let result = crate::pay::send(client, height, &txb).await - .context("send in DKG publish")?; + let pczt = sign_transaction(connection, account, network, &pczt) + .await + .context("sign_transaction in DKG publish")?; + let txb = extract_transaction(&pczt) + .await + .context("extract_transaction in DKG publish")?; + let result = crate::pay::send(client, height, &txb) + .await + .context("send in DKG publish")?; if hex::decode(&result).is_err() { anyhow::bail!(result); } diff --git a/rust/src/frost/sign.rs b/rust/src/frost/sign.rs index 22eb06253..2a398a68e 100644 --- a/rust/src/frost/sign.rs +++ b/rust/src/frost/sign.rs @@ -5,8 +5,8 @@ use bincode::{ config::{self, legacy}, Decode, Encode, }; -use ed25519_dalek::{Signature, SigningKey, VerifyingKey, SECRET_KEY_LENGTH}; use ed25519_dalek::Signer as Ed25519Signer; +use ed25519_dalek::{Signature, SigningKey, VerifyingKey, SECRET_KEY_LENGTH}; use frost_rerandomized::{aggregate, sign, RandomizedParams}; use halo2_proofs::pasta::Fq; use pczt::{ @@ -42,8 +42,8 @@ use crate::{ sync::SYNCING, }, frost::dkg::{ - delete_frost_state, get_coordinator_broadcast_account, get_dkg_params, - get_mailbox_account, publish, + delete_frost_state, get_coordinator_broadcast_account, get_dkg_params, get_mailbox_account, + publish, }, pay::{ plan::{get_orchard_pk, get_sapling_prover}, @@ -85,7 +85,10 @@ const SIGPACKAGE_PREFIX: &[u8] = b"SPK5"; const SIGSHARE_PREFIX: &[u8] = b"SSH3"; /// Load the ed25519 signing key from the database, if available. -async fn load_signing_key(connection: &mut SqliteConnection, account: u32) -> Result> { +async fn load_signing_key( + connection: &mut SqliteConnection, + account: u32, +) -> Result> { let result = sqlx::query_as::<_, (Vec,)>( "SELECT signing_keypair FROM dkg_state WHERE account = ? AND signing_keypair IS NOT NULL", ) @@ -95,9 +98,7 @@ async fn load_signing_key(connection: &mut SqliteConnection, account: u32) -> Re match result { Some((b,)) => { // Validation is performed before storing to DB, so we can use expect here - let arr: [u8; SECRET_KEY_LENGTH] = b - .try_into() - .expect("invalid SigningKey length"); + let arr: [u8; SECRET_KEY_LENGTH] = b.try_into().expect("invalid SigningKey length"); Ok(Some(SigningKey::from_bytes(&arr))) } None => Ok(None), @@ -120,10 +121,10 @@ async fn load_peer_verifying_key( match result { Some((b,)) => { // Validation is performed before storing to DB, so we can use expect here - let arr: [u8; 32] = b - .try_into() - .expect("invalid VerifyingKey length"); - Ok(Some(VerifyingKey::from_bytes(&arr).expect("invalid VerifyingKey"))) + let arr: [u8; 32] = b.try_into().expect("invalid VerifyingKey length"); + Ok(Some( + VerifyingKey::from_bytes(&arr).expect("invalid VerifyingKey"), + )) } None => Ok(None), } @@ -177,7 +178,10 @@ pub async fn init_sign( coordinator: u8, pczt: &PcztPackage, ) -> Result<()> { - info!("init_sign: account={}, funding_account={}, coordinator={}", account, funding_account, coordinator); + info!( + "init_sign: account={}, funding_account={}, coordinator={}", + account, funding_account, coordinator + ); let pczt = bincode::encode_to_vec(pczt, config::legacy()).unwrap(); sqlx::query("INSERT INTO props(key, value) VALUES ('frost_pczt', ?) ON CONFLICT DO NOTHING") .bind(&pczt) @@ -240,7 +244,10 @@ pub async fn do_sign_impl( let birth_height = height.saturating_sub(10000) + 1; let params = get_sign_params(&mut *connection).await?; - info!("sign: got signing params: account={}, coordinator={}", params.account, params.coordinator); + info!( + "sign: got signing params: account={}, coordinator={}", + params.account, params.coordinator + ); let account = params.account; let coordinator_address = get_coordinator_address(connection, account, params.coordinator).await?; @@ -297,7 +304,10 @@ pub async fn do_sign_impl( info!("Processing commitments for account {}", account); let commitments_vec = loop { - info!("sign: checking if we have commitments for sighash={}", hex::encode(&sighash)); + info!( + "sign: checking if we have commitments for sighash={}", + hex::encode(&sighash) + ); let commitments_vec = get_commitments(connection, account, &sighash, nsigs).await?; info!("sign: got {} commitments", commitments_vec.len()); // does the commitment table have our commitments? @@ -367,7 +377,10 @@ pub async fn do_sign_impl( // the coordinator does not need to send a message to itself, // (the commitments are already in the database) if dkg_params.id as u8 != params.coordinator { - info!("sign: sending {} commitment messages to coordinator", recipients.len()); + info!( + "sign: sending {} commitment messages to coordinator", + recipients.len() + ); status.send(SigningStatus::SendingCommitment).await; let txid = publish( network, @@ -527,7 +540,7 @@ pub async fn do_sign_impl( // ── Phase 3: Sigshares ──────────────────────────────────────────────────── let nonces = get_nonces(connection, account, &sighash).await?; - loop { + let _ = loop { // get the sigshares from the database // if we have them all, we have already signed the sigpackages and we are done let sigshares = get_sigshares(connection, account, &sighash).await?; @@ -682,13 +695,13 @@ pub async fn do_sign_impl( hex::encode(&sighash) ); for (idx, signature) in orchard_sigs.iter().enumerate() { - signer.apply_orchard_signature( - pczt_pkg.orchard_indices[idx], signature.clone()) + signer + .apply_orchard_signature(pczt_pkg.orchard_indices[idx], signature.clone()) .expect("apply_orchard_signature must succeed"); } for (idx, signature) in ironwood_sigs.iter().enumerate() { - signer.apply_ironwood_signature( - pczt_pkg.ironwood_indices[idx], signature.clone()) + signer + .apply_ironwood_signature(pczt_pkg.ironwood_indices[idx], signature.clone()) .expect("apply_ironwood_signature must succeed"); } let pczt = signer.finish(); @@ -734,7 +747,7 @@ pub async fn do_sign_impl( } fn get_sighash(pczt: Pczt) -> Vec { - use zcash_primitives::transaction::{TxVersion, sighash_v6::v6_signature_hash}; + use zcash_primitives::transaction::{sighash_v6::v6_signature_hash, TxVersion}; let tx = pczt.into_effects().unwrap(); let txid_parts = tx.digest(TxIdDigester); let shielded_sighash = match tx.version() { @@ -793,12 +806,11 @@ async fn get_keys( connection: &mut SqliteConnection, account: u32, ) -> Result<(KeyPackage

, PublicKeyPackage

)> { - let (data,) = sqlx::query_as::<_, (Vec,)>( - "SELECT key_pkg FROM dkg_state WHERE account = ?", - ) - .bind(account) - .fetch_one(&mut *connection) - .await?; + let (data,) = + sqlx::query_as::<_, (Vec,)>("SELECT key_pkg FROM dkg_state WHERE account = ?") + .bind(account) + .fetch_one(&mut *connection) + .await?; let spkg = KeyPackage::

::deserialize(&data)?; let (data,) = sqlx::query_as::<_, (Vec,)>( @@ -844,7 +856,9 @@ async fn decode_memos( for pkg in pkgs.into_iter().flatten() { // Verify signature if present - if let Some(verifying_key) = load_peer_verifying_key(connection, account, pkg.from_id).await? { + if let Some(verifying_key) = + load_peer_verifying_key(connection, account, pkg.from_id).await? + { if !verify_message(&pkg, &verifying_key) { info!( "decode_memos: rejecting message from participant {} due to invalid signature", diff --git a/rust/src/graphql-cli.rs b/rust/src/graphql-cli.rs index d7e8c379c..234483f2c 100644 --- a/rust/src/graphql-cli.rs +++ b/rust/src/graphql-cli.rs @@ -84,11 +84,16 @@ async fn main() -> Result<()> { } = config; if let Some(hex) = decode_tx { - use zcash_primitives::transaction::Transaction; use zcash_primitives::transaction::OrchardBundle; + use zcash_primitives::transaction::Transaction; use zcash_protocol::consensus::BranchId; let bytes = hex::decode(hex.trim())?; - for branch in [BranchId::Nu6_3, BranchId::Nu6_2, BranchId::Nu6, BranchId::Nu5] { + for branch in [ + BranchId::Nu6_3, + BranchId::Nu6_2, + BranchId::Nu6, + BranchId::Nu5, + ] { if let Ok(tx) = Transaction::read(&mut &bytes[..], branch) { let txid = tx.txid(); eprintln!("TXID: {}", hex::encode(txid.as_ref())); @@ -97,11 +102,16 @@ async fn main() -> Result<()> { eprintln!("Consensus branch: {:?}", tx.consensus_branch_id()); eprintln!("Transparent: {}", tx.transparent_bundle().is_some()); eprintln!("Sapling: {}", tx.sapling_bundle().is_some()); - let oa = tx.orchard_bundle().map(|b| match b { - OrchardBundle::OrchardVanilla(b) => b.actions().len(), - OrchardBundle::OrchardZSA(b) => b.actions().len(), - }).unwrap_or(0); - let iw = tx.ironwood_bundle().map(|b| (b.actions().iter().count(), b.flags().clone())); + let oa = tx + .orchard_bundle() + .map(|b| match b { + OrchardBundle::OrchardVanilla(b) => b.actions().len(), + OrchardBundle::OrchardZSA(b) => b.actions().len(), + }) + .unwrap_or(0); + let iw = tx + .ironwood_bundle() + .map(|b| (b.actions().iter().count(), b.flags().clone())); eprintln!("Orchard actions: {oa}"); if let Some((count, flags)) = iw { eprintln!("Ironwood actions: {count}, flags: {flags:?}"); @@ -196,7 +206,9 @@ async fn main() -> Result<()> { let base_ctx = context.clone(); let decoding_key = Arc::clone(&decoding_key); async move { - let auth_token = variables.get("authToken").and_then(|v| v.convert::().ok()); + let auth_token = variables + .get("authToken") + .and_then(|v| v.convert::().ok()); let ctx = match (&*decoding_key, auth_token) { (Some(key), Some(token)) => Context { diff --git a/rust/src/graphql/data.rs b/rust/src/graphql/data.rs index dc6bd34e5..0bdfcb94c 100644 --- a/rust/src/graphql/data.rs +++ b/rust/src/graphql/data.rs @@ -1,9 +1,9 @@ use std::pin::Pin; -use futures::Stream; -use juniper::{FieldResult, GraphQLEnum, GraphQLObject}; use bigdecimal::BigDecimal; use chrono::NaiveDateTime; +use futures::Stream; +use juniper::{FieldResult, GraphQLEnum, GraphQLObject}; #[derive(Clone, Debug)] pub struct Account { @@ -103,7 +103,8 @@ pub struct Event { #[derive(Clone, GraphQLEnum, Default)] pub enum EventType { - #[default] Block, + #[default] + Block, Tx, DKG, } diff --git a/rust/src/graphql/mod.rs b/rust/src/graphql/mod.rs index 137c9bb0b..108d84652 100644 --- a/rust/src/graphql/mod.rs +++ b/rust/src/graphql/mod.rs @@ -1,12 +1,15 @@ -use crate::{api::coin::Coin, graphql::query::{TxLoader, new_tx_loader}}; use crate::graphql::jwt::Claims; -use juniper::{FieldResult, FieldError}; +use crate::{ + api::coin::Coin, + graphql::query::{new_tx_loader, TxLoader}, +}; +use juniper::{FieldError, FieldResult}; -pub mod jwt; pub mod data; pub mod frost; -pub mod query; +pub mod jwt; pub mod mutation; +pub mod query; pub mod subs; #[derive(Clone)] @@ -34,12 +37,10 @@ pub fn check_auth(context: &Context, id_account: i32, check_write: bool) -> Fiel if auth.sub == 0 { return Ok(()); // has admin rights } - if auth.sub == id_account as u32 && - (!check_write || auth.write) - { + if auth.sub == id_account as u32 && (!check_write || auth.write) { return Ok(()); } - return Err(FieldError::new("Unauthorized", juniper::Value::Null)) + return Err(FieldError::new("Unauthorized", juniper::Value::Null)); } Ok(()) } @@ -47,7 +48,7 @@ pub fn check_auth(context: &Context, id_account: i32, check_write: bool) -> Fiel pub fn check_admin_auth(context: &Context) -> FieldResult<()> { if let Some(auth) = &context.auth { if auth.sub != 0 { - return Err(FieldError::new("Unauthorized", juniper::Value::Null)) + return Err(FieldError::new("Unauthorized", juniper::Value::Null)); } } Ok(()) diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index 8de2cc16b..6bde0d8de 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -1,15 +1,22 @@ use std::{collections::HashMap, sync::LazyLock}; +use crate::graphql::{check_admin_auth, check_auth}; use crate::{ - Sink, account::generate_next_dindex, api::mempool::MempoolMsg, graphql::{ - Context, data::{Addresses, Event, EventType, MigrationEvent, UnconfirmedNote}, query::{prepare_tx, zats_to_zec}, subs::SUBS - }, pay::plan::{extract_transaction, sign_transaction} + account::generate_next_dindex, + api::mempool::MempoolMsg, + graphql::{ + data::{Addresses, Event, EventType, MigrationEvent, UnconfirmedNote}, + query::{prepare_tx, zats_to_zec}, + subs::SUBS, + Context, + }, + pay::plan::{extract_transaction, sign_transaction}, + Sink, }; use bigdecimal::BigDecimal; -use juniper::{graphql_object, FieldResult, GraphQLObject, GraphQLInputObject}; +use juniper::{graphql_object, FieldResult, GraphQLInputObject, GraphQLObject}; use tokio::sync::{mpsc::Sender, Mutex}; use tokio_util::sync::CancellationToken; -use crate::graphql::{check_admin_auth, check_auth}; pub struct Mutation {} @@ -62,7 +69,6 @@ pub struct UnsignedTx { pub fee: BigDecimal, } - #[graphql_object] #[graphql( context = Context, @@ -122,7 +128,12 @@ impl Mutation { Ok(true) } - async fn synchronize(id_accounts: Vec, fast: Option, transparent_limit: Option, context: &Context) -> FieldResult { + async fn synchronize( + id_accounts: Vec, + fast: Option, + transparent_limit: Option, + context: &Context, + ) -> FieldResult { check_admin_auth(context)?; let fast = fast.unwrap_or_default(); let transparent_limit = transparent_limit @@ -144,7 +155,12 @@ impl Mutation { Ok(height as i32) } - async fn synchronize_account(id_account: i32, fast: Option, transparent_limit: Option, context: &Context) -> FieldResult { + async fn synchronize_account( + id_account: i32, + fast: Option, + transparent_limit: Option, + context: &Context, + ) -> FieldResult { check_auth(context, id_account, false)?; let fast = fast.unwrap_or_default(); let transparent_limit = transparent_limit @@ -173,7 +189,8 @@ impl Mutation { let mut client = coin.client().await?; let height = client.latest_height().await?; let network = coin.network(); - let signed_pczt = sign_transaction(&mut connection, id_account as u32, &network, &pczt).await?; + let signed_pczt = + sign_transaction(&mut connection, id_account as u32, &network, &pczt).await?; let tx_bytes = extract_transaction(&signed_pczt).await?; let txid = crate::pay::send(&mut client, height, &tx_bytes).await?; Ok(txid) @@ -195,9 +212,16 @@ impl Mutation { .parse() .map_err(|_| "Invalid amount: must be a non-negative integer")?; let coin = &context.coin; - let tx_bytes = - crate::api::issuance::issue_asset(asset_name, amount, first_issuance, finalize, None, id_account as u32, coin) - .await?; + let tx_bytes = crate::api::issuance::issue_asset( + asset_name, + amount, + first_issuance, + finalize, + None, + id_account as u32, + coin, + ) + .await?; let mut client = coin.client().await?; let height = client.latest_height().await?; let txid = crate::pay::send(&mut client, height, &tx_bytes).await?; @@ -208,22 +232,16 @@ impl Mutation { /// /// This is needed for assets discovered via blockchain scan (where the /// name is not transmitted on-chain). Also useful for renaming. - async fn set_asset_name( - id_asset: i32, - name: String, - context: &Context, - ) -> FieldResult { + async fn set_asset_name(id_asset: i32, name: String, context: &Context) -> FieldResult { check_admin_auth(context)?; let coin = &context.coin; let mut connection = coin.get_connection().await?; - let r = sqlx::query( - "UPDATE assets SET asset_name = ?1 WHERE id_asset = ?2", - ) - .bind(&name) - .bind(id_asset) - .execute(&mut *connection) - .await - .map_err(|e| format!("Failed to set asset name: {e}"))?; + let r = sqlx::query("UPDATE assets SET asset_name = ?1 WHERE id_asset = ?2") + .bind(&name) + .bind(id_asset) + .execute(&mut *connection) + .await + .map_err(|e| format!("Failed to set asset name: {e}"))?; if r.rows_affected() == 0 { return Err(format!("No asset with id_asset={id_asset}").into()); } @@ -272,7 +290,11 @@ impl Mutation { crate::graphql::frost::dkg_cancel(context).await } - pub async fn dkg_set_address(id_participant: i32, address: String, context: &Context) -> FieldResult { + pub async fn dkg_set_address( + id_participant: i32, + address: String, + context: &Context, + ) -> FieldResult { crate::graphql::frost::dkg_set_address(id_participant, address, context).await } @@ -280,22 +302,31 @@ impl Mutation { crate::graphql::frost::do_dkg(context).await } - pub async fn frost_sign(id_coordinator: i32, id_account: i32, message_account: i32, pczt: String, context: &Context) -> FieldResult { - crate::graphql::frost::frost_sign(id_coordinator, id_account, message_account, pczt, context).await + pub async fn frost_sign( + id_coordinator: i32, + id_account: i32, + message_account: i32, + pczt: String, + context: &Context, + ) -> FieldResult { + crate::graphql::frost::frost_sign( + id_coordinator, + id_account, + message_account, + pczt, + context, + ) + .await } /// Run one step of the note migration process (split non-SD → SD, then /// migrate SD to Ironwood). Idempotent — call every ~6 seconds until /// Complete. - async fn step_migration( - id_account: i32, - context: &Context, - ) -> FieldResult { + async fn step_migration(id_account: i32, context: &Context) -> FieldResult { check_auth(context, id_account, true)?; - let event = - crate::api::migrate::step_migration(&context.coin) - .await - .map_err(|e| format!("Migration error: {e}"))?; + let event = crate::api::migrate::step_migration(&context.coin) + .await + .map_err(|e| format!("Migration error: {e}"))?; Ok(match event { crate::api::migrate::MigrationEvent::SplitComplete { fee } => MigrationEvent { event: "SplitComplete".to_string(), @@ -365,7 +396,9 @@ pub async fn run_mempool(context: Context) -> anyhow::Result<()> { pool: n.pool as i32, scope: n.scope as i32, value: zats_to_zec(n.value), - diversifier: n.diversifier.as_deref() + diversifier: n + .diversifier + .as_deref() .map(hex::encode) .unwrap_or_default(), diversifier_index: n.diversifier_index.map(BigDecimal::from), diff --git a/rust/src/graphql/query.rs b/rust/src/graphql/query.rs index 21f32455c..04de606b6 100644 --- a/rust/src/graphql/query.rs +++ b/rust/src/graphql/query.rs @@ -10,17 +10,19 @@ use zcash_keys::keys::UnifiedFullViewingKey; use crate::api::coin::{Coin, Network}; use crate::api::pay::PcztPackage; use crate::db::{calculate_balance, get_sync_height}; -use crate::graphql::data::{Account, Addresses, AssetInfo, Balance, Note, Transaction, UnconfirmedTx}; +use crate::graphql::data::{ + Account, Addresses, AssetInfo, Balance, Note, Transaction, UnconfirmedTx, +}; use crate::graphql::mutation::MEMPOOL; use crate::graphql::mutation::{Output, Payment, UnsignedTx}; -use crate::graphql::{Context, check_admin_auth, check_auth}; -use crate::pay::{TxPlan, pool::ALL_POOLS}; +use crate::graphql::{check_admin_auth, check_auth, Context}; +use crate::pay::{pool::ALL_POOLS, TxPlan}; +use crate::keys::{SaplingDiversifiedAddress, ScopeExt}; use bigdecimal::num_bigint::BigInt; use bigdecimal::{BigDecimal, FromPrimitive}; use chrono::{DateTime, NaiveDateTime}; use juniper::{graphql_object, FieldError, FieldResult, GraphQLInputObject}; -use crate::keys::{SaplingDiversifiedAddress, ScopeExt}; use sqlx::{query, sqlite::SqliteRow, Row}; pub struct Query {} @@ -183,7 +185,10 @@ impl Query { Ok(addresses) } - async fn unconfirmed_by_account(id_account: i32, context: &Context) -> FieldResult> { + async fn unconfirmed_by_account( + id_account: i32, + context: &Context, + ) -> FieldResult> { check_auth(context, id_account, false)?; let mempool = MEMPOOL.lock().await; if let Some(unconfirmed_txs) = mempool.unconfirmed.get(&(id_account as u32)) { @@ -282,7 +287,8 @@ impl Query { bincode::decode_from_slice::(&pczt, bincode::config::standard())?; let network = context.coin.network(); let signed = - crate::pay::plan::sign_transaction(&mut connection, id_account as u32, &network, &pczt).await?; + crate::pay::plan::sign_transaction(&mut connection, id_account as u32, &network, &pczt) + .await?; let tx_bin = crate::pay::plan::extract_transaction(&signed).await?; let tx = hex::encode(&tx_bin); Ok(tx) @@ -358,7 +364,9 @@ pub async fn prepare_tx( let amount: u64 = if asset_base == [0u8; 32] { zec_to_zats(r.amount)? as u64 } else { - r.amount.to_string().parse::() + r.amount + .to_string() + .parse::() .map_err(|e| format!("Invalid ZSA amount: {e}"))? }; @@ -407,11 +415,10 @@ fn resolve_note( .as_ref() .ok_or_else(|| "Sapling note missing diversifier".to_string())? .clone(); - let d = sapling_crypto::keys::Diversifier( - div.clone() - .try_into() - .map_err(|_| format!("Sapling diversifier wrong length: {} bytes", div.len()))?, - ); + let d = + sapling_crypto::keys::Diversifier(div.clone().try_into().map_err(|_| { + format!("Sapling diversifier wrong length: {} bytes", div.len()) + })?); let sfvk = ufvk .sapling() .ok_or_else(|| "UFVK missing sapling key".to_string())?; @@ -429,19 +436,19 @@ fn resolve_note( .as_ref() .ok_or_else(|| "Orchard/Ironwood note missing diversifier".to_string())? .clone(); - let d = orchard::keys::Diversifier::from_bytes( - div.clone() - .try_into() - .map_err(|_| format!("Orchard diversifier wrong length: {} bytes", div.len()))?, - ); + let d = + orchard::keys::Diversifier::from_bytes(div.clone().try_into().map_err(|_| { + format!("Orchard diversifier wrong length: {} bytes", div.len()) + })?); let ofvk = ufvk .orchard() .ok_or_else(|| "UFVK missing orchard key".to_string())?; let scope = n.scope.orchard_scope(); let ivk = ofvk.to_ivk(scope); let address = ofvk.address(d, scope); - let diversifier_index: Option = - ivk.diversifier_index(&address).and_then(|d| d.try_into().ok()); + let diversifier_index: Option = ivk + .diversifier_index(&address) + .and_then(|d| d.try_into().ok()); let ua = UnifiedAddress::from_receivers(Some(address), None, None) .ok_or_else(|| "UnifiedAddress::from_receivers returned None".to_string())?; (Some(ua.encode(&network)), diversifier_index) @@ -602,11 +609,7 @@ impl Transaction { locked: r.get(7), memo: r.get(8), id_asset: id_asset.map(|v| v as u32), - asset_display: crate::account::asset_display( - id_asset, - r.get(10), - r.get(11), - ), + asset_display: crate::account::asset_display(id_asset, r.get(10), r.get(11)), } }) .fetch_all(&mut *conn) @@ -713,9 +716,7 @@ impl dataloader::BatchFn>> for TxBatcher { query("CREATE TEMP TABLE IF NOT EXISTS tmp_ids (id INTEGER PRIMARY KEY)") .execute(&mut *conn) .await?; - query("DELETE FROM tmp_ids") - .execute(&mut *conn) - .await?; + query("DELETE FROM tmp_ids").execute(&mut *conn).await?; for id in keys { query("INSERT INTO tmp_ids(id) VALUES (?1)") .bind(*id) diff --git a/rust/src/graphql/subs.rs b/rust/src/graphql/subs.rs index e1a08823c..23ee7c561 100644 --- a/rust/src/graphql/subs.rs +++ b/rust/src/graphql/subs.rs @@ -7,7 +7,7 @@ use tokio_stream::wrappers::ReceiverStream; use crate::graphql::{ data::{Event, EventStream}, - {Context, check_auth}, + {check_auth, Context}, }; pub struct Subscription {} diff --git a/rust/src/io.rs b/rust/src/io.rs index 751fd7f93..099ab94fc 100644 --- a/rust/src/io.rs +++ b/rust/src/io.rs @@ -408,17 +408,15 @@ pub async fn export_account(connection: &mut SqliteConnection, account: u32) -> io_account.transactions = transactions; // Export user memos - let user_memos = sqlx::query( - "SELECT id_tx, user_memo FROM user_memos WHERE account = ?", - ) - .bind(account) - .map(|row: SqliteRow| { - let id_tx: u32 = row.get(0); - let user_memo: String = row.get(1); - IOUserMemo { id_tx, user_memo } - }) - .fetch_all(&mut *connection) - .await?; + let user_memos = sqlx::query("SELECT id_tx, user_memo FROM user_memos WHERE account = ?") + .bind(account) + .map(|row: SqliteRow| { + let id_tx: u32 = row.get(0); + let user_memo: String = row.get(1); + IOUserMemo { id_tx, user_memo } + }) + .fetch_all(&mut *connection) + .await?; io_account.user_memos = user_memos; let dkg_params = @@ -521,13 +519,12 @@ pub async fn import_account(connection: &mut SqliteConnection, data: &[u8]) -> R .execute(&mut *tx) .await?; // Look up the id_asset (either newly created or existing) - let new_id_asset: (u32,) = sqlx::query_as( - "SELECT id_asset FROM assets WHERE asset_desc_hash = ?1 AND ik = ?2", - ) - .bind(&asset.asset_desc_hash) - .bind(&asset.ik) - .fetch_one(&mut *tx) - .await?; + let new_id_asset: (u32,) = + sqlx::query_as("SELECT id_asset FROM assets WHERE asset_desc_hash = ?1 AND ik = ?2") + .bind(&asset.asset_desc_hash) + .bind(&asset.ik) + .fetch_one(&mut *tx) + .await?; new_assets.insert(asset.id_asset, new_id_asset.0); } @@ -672,9 +669,7 @@ pub async fn import_account(connection: &mut SqliteConnection, data: &[u8]) -> R let new_taddress = note .taddress .and_then(|id_taddress| new_taddresses.get(&id_taddress)); - let new_id_asset = note - .id_asset - .and_then(|id_asset| new_assets.get(&id_asset)); + let new_id_asset = note.id_asset.and_then(|id_asset| new_assets.get(&id_asset)); let r = sqlx::query("INSERT INTO notes (tx, height, account, pool, scope, nullifier, value, cmx, taddress, position, diversifier, rcm, rho, locked, id_asset) diff --git a/rust/src/keys.rs b/rust/src/keys.rs index 436a9a4d3..6287a4987 100644 --- a/rust/src/keys.rs +++ b/rust/src/keys.rs @@ -254,10 +254,7 @@ pub fn sapling_ivk_nk_for_scope( sapling_crypto::keys::NullifierDerivingKey, ) { if scope.is_external() { - ( - vk.fvk().vk.ivk(), - vk.to_nk(zip32::Scope::External), - ) + (vk.fvk().vk.ivk(), vk.to_nk(zip32::Scope::External)) } else { ( vk.to_internal_fvk().vk.ivk(), diff --git a/rust/src/ledger/builder.rs b/rust/src/ledger/builder.rs index 93bd51704..56ef9c37d 100644 --- a/rust/src/ledger/builder.rs +++ b/rust/src/ledger/builder.rs @@ -5,8 +5,8 @@ use byteorder::{WriteBytesExt, LE}; use jubjub::Fr; use pczt::{ roles::{ - io_finalizer::IoFinalizer, prover::Prover, - spend_finalizer::SpendFinalizer, updater::Updater, + io_finalizer::IoFinalizer, prover::Prover, spend_finalizer::SpendFinalizer, + updater::Updater, }, Pczt, }; @@ -24,15 +24,17 @@ use secp256k1::PublicKey; use sqlx::{pool::PoolConnection, Sqlite, SqliteConnection}; use tracing::info; use zcash_keys::encoding::AddressCodec; -use zcash_note_encryption::{try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, OutgoingCipherKey}; -use zcash_script::script::Evaluable; -use zcash_transparent::address::TransparentAddress; +use zcash_note_encryption::{ + try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, OutgoingCipherKey, +}; use zcash_proofs::prover::LocalTxProver; use zcash_protocol::{consensus::NetworkConstants, memo::Memo}; +use zcash_script::script::Evaluable; +use zcash_transparent::address::TransparentAddress; use crate::{ - api::pay::{PcztPackage, SigningEvent}, api::coin::Network, + api::pay::{PcztPackage, SigningEvent}, db::get_account_aindex, ledger::{ hashers::{ @@ -202,7 +204,7 @@ pub async fn sign_transaction( let memo_bytes = memo.encode(); let memo: [u8; 512] = tiu!(*memo_bytes.as_array()); memo - }, + } }; let memo_type = memo[0]; memos.push(memo); @@ -363,12 +365,10 @@ pub async fn sign_transaction( u.update_spend_with(i, |mut su_updater| { let rcv = ValueCommitTrapdoor::from_bytes(su.rcv).unwrap(); let alpha = jubjub::Fr::from_bytes(&su.alpha).unwrap(); - let cv = ValueCommitment::derive( - NoteValue::from_raw(su.value), - rcv, - ); + let cv = ValueCommitment::derive(NoteValue::from_raw(su.value), rcv); let pk: VerificationKeyBytes = su.ak.into(); - let pk: VerificationKey = pk.try_into().expect("valid ak from Ledger"); + let pk: VerificationKey = + pk.try_into().expect("valid ak from Ledger"); let rk = pk.randomize(&alpha); // Re-derive rcv since ValueCommitment::derive consumed it let rcv2 = ValueCommitTrapdoor::from_bytes(su.rcv).unwrap(); @@ -378,7 +378,8 @@ pub async fn sign_transaction( su_updater.set_alpha(alpha); su_updater.set_rseed(su.rseed); Ok(()) - }).unwrap(); + }) + .unwrap(); } for (i, ou) in output_updates.iter().enumerate() { u.update_output_with(i, |mut ou_updater| { @@ -387,11 +388,8 @@ pub async fn sign_transaction( let cv = ValueCommitment::derive(value_note, rcv); let rcv2 = ValueCommitTrapdoor::from_bytes(ou.rcv).unwrap(); let recipient = PaymentAddress::from_bytes(&ou.recipient_bytes).unwrap(); - let note = Note::from_parts( - recipient, - value_note, - Rseed::AfterZip212(ou.rseed), - ); + let note = + Note::from_parts(recipient, value_note, Rseed::AfterZip212(ou.rseed)); let cmu = note.cmu(); let epk = EphemeralKeyBytes(ou.epk_bytes); let ock = OutgoingCipherKey(ou.ock_bytes); @@ -404,7 +402,8 @@ pub async fn sign_transaction( ou_updater.set_rseed(ou.rseed); ou_updater.set_ock(ock); Ok(()) - }).unwrap(); + }) + .unwrap(); } Ok(()) }) @@ -490,7 +489,9 @@ pub async fn sign_transaction( data.write_all(sin.nullifier().as_ref()).unwrap(); let rk_bytes: [u8; 32] = VerificationKeyBytes::from(*sin.rk()).into(); data.write_all(&rk_bytes).unwrap(); - let zkp = sin.zkproof().expect("spend must have zkproof after proving"); + let zkp = sin + .zkproof() + .expect("spend must have zkproof after proving"); data.write_all(zkp.as_ref()).unwrap(); assert_eq!(data.len(), 320); proof_bufs.push(data); @@ -502,7 +503,9 @@ pub async fn sign_transaction( data.write_all(sout.ephemeral_key().as_ref()).unwrap(); data.write_all(sout.enc_ciphertext()).unwrap(); data.write_all(sout.out_ciphertext()).unwrap(); - let zkp = sout.zkproof().expect("output must have zkproof after proving"); + let zkp = sout + .zkproof() + .expect("output must have zkproof after proving"); data.write_all(zkp.as_ref()).unwrap(); assert_eq!(data.len(), 948); proof_bufs.push(data); @@ -610,7 +613,9 @@ pub async fn sign_transaction( let mut signer = pczt::roles::signer::Signer::new(pczt).unwrap(); for (index, signature) in tsigs.iter().enumerate() { - signer.append_transparent_signature(index, *signature).unwrap(); + signer + .append_transparent_signature(index, *signature) + .unwrap(); } for (index, signature) in ssigs.iter().enumerate() { signer.apply_sapling_signature(index, *signature).unwrap(); diff --git a/rust/src/ledger/fvk.rs b/rust/src/ledger/fvk.rs index af98fbaa7..990e96ee4 100644 --- a/rust/src/ledger/fvk.rs +++ b/rust/src/ledger/fvk.rs @@ -9,7 +9,14 @@ use zcash_protocol::consensus::NetworkConstants; use zcash_transparent::address::TransparentAddress; use crate::{ - IntoAnyhow, account::get_sapling_address, api::coin::Network, db::{get_account_aindex, get_account_dindex}, ledger::{LedgerError, LedgerResult, transport::{APDUCommand, Device, connect_ledger}}, tiu + account::get_sapling_address, + api::coin::Network, + db::{get_account_aindex, get_account_dindex}, + ledger::{ + transport::{connect_ledger, APDUCommand, Device}, + LedgerError, LedgerResult, + }, + tiu, IntoAnyhow, }; pub async fn get_fvk(ledger: &D, aindex: u32) -> LedgerResult { @@ -143,7 +150,11 @@ pub async fn get_hw_transparent_address( Ok((pk.to_vec(), taddress)) } -pub async fn show_sapling_address(network: &Network, connection: &mut SqliteConnection, account: u32) -> LedgerResult { +pub async fn show_sapling_address( + network: &Network, + connection: &mut SqliteConnection, + account: u32, +) -> LedgerResult { let ledger = connect_ledger().await?; let aindex = get_account_aindex(connection, account).await? | 0x80000000u32; // We SHOULD be using the diversifier index and ask the device @@ -193,7 +204,11 @@ pub async fn show_sapling_address(network: &Network, connection: &mut SqliteConn Ok(address.encode(network)) } -pub async fn show_transparent_address(network: &Network, connection: &mut SqliteConnection, account: u32) -> LedgerResult { +pub async fn show_transparent_address( + network: &Network, + connection: &mut SqliteConnection, + account: u32, +) -> LedgerResult { let ledger = connect_ledger().await?; let aindex = get_account_aindex(connection, account).await?; let dindex = get_account_dindex(connection, account).await?; @@ -227,7 +242,10 @@ mod tests { use zcash_keys::encoding::AddressCodec; use zcash_protocol::consensus::MainNetwork; - use crate::{ledger::transport::{APDUCommand, Device, LEDGER_ZEMU}, tiu}; + use crate::{ + ledger::transport::{APDUCommand, Device, LEDGER_ZEMU}, + tiu, + }; use std::io::Write; #[tokio::test] @@ -278,7 +296,10 @@ mod tests { let address: [u8; 43] = tiu!(res.data[0..43]); let address = PaymentAddress::from_bytes(&address).unwrap(); let address = address.encode(&MainNetwork); - assert_eq!(address, "zs157m24pkqcq09edxz9p0p653xcsfpdpcspcad5wkkp3pq29hvc7h2uvs7wncakwqtl6jqkxn939p"); + assert_eq!( + address, + "zs157m24pkqcq09edxz9p0p653xcsfpdpcspcad5wkkp3pq29hvc7h2uvs7wncakwqtl6jqkxn939p" + ); Ok(()) } } diff --git a/rust/src/ledger/mock.rs b/rust/src/ledger/mock.rs index b0e3ec525..ab9ed240b 100644 --- a/rust/src/ledger/mock.rs +++ b/rust/src/ledger/mock.rs @@ -4,15 +4,18 @@ use sqlx::SqliteConnection; use tonic::async_trait; use zcash_transparent::address::TransparentAddress; -use crate::{api::{coin::{Coin, Network}, pay::{PcztPackage, SigningEvent}}, frb_generated::StreamSink, ledger::HWAPI}; +use crate::{ + api::{ + coin::{Coin, Network}, + pay::{PcztPackage, SigningEvent}, + }, + frb_generated::StreamSink, + ledger::HWAPI, +}; #[async_trait] impl HWAPI for () { - async fn get_hw_fvk( - &self, - _network: &Network, - _aindex: u32, - ) -> Result { + async fn get_hw_fvk(&self, _network: &Network, _aindex: u32) -> Result { unimplemented!() } async fn get_hw_sapling_address(&self, _network: &Network, _aindex: u32) -> Result { @@ -60,4 +63,3 @@ impl HWAPI for () { unimplemented!() } } - diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index ab19087ff..fd84641b9 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -15,11 +15,7 @@ pub type LedgerResult = std::result::Result; #[async_trait] pub trait HWAPI { - async fn get_hw_fvk( - &self, - network: &Network, - aindex: u32, - ) -> Result; + async fn get_hw_fvk(&self, network: &Network, aindex: u32) -> Result; async fn get_hw_sapling_address(&self, network: &Network, aindex: u32) -> Result; async fn get_hw_transparent_address( &self, @@ -69,4 +65,3 @@ cfg_if::cfg_if! { mod tests; } } - diff --git a/rust/src/ledger/nano.rs b/rust/src/ledger/nano.rs index 397535001..54ea42b93 100644 --- a/rust/src/ledger/nano.rs +++ b/rust/src/ledger/nano.rs @@ -4,7 +4,14 @@ use sqlx::SqliteConnection; use tonic::async_trait; use zcash_transparent::address::TransparentAddress; -use crate::{api::{coin::{Coin, Network}, pay::{PcztPackage, SigningEvent}}, frb_generated::StreamSink, ledger::HWAPI}; +use crate::{ + api::{ + coin::{Coin, Network}, + pay::{PcztPackage, SigningEvent}, + }, + frb_generated::StreamSink, + ledger::HWAPI, +}; pub struct NanoLedger {} diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index ad6ce5aa3..64b9c0593 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -9,9 +9,9 @@ use pczt::{ }; use secp256k1::{ecdsa::Signature, PublicKey}; use sqlx::{Acquire, SqlitePool}; -use zcash_script::script::Evaluable; use std::{fs::File, io::BufReader}; use zcash_keys::encoding::AddressCodec as _; +use zcash_script::script::Evaluable; use zcash_transparent::address::TransparentAddress; use sapling_crypto::{keys::FullViewingKey, Diversifier, PaymentAddress}; @@ -19,13 +19,15 @@ use zcash_address::unified::{self, Encoding, Ufvk}; use zcash_protocol::consensus::MainNetwork; use crate::{ - IntoAnyhow as _, api::{coin::Network, pay::PcztPackage}, ledger::{ + api::{coin::Network, pay::PcztPackage}, + ledger::{ hashers::{ create_hasher, header_hasher, orchard_hasher, output_hasher, prevout_hasher, sequence_hasher, spend_hasher, transparent_hasher, zoutput_hasher, }, transport::{APDUCommand, Device, LEDGER_ZEMU}, - } + }, + IntoAnyhow as _, }; use super::*; diff --git a/rust/src/ledger/transport.rs b/rust/src/ledger/transport.rs index 5c8fb2e93..af7c34dca 100644 --- a/rust/src/ledger/transport.rs +++ b/rust/src/ledger/transport.rs @@ -1,11 +1,17 @@ -use std::sync::LazyLock; -use std::io::Write; use byteorder::{WriteBytesExt, BE}; use hidapi::{HidApi, HidDevice}; -use tokio::{runtime::Builder, sync::{Mutex, mpsc, oneshot}}; +use std::io::Write; +use std::sync::LazyLock; +use tokio::{ + runtime::Builder, + sync::{mpsc, oneshot, Mutex}, +}; use tonic::async_trait; -use crate::{IntoAnyhow, ledger::{LedgerError, LedgerResult}}; +use crate::{ + ledger::{LedgerError, LedgerResult}, + IntoAnyhow, +}; pub fn open_ledger(api: &HidApi) -> LedgerResult { for devinfo in api.device_list() { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 297fb7061..46c224bd6 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -13,7 +13,7 @@ pub mod bip38; pub mod budget; pub mod contacts; pub mod db; -#[cfg(feature="flutter")] +#[cfg(feature = "flutter")] mod frb_generated; pub mod frost; #[cfg(feature = "graphql")] @@ -25,15 +25,15 @@ pub mod ledger; pub mod lwd; pub mod memo; pub mod mempool; -pub mod openalias; -pub mod net; pub mod migrate; +pub mod net; +pub mod openalias; pub mod pay; pub mod plugin; pub mod recover; pub mod sync; -pub mod warp; pub mod vault; +pub mod warp; pub type Hash32 = [u8; 32]; pub type GRPCClient = CompactTxStreamerClient; @@ -69,7 +69,7 @@ pub trait Sink: Clone { fn send_error(&self, e: Error) -> impl std::future::Future + Send; } -#[cfg(feature="flutter")] +#[cfg(feature = "flutter")] impl Sink for StreamSink { async fn send(&self, value: T) { let _ = self.add(value); diff --git a/rust/src/lwd.rs b/rust/src/lwd.rs index 62d81756c..04211fb90 100644 --- a/rust/src/lwd.rs +++ b/rust/src/lwd.rs @@ -355,10 +355,10 @@ pub mod compact_tx_streamer_client { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] - use tonic::codegen::*; use tonic::codegen::http::Uri; + use tonic::codegen::*; #[derive(Debug, Clone)] pub struct CompactTxStreamerClient { inner: tonic::client::Grpc, @@ -402,9 +402,8 @@ pub mod compact_tx_streamer_client { >::ResponseBody, >, >, - , - >>::Error: Into + std::marker::Send + std::marker::Sync, + >>::Error: + Into + std::marker::Send + std::marker::Sync, { CompactTxStreamerClient::new(InterceptedService::new(inner, interceptor)) } @@ -444,26 +443,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetLatestBlock", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetLatestBlock", + )); self.inner.unary(req, path, codec).await } /// Return the compact block corresponding to the given block identifier @@ -471,26 +462,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetBlock", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlock", + )); self.inner.unary(req, path, codec).await } /// Return a list of consecutive compact blocks @@ -501,26 +484,18 @@ pub mod compact_tx_streamer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetBlockRange", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetBlockRange", + )); self.inner.server_streaming(req, path, codec).await } /// Return the requested full (not compact) transaction (as from zcashd) @@ -528,26 +503,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetTransaction", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTransaction", + )); self.inner.unary(req, path, codec).await } /// Submit the given transaction to the Zcash network @@ -555,26 +522,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "SendTransaction", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "SendTransaction", + )); self.inner.unary(req, path, codec).await } /// Return the txids corresponding to the given t-address within the given block range @@ -585,78 +544,54 @@ pub mod compact_tx_streamer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetTaddressTxids", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressTxids", + )); self.inner.server_streaming(req, path, codec).await } pub async fn get_taddress_balance( &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetTaddressBalance", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressBalance", + )); self.inner.unary(req, path, codec).await } pub async fn get_taddress_balance_stream( &mut self, request: impl tonic::IntoStreamingRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream", ); let mut req = request.into_streaming_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetTaddressBalanceStream", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTaddressBalanceStream", + )); self.inner.client_streaming(req, path, codec).await } /// Return the compact transactions currently in the mempool; the results @@ -675,26 +610,18 @@ pub mod compact_tx_streamer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetMempoolTx", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetMempoolTx", + )); self.inner.server_streaming(req, path, codec).await } /// Return a stream of current Mempool transactions. This will keep the output stream open while @@ -706,26 +633,18 @@ pub mod compact_tx_streamer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetMempoolStream", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetMempoolStream", + )); self.inner.server_streaming(req, path, codec).await } /// GetTreeState returns the note commitment tree state corresponding to the given block. @@ -736,55 +655,37 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetTreeState", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetTreeState", + )); self.inner.unary(req, path, codec).await } pub async fn get_address_utxos( &mut self, request: impl tonic::IntoRequest, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetAddressUtxos", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetAddressUtxos", + )); self.inner.unary(req, path, codec).await } pub async fn get_address_utxos_stream( @@ -794,26 +695,18 @@ pub mod compact_tx_streamer_client { tonic::Response>, tonic::Status, > { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetAddressUtxosStream", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetAddressUtxosStream", + )); self.inner.server_streaming(req, path, codec).await } /// Return information about this lightwalletd instance and the blockchain @@ -821,26 +714,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new( - "cash.z.wallet.sdk.rpc.CompactTxStreamer", - "GetLightdInfo", - ), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "GetLightdInfo", + )); self.inner.unary(req, path, codec).await } /// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) @@ -848,23 +733,18 @@ pub mod compact_tx_streamer_client { &mut self, request: impl tonic::IntoRequest, ) -> std::result::Result, tonic::Status> { - self.inner - .ready() - .await - .map_err(|e| { - tonic::Status::unknown( - format!("Service was not ready: {}", e.into()), - ) - })?; + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; let codec = tonic_prost::ProstCodec::default(); let path = http::uri::PathAndQuery::from_static( "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping", ); let mut req = request.into_request(); - req.extensions_mut() - .insert( - GrpcMethod::new("cash.z.wallet.sdk.rpc.CompactTxStreamer", "Ping"), - ); + req.extensions_mut().insert(GrpcMethod::new( + "cash.z.wallet.sdk.rpc.CompactTxStreamer", + "Ping", + )); self.inner.unary(req, path, codec).await } } @@ -876,7 +756,7 @@ pub mod compact_tx_streamer_server { dead_code, missing_docs, clippy::wildcard_imports, - clippy::let_unit_value, + clippy::let_unit_value )] use tonic::codegen::*; /// Generated trait containing gRPC methods that should be implemented for use with CompactTxStreamerServer. @@ -895,17 +775,13 @@ pub mod compact_tx_streamer_server { /// Server streaming response type for the GetBlockRange method. type GetBlockRangeStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Return a list of consecutive compact blocks async fn get_block_range( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Return the requested full (not compact) transaction (as from zcashd) async fn get_transaction( &self, @@ -919,17 +795,13 @@ pub mod compact_tx_streamer_server { /// Server streaming response type for the GetTaddressTxids method. type GetTaddressTxidsStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Return the txids corresponding to the given t-address within the given block range async fn get_taddress_txids( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; async fn get_taddress_balance( &self, request: tonic::Request, @@ -941,8 +813,7 @@ pub mod compact_tx_streamer_server { /// Server streaming response type for the GetMempoolTx method. type GetMempoolTxStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Return the compact transactions currently in the mempool; the results /// can be a few seconds out of date. If the Exclude list is empty, return @@ -956,25 +827,18 @@ pub mod compact_tx_streamer_server { async fn get_mempool_tx( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the GetMempoolStream method. type GetMempoolStreamStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; /// Return a stream of current Mempool transactions. This will keep the output stream open while /// there are mempool transactions. It will close the returned stream when a new block is mined. async fn get_mempool_stream( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// GetTreeState returns the note commitment tree state corresponding to the given block. /// See section 3.7 of the Zcash protocol specification. It returns several other useful /// values also (even though they can be obtained using GetBlock). @@ -986,23 +850,16 @@ pub mod compact_tx_streamer_server { async fn get_address_utxos( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Server streaming response type for the GetAddressUtxosStream method. type GetAddressUtxosStreamStream: tonic::codegen::tokio_stream::Stream< Item = std::result::Result, - > - + std::marker::Send + > + std::marker::Send + 'static; async fn get_address_utxos_stream( &self, request: tonic::Request, - ) -> std::result::Result< - tonic::Response, - tonic::Status, - >; + ) -> std::result::Result, tonic::Status>; /// Return information about this lightwalletd instance and the blockchain async fn get_lightd_info( &self, @@ -1035,10 +892,7 @@ pub mod compact_tx_streamer_server { max_encoding_message_size: None, } } - pub fn with_interceptor( - inner: T, - interceptor: F, - ) -> InterceptedService + pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService where F: tonic::service::Interceptor, { @@ -1093,23 +947,16 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock" => { #[allow(non_camel_case_types)] struct GetLatestBlockSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for GetLatestBlockSvc { + impl tonic::server::UnaryService for GetLatestBlockSvc { type Response = super::BlockId; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_latest_block(&inner, request) - .await + ::get_latest_block(&inner, request).await }; Box::pin(fut) } @@ -1139,14 +986,9 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock" => { #[allow(non_camel_case_types)] struct GetBlockSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService for GetBlockSvc { + impl tonic::server::UnaryService for GetBlockSvc { type Response = super::CompactBlock; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -1183,24 +1025,21 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange" => { #[allow(non_camel_case_types)] struct GetBlockRangeSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ServerStreamingService - for GetBlockRangeSvc { + impl + tonic::server::ServerStreamingService + for GetBlockRangeSvc + { type Response = super::CompactBlock; type ResponseStream = T::GetBlockRangeStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_block_range(&inner, request) - .await + ::get_block_range(&inner, request).await }; Box::pin(fut) } @@ -1230,23 +1069,16 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction" => { #[allow(non_camel_case_types)] struct GetTransactionSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for GetTransactionSvc { + impl tonic::server::UnaryService for GetTransactionSvc { type Response = super::RawTransaction; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_transaction(&inner, request) - .await + ::get_transaction(&inner, request).await }; Box::pin(fut) } @@ -1276,23 +1108,18 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction" => { #[allow(non_camel_case_types)] struct SendTransactionSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for SendTransactionSvc { + impl tonic::server::UnaryService + for SendTransactionSvc + { type Response = super::SendResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::send_transaction(&inner, request) - .await + ::send_transaction(&inner, request).await }; Box::pin(fut) } @@ -1322,28 +1149,21 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids" => { #[allow(non_camel_case_types)] struct GetTaddressTxidsSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ServerStreamingService< - super::TransparentAddressBlockFilter, - > for GetTaddressTxidsSvc { + impl + tonic::server::ServerStreamingService + for GetTaddressTxidsSvc + { type Response = super::RawTransaction; type ResponseStream = T::GetTaddressTxidsStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_taddress_txids( - &inner, - request, - ) - .await + ::get_taddress_txids(&inner, request).await }; Box::pin(fut) } @@ -1373,25 +1193,18 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance" => { #[allow(non_camel_case_types)] struct GetTaddressBalanceSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for GetTaddressBalanceSvc { + impl tonic::server::UnaryService + for GetTaddressBalanceSvc + { type Response = super::Balance; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_taddress_balance( - &inner, - request, - ) + ::get_taddress_balance(&inner, request) .await }; Box::pin(fut) @@ -1422,15 +1235,11 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream" => { #[allow(non_camel_case_types)] struct GetTaddressBalanceStreamSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ClientStreamingService - for GetTaddressBalanceStreamSvc { + impl tonic::server::ClientStreamingService + for GetTaddressBalanceStreamSvc + { type Response = super::Balance; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request>, @@ -1438,10 +1247,9 @@ pub mod compact_tx_streamer_server { let inner = Arc::clone(&self.0); let fut = async move { ::get_taddress_balance_stream( - &inner, - request, - ) - .await + &inner, request, + ) + .await }; Box::pin(fut) } @@ -1471,24 +1279,20 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx" => { #[allow(non_camel_case_types)] struct GetMempoolTxSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ServerStreamingService - for GetMempoolTxSvc { + impl tonic::server::ServerStreamingService + for GetMempoolTxSvc + { type Response = super::CompactTx; type ResponseStream = T::GetMempoolTxStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_mempool_tx(&inner, request) - .await + ::get_mempool_tx(&inner, request).await }; Box::pin(fut) } @@ -1518,27 +1322,17 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream" => { #[allow(non_camel_case_types)] struct GetMempoolStreamSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ServerStreamingService - for GetMempoolStreamSvc { + impl tonic::server::ServerStreamingService + for GetMempoolStreamSvc + { type Response = super::RawTransaction; type ResponseStream = T::GetMempoolStreamStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { + type Future = + BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_mempool_stream( - &inner, - request, - ) - .await + ::get_mempool_stream(&inner, request).await }; Box::pin(fut) } @@ -1568,23 +1362,16 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState" => { #[allow(non_camel_case_types)] struct GetTreeStateSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for GetTreeStateSvc { + impl tonic::server::UnaryService for GetTreeStateSvc { type Response = super::TreeState; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_tree_state(&inner, request) - .await + ::get_tree_state(&inner, request).await }; Box::pin(fut) } @@ -1614,23 +1401,19 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos" => { #[allow(non_camel_case_types)] struct GetAddressUtxosSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService - for GetAddressUtxosSvc { + impl + tonic::server::UnaryService + for GetAddressUtxosSvc + { type Response = super::GetAddressUtxosReplyList; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_address_utxos(&inner, request) - .await + ::get_address_utxos(&inner, request).await }; Box::pin(fut) } @@ -1660,26 +1443,21 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream" => { #[allow(non_camel_case_types)] struct GetAddressUtxosStreamSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::ServerStreamingService - for GetAddressUtxosStreamSvc { + impl + tonic::server::ServerStreamingService + for GetAddressUtxosStreamSvc + { type Response = super::GetAddressUtxosReply; type ResponseStream = T::GetAddressUtxosStreamStream; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = + BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, ) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_address_utxos_stream( - &inner, - request, - ) + ::get_address_utxos_stream(&inner, request) .await }; Box::pin(fut) @@ -1710,21 +1488,13 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo" => { #[allow(non_camel_case_types)] struct GetLightdInfoSvc(pub Arc); - impl tonic::server::UnaryService - for GetLightdInfoSvc { + impl tonic::server::UnaryService for GetLightdInfoSvc { type Response = super::LightdInfo; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; - fn call( - &mut self, - request: tonic::Request, - ) -> Self::Future { + type Future = BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request) -> Self::Future { let inner = Arc::clone(&self.0); let fut = async move { - ::get_lightd_info(&inner, request) - .await + ::get_lightd_info(&inner, request).await }; Box::pin(fut) } @@ -1754,14 +1524,9 @@ pub mod compact_tx_streamer_server { "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping" => { #[allow(non_camel_case_types)] struct PingSvc(pub Arc); - impl< - T: CompactTxStreamer, - > tonic::server::UnaryService for PingSvc { + impl tonic::server::UnaryService for PingSvc { type Response = super::PingResponse; - type Future = BoxFuture< - tonic::Response, - tonic::Status, - >; + type Future = BoxFuture, tonic::Status>; fn call( &mut self, request: tonic::Request, @@ -1795,25 +1560,19 @@ pub mod compact_tx_streamer_server { }; Box::pin(fut) } - _ => { - Box::pin(async move { - let mut response = http::Response::new( - tonic::body::Body::default(), - ); - let headers = response.headers_mut(); - headers - .insert( - tonic::Status::GRPC_STATUS, - (tonic::Code::Unimplemented as i32).into(), - ); - headers - .insert( - http::header::CONTENT_TYPE, - tonic::metadata::GRPC_CONTENT_TYPE, - ); - Ok(response) - }) - } + _ => Box::pin(async move { + let mut response = http::Response::new(tonic::body::Body::default()); + let headers = response.headers_mut(); + headers.insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers.insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }), } } } diff --git a/rust/src/memo.rs b/rust/src/memo.rs index ad54c1970..7f67fd68b 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -1,18 +1,24 @@ use anyhow::{Context as _, Result}; -use orchard::{keys::Scope, note::ExtractedNoteCommitment, note_encryption::{IronwoodDomain, OrchardDomain}, zsa::OrchardZSADomain}; -use zcash_note_encryption::note_bytes::NoteBytesData; +use orchard::{ + keys::Scope, + note::ExtractedNoteCommitment, + note_encryption::{IronwoodDomain, OrchardDomain}, + zsa::OrchardZSADomain, +}; use sapling_crypto::{keys::PreparedIncomingViewingKey, note_encryption::SaplingDomain}; use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use tracing::debug; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec}; +use zcash_note_encryption::note_bytes::NoteBytesData; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; -use zcash_primitives::transaction::{ - components::sapling::zip212_enforcement, OrchardBundle, -}; +use zcash_primitives::transaction::{components::sapling::zip212_enforcement, OrchardBundle}; use zcash_protocol::memo::Memo; use crate::{ - account::{get_orchard_vk, get_sapling_vk}, api::coin::Network, pay::fee::FeeManager, Client + account::{get_orchard_vk, get_sapling_vk}, + api::coin::Network, + pay::fee::FeeManager, + Client, }; pub async fn fetch_tx_details( @@ -51,7 +57,10 @@ pub async fn fetch_tx_details( Ok(()) } -async fn summarize_tx(connection: &mut SqliteConnection, tx: u32) -> Result<(u8, i64, Option, i64)> { +async fn summarize_tx( + connection: &mut SqliteConnection, + tx: u32, +) -> Result<(u8, i64, Option, i64)> { let (value, fee) = sqlx::query( "WITH n AS (SELECT value, tx FROM notes WHERE id_asset IS NULL UNION ALL @@ -114,15 +123,13 @@ async fn summarize_tx(connection: &mut SqliteConnection, tx: u32) -> Result<(u8, /// Try ZSA decryption using the raw 612-byte enc_ciphertext with OrchardZSADomain. /// Called when vanilla OrchardDomain decryption fails and raw ZSA ciphertext is available. fn try_zsa_decrypt( - action: &orchard::Action<::SpendAuth>, + action: &orchard::Action< + ::SpendAuth, + >, raw_enc: &[u8], pivk: &orchard::keys::PreparedIncomingViewingKey, ovk: &orchard::keys::OutgoingViewingKey, -) -> Option<( - orchard::Note, - orchard::Address, - [u8; 512], -)> { +) -> Option<(orchard::Note, orchard::Address, [u8; 512])> { use orchard::note::TransmittedNoteCiphertext; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; @@ -148,10 +155,11 @@ fn try_zsa_decrypt( ) .ok()?; - let zsa_domain = OrchardZSADomain { rho: zsa_action.rho() }; + let zsa_domain = OrchardZSADomain { + rho: zsa_action.rho(), + }; - if let Some((note, _address, memo_bytes)) = - try_note_decryption(&zsa_domain, pivk, &zsa_action) + if let Some((note, _address, memo_bytes)) = try_note_decryption(&zsa_domain, pivk, &zsa_action) { Some((note, _address, memo_bytes)) } else if let Some((note, address, memo_bytes)) = try_output_recovery_with_ovk( @@ -431,10 +439,16 @@ pub async fn decrypt_memo( } } if let Some(bundle) = tx_data.ironwood_bundle() { - debug!("decrypt_memo: ironwood bundle with {} actions", bundle.actions().len()); + debug!( + "decrypt_memo: ironwood bundle with {} actions", + bundle.actions().len() + ); process_orchard_memo!(bundle, 3, IronwoodDomain); } else { - debug!("decrypt_memo: no ironwood bundle in tx {}", hex::encode(txid)); + debug!( + "decrypt_memo: no ironwood bundle in tx {}", + hex::encode(txid) + ); } let fee = fee_manager.fee(); sqlx::query("UPDATE transactions SET fee = ? WHERE id_tx = ?") diff --git a/rust/src/mempool.rs b/rust/src/mempool.rs index 71251c460..f9d7589a8 100644 --- a/rust/src/mempool.rs +++ b/rust/src/mempool.rs @@ -1,12 +1,11 @@ use crate::api::coin::Network; use crate::api::mempool::{MempoolAmount, MempoolMsg, MempoolNote, MempoolTx}; +use crate::keys::{orchard_scope_to_u8, scope_to_u8}; use anyhow::{Context as _, Result}; use itertools::Itertools; use orchard::{keys::Scope, note_encryption::OrchardDomain}; -use crate::keys::{orchard_scope_to_u8, scope_to_u8}; use sapling_crypto::{ - keys::PreparedIncomingViewingKey, - note_encryption::SaplingDomain, + keys::PreparedIncomingViewingKey, note_encryption::SaplingDomain, zip32::DiversifiableFullViewingKey, }; use sqlx::SqliteConnection; @@ -22,9 +21,9 @@ use zcash_primitives::transaction::{ use zcash_protocol::memo::Memo; use zcash_transparent::address::TransparentAddress; -use crate::{Client, Sink}; #[cfg(feature = "flutter")] use crate::frb_generated::StreamSink; +use crate::{Client, Sink}; #[cfg(feature = "flutter")] pub async fn run_mempool( diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 469da0244..c7dec9f0b 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -7,13 +7,10 @@ use crate::{ api::coin::Network, db::get_account_hw, pay::{ - fee::{COST_PER_ACTION, FeeManager}, - plan::{ - extract_transaction, plan_transaction, - sign_transaction, - }, + fee::{FeeManager, COST_PER_ACTION}, + plan::{extract_transaction, plan_transaction, sign_transaction}, pool::PoolMask, - Recipient, send, + send, Recipient, }, Client, }; @@ -35,7 +32,6 @@ pub const ANCHOR_BUCKET_SIZE: u32 = 144; /// output (2 actions, padded) = 4 × COST_PER_ACTION = 20,000 zats. const SD_FEE_PAD: u64 = 4 * COST_PER_ACTION; - /// Decompose a total amount into standard denomination notes with embedded fees. /// /// Each standard denomination is `10^k + P` where P = 2*COST_PER_ACTION: @@ -154,14 +150,12 @@ async fn fetch_unspent_orchard_notes_with_cmx( ) .bind(checkpoint_height) .bind(account) - .map(|row| { - OrchardZecNote { - id: row.get(0), - height: row.get(1), - value: row.get::(2) as u64, - cmx: row.get(3), - has_checkpoint: row.get(4), - } + .map(|row| OrchardZecNote { + id: row.get(0), + height: row.get(1), + value: row.get::(2) as u64, + cmx: row.get(3), + has_checkpoint: row.get(4), }) .fetch_all(connection) .await @@ -190,21 +184,17 @@ pub async fn step( account: u32, ) -> Result { let height = client.latest_height().await?; - let checkpoint_height = - crate::sync::get_db_height(&mut *connection, account).await?.height; + let checkpoint_height = crate::sync::get_db_height(&mut *connection, account) + .await? + .height; // Get the wallet's own Orchard/Ironwood address let hw = get_account_hw(&mut *connection, account).await?; - let own_address = - get_account_full_address(network, &mut *connection, account, 0, hw).await?; + let own_address = get_account_full_address(network, &mut *connection, account, 0, hw).await?; // Fetch all unspent Orchard ZEC notes with cmx. - let orchard_zec = fetch_unspent_orchard_notes_with_cmx( - &mut *connection, - account, - checkpoint_height, - ) - .await?; + let orchard_zec = + fetch_unspent_orchard_notes_with_cmx(&mut *connection, account, checkpoint_height).await?; info!( "Migration step: {} Orchard ZEC notes found", @@ -215,8 +205,7 @@ pub async fn step( } // Separate SD vs non-SD - let sd_notes: Vec<&OrchardZecNote> = - orchard_zec.iter().filter(|n| is_sd(n.value)).collect(); + let sd_notes: Vec<&OrchardZecNote> = orchard_zec.iter().filter(|n| is_sd(n.value)).collect(); let non_sd_notes: Vec<&OrchardZecNote> = orchard_zec.iter().filter(|n| !is_sd(n.value)).collect(); info!( @@ -241,122 +230,114 @@ pub async fn step( let total: u64 = capped_non_sd.iter().map(|n| n.value).sum(); if total >= MIN_SD { - // Decompose into standard denomination counts (digits) and remainder. - let (mut digits, mut remainder) = decompose_to_sd(total); - info!( - "SD split: {:?}", - digits, - ); - - // If the natural remainder is too small to cover the transaction fee, - // carve out MIN_SD from the decomposable pool as a fee buffer. - if remainder < MIN_SD / 2 { - let (d, r) = decompose_to_sd(total.saturating_sub(MIN_SD)); - digits = d; - remainder = r + MIN_SD; - info!( - "SD split (reserved {} for fees): {:?}", - MIN_SD, digits, - ); - } - - let mut num_outputs: u64 = digits.iter().map(|&(_, c)| c as u64).sum(); - let num_inputs = capped_non_sd.len() as u64; - - // Build a FeeManager matching what plan_transaction will construct, - // including the change output, so our fee estimate is exact. - let mut fm = FeeManager { - migration: true, - ..FeeManager::default() - }; - for _ in 0..num_inputs { - fm.add_input(2); - } - for _ in 0..num_outputs { - fm.add_output(2); - } - fm.add_output(2); // change output - - // Fee loop: if fee exceeds remainder, trim the lowest-denomination - // output to make room, then retry. Exit when fee fits or no outputs - // remain (fall through to migration). - loop { - let fee = fm.fee(); + // Decompose into standard denomination counts (digits) and remainder. + let (mut digits, mut remainder) = decompose_to_sd(total); + info!("SD split: {:?}", digits,); + + // If the natural remainder is too small to cover the transaction fee, + // carve out MIN_SD from the decomposable pool as a fee buffer. + if remainder < MIN_SD / 2 { + let (d, r) = decompose_to_sd(total.saturating_sub(MIN_SD)); + digits = d; + remainder = r + MIN_SD; + info!("SD split (reserved {} for fees): {:?}", MIN_SD, digits,); + } - if fee <= remainder || num_outputs == 0 { - break; + let mut num_outputs: u64 = digits.iter().map(|&(_, c)| c as u64).sum(); + let num_inputs = capped_non_sd.len() as u64; + + // Build a FeeManager matching what plan_transaction will construct, + // including the change output, so our fee estimate is exact. + let mut fm = FeeManager { + migration: true, + ..FeeManager::default() + }; + for _ in 0..num_inputs { + fm.add_input(2); } + for _ in 0..num_outputs { + fm.add_output(2); + } + fm.add_output(2); // change output + + // Fee loop: if fee exceeds remainder, trim the lowest-denomination + // output to make room, then retry. Exit when fee fits or no outputs + // remain (fall through to migration). + loop { + let fee = fm.fee(); - // Remove one unit from the lowest denomination (last, since - // denominations are sorted largest-first). - if let Some((denom, count)) = digits.last_mut() { - *count -= 1; - remainder += *denom; - num_outputs -= 1; - fm.remove_output(2); - if *count == 0 { - digits.pop(); + if fee <= remainder || num_outputs == 0 { + break; } - } - } - if num_outputs > 0 { - // Build recipients from (denom, count) pairs. - let mut recipients: Vec = Vec::new(); - for &(denom, count) in &digits { - for _ in 0..count { - recipients.push(Recipient { - address: own_address.clone(), - amount: denom, - pools: Some(PoolMask::from_pool(2).0), // Orchard only - ..Recipient::default() - }); + // Remove one unit from the lowest denomination (last, since + // denominations are sorted largest-first). + if let Some((denom, count)) = digits.last_mut() { + *count -= 1; + remainder += *denom; + num_outputs -= 1; + fm.remove_output(2); + if *count == 0 { + digits.pop(); + } } } - info!( - "Migration split: {} non-SD notes (total {}) → {} SD outputs (remainder {})", - capped_non_sd.len(), - total, - recipients.len(), - remainder, - ); - - let preselected: Vec = capped_non_sd.iter().map(|n| n.id).collect(); - - let pczt = plan_transaction( - network, - &mut *connection, - client, - account, - PoolMask::from_pool(2).0, // Orchard source - &recipients, - false, - None, - false, - None, - None, - true, // migration - Some(&preselected), - None, // anchor_height - ) - .await?; + if num_outputs > 0 { + // Build recipients from (denom, count) pairs. + let mut recipients: Vec = Vec::new(); + for &(denom, count) in &digits { + for _ in 0..count { + recipients.push(Recipient { + address: own_address.clone(), + amount: denom, + pools: Some(PoolMask::from_pool(2).0), // Orchard only + ..Recipient::default() + }); + } + } - let fee = crate::pay::TxPlan::from_package(network, &pczt) - .map(|p| p.fee) - .unwrap_or(0); - let pczt = - sign_transaction(&mut *connection, account, network, &pczt).await?; - let tx_bytes = extract_transaction(&pczt).await?; - let _txid = send(client, height, &tx_bytes).await?; + info!( + "Migration split: {} non-SD notes (total {}) → {} SD outputs (remainder {})", + capped_non_sd.len(), + total, + recipients.len(), + remainder, + ); - return Ok(MigrationEvent::SplitComplete { fee }); - } - // If no outputs after trimming, fall through to migration phase. + let preselected: Vec = capped_non_sd.iter().map(|n| n.id).collect(); + + let pczt = plan_transaction( + network, + &mut *connection, + client, + account, + PoolMask::from_pool(2).0, // Orchard source + &recipients, + false, + None, + false, + None, + None, + true, // migration + Some(&preselected), + None, // anchor_height + ) + .await?; + + let fee = crate::pay::TxPlan::from_package(network, &pczt) + .map(|p| p.fee) + .unwrap_or(0); + let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; + let tx_bytes = extract_transaction(&pczt).await?; + let _txid = send(client, height, &tx_bytes).await?; + + return Ok(MigrationEvent::SplitComplete { fee }); + } + // If no outputs after trimming, fall through to migration phase. } // end if total >= MIN_SD if !sd_notes.is_empty() { - /* # migrate one orchard SD note at a time - inputs: @@ -435,8 +416,7 @@ pub async fn step( let fee = crate::pay::TxPlan::from_package(network, &pczt) .map(|p| p.fee) .unwrap_or(0); - let pczt = - sign_transaction(&mut *connection, account, network, &pczt).await?; + let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; let tx_bytes = extract_transaction(&pczt).await?; let _txid = send(client, height, &tx_bytes).await?; @@ -454,14 +434,14 @@ mod tests { #[test] fn test_is_sd() { // SD_FEE_PAD = 20_000, so SD = 10^k + 20_000 - assert!(!is_sd(10_001)); // not a multiple of 10,000 - assert!(!is_sd(20_001)); // (20001-20000) % 100000 = 1 ≠ 0 - assert!(is_sd(120_000)); // 10^5 + 20_000 - assert!(is_sd(1_020_000)); // 10^6 + 20_000 - assert!(is_sd(10_020_000)); // 10^7 + 20_000 - assert!(!is_sd(1_000_000)); // missing +base - assert!(!is_sd(120_001)); // (120001-20000) % 100000 = 1 ≠ 0 - // Old P=10_000 values are no longer SD + assert!(!is_sd(10_001)); // not a multiple of 10,000 + assert!(!is_sd(20_001)); // (20001-20000) % 100000 = 1 ≠ 0 + assert!(is_sd(120_000)); // 10^5 + 20_000 + assert!(is_sd(1_020_000)); // 10^6 + 20_000 + assert!(is_sd(10_020_000)); // 10^7 + 20_000 + assert!(!is_sd(1_000_000)); // missing +base + assert!(!is_sd(120_001)); // (120001-20000) % 100000 = 1 ≠ 0 + // Old P=10_000 values are no longer SD assert!(!is_sd(110_000)); assert!(!is_sd(1_010_000)); } diff --git a/rust/src/net/lwd.rs b/rust/src/net/lwd.rs index 37dee32b7..2d79ec580 100644 --- a/rust/src/net/lwd.rs +++ b/rust/src/net/lwd.rs @@ -7,7 +7,10 @@ use tonic::{async_trait, Request}; use zcash_protocol::consensus::{BlockHeight, BranchId}; use crate::{ - GRPCClient, api::{coin::Network, network::LWDInfo}, lwd::*, net::LwdServer + api::{coin::Network, network::LWDInfo}, + lwd::*, + net::LwdServer, + GRPCClient, }; #[async_trait] @@ -182,8 +185,7 @@ impl LwdServer for GRPCClient { hex::decode(&state.sapling_tree).expect("Failed to decode sapling tree hex"); let orchard_tree = hex::decode(&state.orchard_tree).expect("Failed to decode sapling tree hex"); - let ironwood_tree = - hex::decode(&state.ironwood_tree).unwrap_or_default(); + let ironwood_tree = hex::decode(&state.ironwood_tree).unwrap_or_default(); Ok((sapling_tree, orchard_tree, ironwood_tree)) } } @@ -207,7 +209,11 @@ pub async fn query_lwd_list(coin: u8) -> Result> { for item in servers { let hostname = item["hostname"].as_str().unwrap_or_default(); let port = item["port"].as_u64().unwrap_or(9067); - let scheme = if hostname.ends_with(".onion") { "http" } else { "https" }; + let scheme = if hostname.ends_with(".onion") { + "http" + } else { + "https" + }; let url = format!("{}://{}:{}", scheme, hostname, port); let is_tor = hostname.ends_with(".onion"); let height = item["height"].as_u64().unwrap_or(0) as u32; diff --git a/rust/src/net/mod.rs b/rust/src/net/mod.rs index 6ff3c4ca6..f14693698 100644 --- a/rust/src/net/mod.rs +++ b/rust/src/net/mod.rs @@ -4,10 +4,7 @@ use zcash_primitives::transaction::Transaction; use tonic::async_trait; -use crate::{ - api::coin::Network, - lwd::*, -}; +use crate::{api::coin::Network, lwd::*}; pub mod lwd; pub mod zebra; diff --git a/rust/src/net/zebra.rs b/rust/src/net/zebra.rs index 9deffd815..3cbed4f59 100644 --- a/rust/src/net/zebra.rs +++ b/rust/src/net/zebra.rs @@ -22,8 +22,8 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio_rustls::TlsConnector; use tor_rtcompat::PreferredRuntime; use webpki_roots::TLS_SERVER_ROOTS; -use zcash_primitives::{block::BlockHeader, transaction::Transaction}; use zcash_primitives::transaction::OrchardBundle; +use zcash_primitives::{block::BlockHeader, transaction::Transaction}; use byteorder::{ReadBytesExt, LE}; use tokio_stream::wrappers::ReceiverStream; @@ -33,7 +33,10 @@ use zcash_protocol::consensus::{BlockHeight, BranchId}; const COMPACT_NOTE_SIZE: usize = 52; use crate::{ - IntoAnyhow, api::coin::{Network, TOR}, lwd::*, net::LwdServer + api::coin::{Network, TOR}, + lwd::*, + net::LwdServer, + IntoAnyhow, }; #[derive(Clone)] @@ -111,10 +114,7 @@ macro_rules! jsonrpc { } impl ZebraClient { - pub async fn jsonrpc_impl( - &self, - req: Value, - ) -> Result + pub async fn jsonrpc_impl(&self, req: Value) -> Result where R: for<'de> Deserialize<'de>, { @@ -122,7 +122,8 @@ impl ZebraClient { let tor = &*tor_client.lock().await; self.post_tor(tor, req).await? } else { - let body: Value = self.client + let body: Value = self + .client .post(&self.url) .json(&req) .send() @@ -203,12 +204,7 @@ impl LwdServer for ZebraClient { } async fn block(&mut self, network: &Network, height: u32) -> Result { - let block_hex = jsonrpc!( - self, - "getblock", - [height.to_string(), 0], - String - )?; + let block_hex = jsonrpc!(self, "getblock", [height.to_string(), 0], String)?; let block_bytes = hex::decode(block_hex) .map_err(|e| anyhow::anyhow!("Failed to decode block hex: {}", e))?; let branch_id = BranchId::for_height(network, BlockHeight::from_u32(height)); @@ -218,12 +214,7 @@ impl LwdServer for ZebraClient { async fn post_transaction(&mut self, height: u32, tx: &[u8]) -> Result { let tx_hex = hex::encode(tx); - let rep = jsonrpc!( - self, - "sendrawtransaction", - [tx_hex], - String - )?; + let rep = jsonrpc!(self, "sendrawtransaction", [tx_hex], String)?; Ok(rep) } @@ -231,12 +222,7 @@ impl LwdServer for ZebraClient { let mut txid = txid.to_vec(); txid.reverse(); let tx_hex = hex::encode(txid); - let rep = jsonrpc!( - self, - "getrawtransaction", - [tx_hex, 1], - Value - )?; + let rep = jsonrpc!(self, "getrawtransaction", [tx_hex, 1], Value)?; let data = rep["hex"] .as_str() .ok_or_else(|| anyhow::anyhow!("Invalid response from node: No hex field"))? @@ -320,12 +306,7 @@ impl LwdServer for ZebraClient { } async fn tree_state(&mut self, height: u32) -> Result<(Vec, Vec, Vec)> { - let res = jsonrpc!( - self, - "z_gettreestate", - [height.to_string()], - Value - )?; + let res = jsonrpc!(self, "z_gettreestate", [height.to_string()], Value)?; let sapling_tree = res["sapling"]["commitments"]["finalState"] .as_str() .ok_or_else(|| { @@ -346,7 +327,11 @@ impl LwdServer for ZebraClient { .as_str() .unwrap_or("") .to_string(); - Ok((hex::decode(sapling_tree)?, hex::decode(orchard_tree)?, hex::decode(&ironwood_tree).unwrap_or_default())) + Ok(( + hex::decode(sapling_tree)?, + hex::decode(orchard_tree)?, + hex::decode(&ironwood_tree).unwrap_or_default(), + )) } } @@ -390,7 +375,9 @@ pub fn parse_block( ($bundle:expr, $actions:expr) => {{ let bundle = $bundle; for action in bundle.actions().iter() { - let ciphertext = action.encrypted_note().enc_ciphertext.as_ref()[..COMPACT_NOTE_SIZE].to_vec(); + let ciphertext = action.encrypted_note().enc_ciphertext.as_ref() + [..COMPACT_NOTE_SIZE] + .to_vec(); $actions.push(CompactOrchardAction { nullifier: action.nullifier().to_bytes().to_vec(), cmx: action.cmx().to_bytes().to_vec(), @@ -463,15 +450,22 @@ pub fn parse_block( } pub fn read_compact_u32(mut reader: R) -> Result { - let tpe = reader.read_u8().map_err(|e| anyhow::anyhow!("Failed to read compact u32 type: {}", e))?; + let tpe = reader + .read_u8() + .map_err(|e| anyhow::anyhow!("Failed to read compact u32 type: {}", e))?; if tpe < 0xFD { return Ok(tpe as u32); } if tpe == 0xFD { - return Ok(reader.read_u16::().map_err(|e| anyhow::anyhow!("Failed to read compact u16: {}", e))? as u32); + return Ok(reader + .read_u16::() + .map_err(|e| anyhow::anyhow!("Failed to read compact u16: {}", e))? + as u32); } if tpe == 0xFE { - return reader.read_u32::().map_err(|e| anyhow::anyhow!("Failed to read compact u32: {}", e)); + return reader + .read_u32::() + .map_err(|e| anyhow::anyhow!("Failed to read compact u32: {}", e)); } anyhow::bail!("Invalid compact u32 type: {tpe}"); } diff --git a/rust/src/openalias.rs b/rust/src/openalias.rs index a8772a0db..9bad1e06d 100644 --- a/rust/src/openalias.rs +++ b/rust/src/openalias.rs @@ -170,9 +170,7 @@ fn build_dns_resolver(secure: bool) -> TokioAsyncResolver { match hickory_resolver::system_conf::read_system_conf() { Ok((config, _)) => { - info!( - "DNS resolver created from system config (DNSSEC: {secure})" - ); + info!("DNS resolver created from system config (DNSSEC: {secure})"); TokioAsyncResolver::tokio(config, opts) } Err(e) => { @@ -202,10 +200,9 @@ fn resolver_secure() -> &'static TokioAsyncResolver { /// records (as opposed to having broken/unverifiable DNSSEC records). fn is_unsigned_error(err: &ResolveError) -> bool { match err.kind() { - ResolveErrorKind::Proto(proto_err) => matches!( - proto_err.kind(), - ProtoErrorKind::RrsigsNotPresent { .. } - ), + ResolveErrorKind::Proto(proto_err) => { + matches!(proto_err.kind(), ProtoErrorKind::RrsigsNotPresent { .. }) + } _ => false, } } @@ -250,8 +247,7 @@ async fn lookup_txt_with_dnssec( /// Perform async DNS TXT lookup and parse OA1 records into [`Oa1Record`]s. /// Returns the parsed records along with the DNSSEC validation status. async fn lookup_oa1_records(alias: &str) -> Result<(Vec, DnssecStatus)> { - let fqdn = - alias_to_fqdn(alias).ok_or_else(|| anyhow!("Invalid OpenAlias name: {alias}"))?; + let fqdn = alias_to_fqdn(alias).ok_or_else(|| anyhow!("Invalid OpenAlias name: {alias}"))?; info!("Resolving OpenAlias: {alias} → {fqdn}"); let (response, status) = lookup_txt_with_dnssec(&fqdn, alias).await?; @@ -271,9 +267,7 @@ async fn lookup_oa1_records(alias: &str) -> Result<(Vec, DnssecStatus for r in &records { match parse_oa1(r) { Some(addr) => addrs.push(addr), - None => info!( - "OpenAlias failed to parse OA1 record for {alias}: {r}" - ), + None => info!("OpenAlias failed to parse OA1 record for {alias}: {r}"), } } info!("OpenAlias parsed {} address(es) for {alias}", addrs.len()); @@ -325,8 +319,8 @@ pub async fn resolve_zcash(alias: &str) -> Result<(Vec, DnssecStatus) /// `convert_if_network` for the network check. Returns `Ok(())` if the /// address is valid for the given network, or an error with details. pub fn try_validate_zcash_address(address: &str, net: NetworkType) -> Result<()> { - let addr = - ZcashAddress::try_from_encoded(address).map_err(|e| anyhow!("Invalid Zcash address: {e}"))?; + let addr = ZcashAddress::try_from_encoded(address) + .map_err(|e| anyhow!("Invalid Zcash address: {e}"))?; match addr.convert_if_network::(net) { Err(ConversionError::IncorrectNetwork { expected, actual }) => Err(anyhow!( @@ -373,8 +367,7 @@ pub async fn resolve_zcash_for_network( /// Get the raw OpenAlias TXT record strings for an alias (without parsing), /// along with the DNSSEC validation status. pub async fn resolve_raw(alias: &str) -> Result<(Vec, DnssecStatus)> { - let fqdn = - alias_to_fqdn(alias).ok_or_else(|| anyhow!("Invalid OpenAlias name: {alias}"))?; + let fqdn = alias_to_fqdn(alias).ok_or_else(|| anyhow!("Invalid OpenAlias name: {alias}"))?; let (response, status) = lookup_txt_with_dnssec(&fqdn, alias).await?; @@ -417,8 +410,14 @@ mod tests { #[test] fn test_validate_zcash_address_garbage() { - assert!(!validate_zcash_address("not-a-zcash-address", NetworkType::Main)); - assert!(!validate_zcash_address("not-a-zcash-address", NetworkType::Test)); + assert!(!validate_zcash_address( + "not-a-zcash-address", + NetworkType::Main + )); + assert!(!validate_zcash_address( + "not-a-zcash-address", + NetworkType::Test + )); assert!(!validate_zcash_address( "not-a-zcash-address", NetworkType::Regtest @@ -436,8 +435,7 @@ mod tests { #[test] fn test_parse_oa1_with_quoted_semicolon() { - let record = - "oa1:btc recipient_address=1addr; recipient_name=\"nabijaczleweli; FOSS\";"; + let record = "oa1:btc recipient_address=1addr; recipient_name=\"nabijaczleweli; FOSS\";"; let parsed = parse_oa1(record).unwrap(); assert_eq!(parsed.cryptocurrency, "btc"); assert_eq!(parsed.address, "1addr"); @@ -456,7 +454,10 @@ mod tests { let parsed = parse_oa1(record).unwrap(); assert_eq!(parsed.cryptocurrency, "btc"); assert_eq!(parsed.address, "1MoSyGZp3SKpoiXPXfZDFK7cDUFCVtEDeS"); - assert_eq!(parsed.tx_description, Some("Donation for nabijaczleweli: ".to_string())); + assert_eq!( + parsed.tx_description, + Some("Donation for nabijaczleweli: ".to_string()) + ); } #[test] diff --git a/rust/src/pay/fee.rs b/rust/src/pay/fee.rs index 6d0fb4b72..67ece34a8 100644 --- a/rust/src/pay/fee.rs +++ b/rust/src/pay/fee.rs @@ -79,9 +79,9 @@ impl FeeManager { 0 }; let f = (t as u64 + s as u64 + o + i as u64).max(2); // minimum 2 logical actions - // Issuance actions are counted by the builder as orchard actions, - // so we don't add them separately here. The issuance counts are - // informational for logging only. + // Issuance actions are counted by the builder as orchard actions, + // so we don't add them separately here. The issuance counts are + // informational for logging only. f as u64 * COST_PER_ACTION } diff --git a/rust/src/pay/mod.rs b/rust/src/pay/mod.rs index 1a7ca33ce..7f7113be3 100644 --- a/rust/src/pay/mod.rs +++ b/rust/src/pay/mod.rs @@ -130,10 +130,7 @@ pub struct TxPlan { pub can_broadcast: bool, } -fn orchard_asset_name( - proprietary: &BTreeMap>, - asset: Option, -) -> String { +fn orchard_asset_name(proprietary: &BTreeMap>, asset: Option) -> String { proprietary .get("asset_name") .and_then(|value| String::from_utf8(value.clone()).ok()) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 32554ecac..fc9040f49 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -29,7 +29,6 @@ use tracing::{event, info, span, Level}; use zcash_address::{unified::Receiver, ConversionError, TryFromAddress, ZcashAddress}; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; use zcash_note_encryption::Domain; -use zcash_protocol::{PoolType, ShieldedPool}; use zcash_primitives::transaction::{ builder::{BuildConfig, Builder, BundlePadding}, fees::zip317::FeeRule, @@ -40,6 +39,7 @@ use zcash_protocol::{ memo::{Memo, MemoBytes}, value::Zatoshis, }; +use zcash_protocol::{PoolType, ShieldedPool}; use zcash_transparent::{ address::TransparentAddress, builder::{SpendInfo, TransparentInputInfo}, @@ -62,7 +62,7 @@ use crate::{ fee::COST_PER_ACTION, pool::{PoolMask, NUM_POOLS}, prepare::to_zec, - solve, InputNote, Recipient, RecipientState, ReceiverOption, DecomposedRecipient, + solve, DecomposedRecipient, InputNote, ReceiverOption, Recipient, RecipientState, }, warp::hasher::{empty_roots, OrchardHasher, SaplingHasher}, Client, @@ -192,7 +192,11 @@ fn decompose_address( TransparentAddress::PublicKeyHash(hash) => Receiver::P2pkh(hash), TransparentAddress::ScriptHash(hash) => Receiver::P2sh(hash), }; - return Ok(ReceiverOption { receiver, pool: 0, remaining: 0 }); + return Ok(ReceiverOption { + receiver, + pool: 0, + remaining: 0, + }); } if zaddr.can_receive_as(PoolType::Shielded(ShieldedPool::Sapling)) { @@ -287,8 +291,8 @@ pub async fn plan_transaction( (input_pools, recipients, recipient_pays_fee) }; - let ironwood_active = network - .is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height)); + let ironwood_active = + network.is_nu_active(NetworkUpgrade::Nu6_3, BlockHeight::from_u32(height)); let orchard_note_version = if BranchId::for_height(network, BlockHeight::from_u32(height)) == BranchId::Nu7 { orchard::NoteVersion::V3ZSA @@ -316,7 +320,9 @@ pub async fn plan_transaction( .collect::>>()?; // ZSA and Ironwood are mutually exclusive (different V6 version group IDs). - let has_zsa = decomposed.iter().any(|d| d.asset_base != [0u8; 32].to_vec()) + let has_zsa = decomposed + .iter() + .any(|d| d.asset_base != [0u8; 32].to_vec()) || issuance.is_some(); if has_zsa && ironwood_active { anyhow::bail!("ZSA and Ironwood are incompatible"); @@ -370,10 +376,14 @@ pub async fn plan_transaction( } info!( "plan: after dust filter — t:{}→{}, s:{}→{}, o:{}→{}, iw:{}→{}", - before_dust[0], input_pools[0].len(), - before_dust[1], input_pools[1].len(), - before_dust[2], input_pools[2].len(), - before_dust[3], input_pools[3].len(), + before_dust[0], + input_pools[0].len(), + before_dust[1], + input_pools[1].len(), + before_dust[2], + input_pools[2].len(), + before_dust[3], + input_pools[3].len(), ); // Build asset→index lookup: 0 = ZEC, 1+ = index into zsa_assets @@ -416,8 +426,7 @@ pub async fn plan_transaction( // with phantom ZEC while the builder spent the note as its real // asset, leaving that asset over-spent and the ZEC change unbacked // (Orchard IO-finalize → ValueCommitMismatch). - let asset_bytes: [u8; 32] = - n.asset_base.clone().try_into().unwrap_or(zec_key); + let asset_bytes: [u8; 32] = n.asset_base.clone().try_into().unwrap_or(zec_key); let asset_index = if asset_bytes == zec_key { 0 } else { @@ -426,7 +435,12 @@ pub async fn plan_transaction( None => return None, } }; - Some(solve::Note { pool: pool as u8, amount: n.amount, pool_index: idx, asset_index }) + Some(solve::Note { + pool: pool as u8, + amount: n.amount, + pool_index: idx, + asset_index, + }) }) }) .collect(); @@ -448,7 +462,11 @@ pub async fn plan_transaction( .zip(decomposed.iter()) .map(|(&pool, dr)| { let asset_index = resolve_asset_index(&dr.asset_base, zec_key, &zsa_index); - solve::Output { pool, amount: dr.amount, asset_index } + solve::Output { + pool, + amount: dr.amount, + asset_index, + } }) .collect(); @@ -473,7 +491,9 @@ pub async fn plan_transaction( info!( "plan: select_notes succeeded — fee={}, change_pool={}, selected_inputs={}", - selection.fee, selection.change_pool, selection.inputs.len() + selection.fee, + selection.change_pool, + selection.inputs.len() ); // Mark selected notes as fully consumed (select_notes uses 0/1 knapsack) @@ -595,8 +615,7 @@ pub async fn plan_transaction( "Anchor height {anchor_height} is ahead of checkpoint {}", h.height, ); - let (ts, to, ti) = - crate::sync::get_tree_state(network, client, anchor_height).await?; + let (ts, to, ti) = crate::sync::get_tree_state(network, client, anchor_height).await?; let es = ts.to_edge(&SaplingHasher::default()); let eo = to.to_edge(&OrchardHasher::default()); let ei = ti.to_edge(&OrchardHasher::default()); @@ -609,7 +628,9 @@ pub async fn plan_transaction( for pool in 1..NUM_POOLS { let p = pool as u8; has_pool[pool] = input_pools[pool].iter().any(|inp| inp.is_used()) - || recipient_states.iter().any(|r| r.pool_mask.to_best_pool() == Some(p)) + || recipient_states + .iter() + .any(|r| r.pool_mask.to_best_pool() == Some(p)) || change_pool == p; } has_pool[3] &= ironwood_active; @@ -720,23 +741,19 @@ pub async fn plan_transaction( } else { pubkey.serialize().to_vec() }; - let pkh: [u8; 20] = - Ripemd160::digest(Sha256::digest(&pk_bytes)).into(); + let pkh: [u8; 20] = Ripemd160::digest(Sha256::digest(&pk_bytes)).into(); let addr = TransparentAddress::PublicKeyHash(pkh); - let coin = TxOut::new( - Zatoshis::from_u64(*amount).unwrap(), - addr.script().into(), + let coin = + TxOut::new(Zatoshis::from_u64(*amount).unwrap(), addr.script().into()); + + builder.add_transparent_input( + TransparentInputInfo::from_parts( + utxo, + coin, + SpendInfo::P2pkh { pubkey }, + ) + .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?, ); - - builder - .add_transparent_input( - TransparentInputInfo::from_parts( - utxo, - coin, - SpendInfo::P2pkh { pubkey }, - ) - .map_err(|e: zcash_transparent::builder::Error| anyhow!(e))?, - ); tsk_dindex.push((pubkey, scope, dindex_t, taddress, uncompressed)); } 1 => { @@ -760,7 +777,6 @@ pub async fn plan_transaction( s_scope.push(scope); } 2 => { - let (note, merkle_path) = get_orchard_note( connection, *id, @@ -845,11 +861,13 @@ pub async fn plan_transaction( let asset_base = if r.asset_base == [0u8; 32].to_vec() { AssetBase::zatoshi() } else { - let asset_bytes: [u8; 32] = r.asset_base.clone().try_into().map_err( - |v: Vec| anyhow!("Invalid asset_base length: expected 32, got {}", v.len()), - )?; - Option::from(AssetBase::from_bytes(&asset_bytes)) - .ok_or_else(|| anyhow!("Invalid asset_base bytes: {}", hex::encode(&asset_bytes)))? + let asset_bytes: [u8; 32] = + r.asset_base.clone().try_into().map_err(|v: Vec| { + anyhow!("Invalid asset_base length: expected 32, got {}", v.len()) + })?; + Option::from(AssetBase::from_bytes(&asset_bytes)).ok_or_else(|| { + anyhow!("Invalid asset_base bytes: {}", hex::encode(&asset_bytes)) + })? }; if ironwood_active { // O->O self-send: use change output to avoid dummy-spend @@ -1047,14 +1065,13 @@ pub async fn plan_transaction( }) .unwrap(); - let updater = if BranchId::for_height(network, BlockHeight::from_u32(target_height)) - == BranchId::Nu7 - { - updater.update_orchard_zsa_with(|u| attach_orchard_asset_names(u, &asset_names)) - } else { - updater.update_orchard_with(|u| attach_orchard_asset_names(u, &asset_names)) - } - .map_err(|error| anyhow!("Failed to attach Orchard asset names: {error:?}"))?; + let updater = + if BranchId::for_height(network, BlockHeight::from_u32(target_height)) == BranchId::Nu7 { + updater.update_orchard_zsa_with(|u| attach_orchard_asset_names(u, &asset_names)) + } else { + updater.update_orchard_with(|u| attach_orchard_asset_names(u, &asset_names)) + } + .map_err(|error| anyhow!("Failed to attach Orchard asset names: {error:?}"))?; let pczt = updater.finish(); @@ -1089,13 +1106,7 @@ pub async fn plan_transaction( .actions() .iter() .enumerate() - .filter_map(|(index, action)| { - action - .spend() - .spend_auth_sig() - .is_none() - .then_some(index) - }) + .filter_map(|(index, action)| action.spend().spend_auth_sig().is_none().then_some(index)) .collect(); let pczt_package = PcztPackage { pczt: pczt.serialize().unwrap(), @@ -1291,9 +1302,7 @@ pub async fn sign_transaction( return Err(Error::NoSigningKey.into()); }; signer.sign_orchard(*bundle_index, osak).map_err(|e| { - anyhow!( - "failed to sign Orchard action {bundle_index} (selected spend {index}): {e:?}" - ) + anyhow!("failed to sign Orchard action {bundle_index} (selected spend {index}): {e:?}") })?; } for (index, bundle_index) in ironwood_indices.iter().enumerate() { @@ -1449,7 +1458,6 @@ fn get_orchard_address(network: &Network, address: &str) -> Result

{ } } - pub async fn fetch_unspent_notes_grouped_by_pool( connection: &mut SqliteConnection, account: u32, @@ -1555,8 +1563,7 @@ pub async fn get_sapling_prover() -> Result<&'static LocalTxProver> { } pub static ORCHARD_VANILLA_PK: LazyLock = LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::FixedPostNu6_2)); -pub static ORCHARD_ZSA_PK: LazyLock = - LazyLock::new(|| ProvingKey::build_zsa()); +pub static ORCHARD_ZSA_PK: LazyLock = LazyLock::new(|| ProvingKey::build_zsa()); pub static IRONWOOD_PK: LazyLock = LazyLock::new(|| ProvingKey::build(orchard::circuit::OrchardCircuitVersion::PostNu6_3)); diff --git a/rust/src/pay/pool.rs b/rust/src/pay/pool.rs index 984bf00ed..3eba98b21 100644 --- a/rust/src/pay/pool.rs +++ b/rust/src/pay/pool.rs @@ -75,14 +75,10 @@ impl PoolMask { if address.can_receive_as(PoolType::Transparent) { pool_mask |= 1; } - if address.can_receive_as(PoolType::Shielded( - ShieldedPool::Sapling, - )) { + if address.can_receive_as(PoolType::Shielded(ShieldedPool::Sapling)) { pool_mask |= 2; } - if address.can_receive_as(PoolType::Shielded( - ShieldedPool::Orchard, - )) { + if address.can_receive_as(PoolType::Shielded(ShieldedPool::Orchard)) { pool_mask |= 4 | 8; // I and O share the same addresses } Ok(PoolMask(pool_mask)) diff --git a/rust/src/pay/select.rs b/rust/src/pay/select.rs index 7482e926e..94c864aef 100644 --- a/rust/src/pay/select.rs +++ b/rust/src/pay/select.rs @@ -100,8 +100,7 @@ fn closest_subset_sum(notes: &[u64], target: u64, slack: u64) -> Option<(u64, Ve continue; // this note alone overshoots the window, never useful here } // snapshot existing keys before mutating (0/1 knapsack: each note used once) - let existing: Vec<(u64, Vec)> = - dp.iter().map(|(&s, v)| (s, v.clone())).collect(); + let existing: Vec<(u64, Vec)> = dp.iter().map(|(&s, v)| (s, v.clone())).collect(); for (s, path) in existing { let ns = s + amt; @@ -120,7 +119,9 @@ fn closest_subset_sum(notes: &[u64], target: u64, slack: u64) -> Option<(u64, Ve .map(|(&s, path)| (s, path.clone())) .or_else(|| { // nothing covers target: return largest reachable sum below it - dp.iter().max_by_key(|&(&s, _)| s).map(|(&s, path)| (s, path.clone())) + dp.iter() + .max_by_key(|&(&s, _)| s) + .map(|(&s, path)| (s, path.clone())) }) } @@ -170,7 +171,12 @@ struct TrialResult { // Main selection algorithm // --------------------------------------------------------------------- -pub fn select_notes(notes: &[Note], outputs: &[Output], f_unit: u64, slack: u64) -> Option { +pub fn select_notes( + notes: &[Note], + outputs: &[Output], + f_unit: u64, + slack: u64, +) -> Option { let notes_by_pool = group_notes_by_pool(notes); let (out_sum, out_count) = out_sum_and_count(outputs); let a_o: u64 = out_sum.iter().sum(); @@ -179,7 +185,10 @@ pub fn select_notes(notes: &[Note], outputs: &[Output], f_unit: u64, slack: u64) let mut plain: [PoolSolution; NUM_POOLS] = Default::default(); for p in 1..NUM_POOLS { if let Some((sum, idx)) = closest_subset_sum(¬es_by_pool[p], out_sum[p], slack) { - plain[p] = PoolSolution { note_indices: idx, sum }; + plain[p] = PoolSolution { + note_indices: idx, + sum, + }; } } @@ -221,25 +230,45 @@ pub fn select_notes(notes: &[Note], outputs: &[Output], f_unit: u64, slack: u64) let change = total_input.saturating_sub(a_o + fee); let mut per_pool: [PoolSolution; NUM_POOLS] = Default::default(); - per_pool[cp] = PoolSolution { note_indices: idx_cp.clone(), sum: gross_cp }; + per_pool[cp] = PoolSolution { + note_indices: idx_cp.clone(), + sum: gross_cp, + }; for p in 1..NUM_POOLS { if p != cp { per_pool[p] = plain[p].clone(); } } - let t0 = if cp == 0 { gross_cp + out_sum[0] } else { out_sum[0] }; + let t0 = if cp == 0 { + gross_cp + out_sum[0] + } else { + out_sum[0] + }; let t_shielded: u64 = (1..NUM_POOLS) .map(|p| { - let target = if p == cp { out_sum[p] + change } else { out_sum[p] }; + let target = if p == cp { + out_sum[p] + change + } else { + out_sum[p] + }; (per_pool[p].sum as i64 - target as i64).unsigned_abs() }) .sum(); let turnstile = t0 + t_shielded; - let candidate = TrialResult { change_pool, per_pool, fee, change, turnstile }; + let candidate = TrialResult { + change_pool, + per_pool, + fee, + change, + turnstile, + }; - if best.as_ref().map_or(true, |b| candidate.turnstile < b.turnstile) { + if best + .as_ref() + .map_or(true, |b| candidate.turnstile < b.turnstile) + { best = Some(candidate); } } @@ -266,7 +295,10 @@ fn fallback_with_pool0( let idx: Vec = (0..notes_by_pool[p].len()).collect(); let sum: u64 = notes_by_pool[p].iter().sum(); covered += sum; - per_pool[p] = PoolSolution { note_indices: idx, sum }; + per_pool[p] = PoolSolution { + note_indices: idx, + sum, + }; } let fixed_fee: u64 = (1..NUM_POOLS) @@ -279,7 +311,10 @@ fn fallback_with_pool0( let (n0, gross0, idx0) = solve_with_folded_fee(¬es_by_pool[0], out_count[0], required, f_unit, 0)?; - per_pool[0] = PoolSolution { note_indices: idx0, sum: gross0 }; + per_pool[0] = PoolSolution { + note_indices: idx0, + sum: gross0, + }; let fee0 = pool_fee(n0, out_count[0], 0); let fee = fixed_fee + fee0 * f_unit; @@ -294,7 +329,11 @@ fn fallback_with_pool0( for p in 0..NUM_POOLS { let t: u64 = (1..NUM_POOLS) .map(|q| { - let target = if q == p { out_sum[q] + change } else { out_sum[q] }; + let target = if q == p { + out_sum[q] + change + } else { + out_sum[q] + }; (per_pool[q].sum as i64 - target as i64).unsigned_abs() }) .sum(); @@ -318,7 +357,10 @@ fn finalize_selection(trial: TrialResult, notes_by_pool: &[Vec; NUM_POOLS]) let mut per_pool_indices: [Vec; NUM_POOLS] = Default::default(); for p in 0..NUM_POOLS { for &idx in &trial.per_pool[p].note_indices { - inputs.push(Note { pool: p as u8, amount: notes_by_pool[p][idx] }); + inputs.push(Note { + pool: p as u8, + amount: notes_by_pool[p][idx], + }); } per_pool_indices[p] = trial.per_pool[p].note_indices.clone(); } @@ -346,18 +388,45 @@ mod tests { let slack = 50u64; // DP search window for the plain (non-change) pools let notes = vec![ - Note { pool: 1, amount: 120 }, - Note { pool: 1, amount: 80 }, - Note { pool: 1, amount: 30 }, - Note { pool: 2, amount: 200 }, - Note { pool: 2, amount: 15 }, - Note { pool: 3, amount: 60 }, - Note { pool: 0, amount: 500 }, // last resort only + Note { + pool: 1, + amount: 120, + }, + Note { + pool: 1, + amount: 80, + }, + Note { + pool: 1, + amount: 30, + }, + Note { + pool: 2, + amount: 200, + }, + Note { + pool: 2, + amount: 15, + }, + Note { + pool: 3, + amount: 60, + }, + Note { + pool: 0, + amount: 500, + }, // last resort only ]; let outputs = vec![ - Output { pool: 1, amount: 150 }, - Output { pool: 2, amount: 100 }, + Output { + pool: 1, + amount: 150, + }, + Output { + pool: 2, + amount: 100, + }, ]; let sel = select_notes(¬es, &outputs, f_unit, slack) @@ -395,4 +464,4 @@ mod tests { "pool 0 (transparent) should not be used when shielded notes suffice" ); } -} \ No newline at end of file +} diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 1a4ec4f3e..35e1424da 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -87,14 +87,14 @@ struct State { /// Fixed, precomputed context for a single selection run. struct Context<'a> { - notes: &'a [Note], // sorted: shielded pools first, then transparent; within pool descending by amount - n_assets: u8, // total number of distinct assets (1 = ZEC only) - asset_output_amounts: Vec, // required output amount per asset (index 0 = ZEC) - output_amounts: [u64; N_POOLS], // output value per pool (zats) - n_outputs: [u32; N_POOLS], // number of fixed recipient outputs per pool + notes: &'a [Note], // sorted: shielded pools first, then transparent; within pool descending by amount + n_assets: u8, // total number of distinct assets (1 = ZEC only) + asset_output_amounts: Vec, // required output amount per asset (index 0 = ZEC) + output_amounts: [u64; N_POOLS], // output value per pool (zats) + n_outputs: [u32; N_POOLS], // number of fixed recipient outputs per pool orchard_asset_outputs: Vec, // fixed Orchard recipient outputs per asset - f_unit: u64, // COST_PER_ACTION (5000) - migration: bool, // orchard fee = inputs+outputs instead of max + f_unit: u64, // COST_PER_ACTION (5000) + migration: bool, // orchard fee = inputs+outputs instead of max recipient_pays_fee: bool, first_recipient_amount: u64, } @@ -111,7 +111,11 @@ pub(super) struct Budget { impl Default for Budget { fn default() -> Self { - Budget { max_nodes: 100_000, max_time: Duration::from_millis(200), beam_width: 24 } + Budget { + max_nodes: 100_000, + max_time: Duration::from_millis(200), + beam_width: 24, + } } } @@ -124,7 +128,12 @@ struct BudgetTracker { impl BudgetTracker { fn new(b: &Budget) -> Self { - BudgetTracker { start: Instant::now(), limit: b.max_time, max_nodes: b.max_nodes, nodes: 0 } + BudgetTracker { + start: Instant::now(), + limit: b.max_time, + max_nodes: b.max_nodes, + nodes: 0, + } } fn exceeded(&mut self) -> bool { self.nodes += 1; @@ -158,7 +167,9 @@ fn compute_fee( // Sapling: if any activity, max(inputs, outputs, 2) let s: u64 = if n_inputs[1] > 0 || n_outs[1] > 0 { n_inputs[1].max(n_outs[1]).max(2) as u64 - } else { 0 }; + } else { + 0 + }; // Orchard: migration? inputs+outputs : max(inputs,outputs); clamped to 2 let o: u64 = orchard_actions.unwrap_or_else(|| { @@ -176,7 +187,9 @@ fn compute_fee( // Ironwood: same as Orchard non-migration let iw: u64 = if n_inputs[3] > 0 || n_outs[3] > 0 { n_inputs[3].max(n_outs[3]).max(2) as u64 - } else { 0 }; + } else { + 0 + }; let logical = (t + s + o + iw).max(GRACE_ACTIONS); logical * f_unit @@ -216,9 +229,15 @@ fn zsa_orchard_actions(state: &State, ctx: &Context, change_pool: u8) -> Option< fn evaluate(state: &State, ctx: &Context) -> (u64, u8) { let (cost, pool) = evaluate_privacy(state, ctx); if cost == u64::MAX { - info!("evaluate: asset_sums[0]={}, INFEASIBLE", state.asset_sums[0]); + info!( + "evaluate: asset_sums[0]={}, INFEASIBLE", + state.asset_sums[0] + ); } else { - info!("evaluate: asset_sums[0]={}, privacy_cost={}, change_pool={}", state.asset_sums[0], cost, pool); + info!( + "evaluate: asset_sums[0]={}, privacy_cost={}, change_pool={}", + state.asset_sums[0], cost, pool + ); } (cost, pool) } @@ -256,12 +275,7 @@ fn fee_for_change_pool(state: &State, ctx: &Context, change_pool: u8) -> u64 { ) } -fn is_better_solution( - cost: u64, - fee: u64, - best_cost: u64, - best_fee: u64, -) -> bool { +fn is_better_solution(cost: u64, fee: u64, best_cost: u64, best_fee: u64) -> bool { (cost, fee) < (best_cost, best_fee) } @@ -298,17 +312,19 @@ fn evaluate_privacy(state: &State, ctx: &Context) -> (u64, u8) { // All transparent value passes through the turnstile. let turnstile = state.tin + state.tout - + (1..N_POOLS).map(|p| { - let bal = state.balance[p]; - // Change output adds to the change-pool's output side, - // deepening any deficit or reducing any surplus. - let adjusted = if p == cp as usize { - (bal - change as i64).unsigned_abs() - } else { - bal.unsigned_abs() - }; - adjusted - }).sum::(); + + (1..N_POOLS) + .map(|p| { + let bal = state.balance[p]; + // Change output adds to the change-pool's output side, + // deepening any deficit or reducing any surplus. + let adjusted = if p == cp as usize { + (bal - change as i64).unsigned_abs() + } else { + bal.unsigned_abs() + }; + adjusted + }) + .sum::(); if (turnstile, fee) < (best_turnstile, best_fee) { best_turnstile = turnstile; @@ -435,7 +451,11 @@ fn top_k_by_local_heuristic<'a>( .map(|&(idx, n)| (local_score(n, state), idx, n)) .collect(); scored.sort_by(|a, b| b.0.cmp(&a.0)); // descending - scored.into_iter().take(k).map(|(_, idx, n)| (idx, n)).collect() + scored + .into_iter() + .take(k) + .map(|(_, idx, n)| (idx, n)) + .collect() } // --------------------------------------------------------------------- @@ -454,8 +474,10 @@ fn state_key(state: &State) -> StateKey { ( state.asset_sums.iter().map(|&s| q_u64(s)).collect(), [ - q(state.balance[0]), q(state.balance[1]), - q(state.balance[2]), q(state.balance[3]), + q(state.balance[0]), + q(state.balance[1]), + q(state.balance[2]), + q(state.balance[3]), ], state.tout, state.n_inputs, @@ -665,7 +687,11 @@ pub(super) fn select_notes( let start = initial_state(&ctx); let start_bound = lower_bound(&start, &ctx); if bound_can_beat(start_bound, best_cost) { - heap.push(Reverse(QueueItem { bound: start_bound, seq, state: start })); + heap.push(Reverse(QueueItem { + bound: start_bound, + seq, + state: start, + })); } // ---- 7. Best-first branch-and-bound ----------------------------------- @@ -683,9 +709,7 @@ pub(super) fn select_notes( // Feasibility check: evaluate with change-pool folding let (cost, pool) = evaluate(&state, &ctx); let fee = fee_for_change_pool(&state, &ctx, pool); - if cost != u64::MAX - && is_better_solution(cost, fee, best_cost, best_fee) - { + if cost != u64::MAX && is_better_solution(cost, fee, best_cost, best_fee) { best_cost = cost; best_fee = fee; best_state = state.clone(); @@ -709,7 +733,6 @@ pub(super) fn select_notes( let candidates = top_k_by_local_heuristic(&remaining, &state, budget.beam_width); for (note_idx, note) in candidates { - let child = apply(&state, note_idx, note); let child_bound = lower_bound(&child, &ctx); @@ -726,7 +749,11 @@ pub(super) fn select_notes( seen.insert(key, child_bound); seq = seq.saturating_add(1); - heap.push(Reverse(QueueItem { bound: child_bound, seq, state: child })); + heap.push(Reverse(QueueItem { + bound: child_bound, + seq, + state: child, + })); } } @@ -737,7 +764,11 @@ pub(super) fn select_notes( let fee = best_fee; // Gather inputs and per-pool indices - let inputs: Vec = best_state.selected.iter().map(|&idx| ctx.notes[idx].clone()).collect(); + let inputs: Vec = best_state + .selected + .iter() + .map(|&idx| ctx.notes[idx].clone()) + .collect(); let mut per_pool_indices: [Vec; N_POOLS] = Default::default(); for &idx in &best_state.selected { @@ -764,18 +795,61 @@ mod tests { #[test] fn test_select_notes_basic() { let notes = vec![ - Note { pool: 1, amount: 120_000, pool_index: 0, asset_index: 0 }, - Note { pool: 1, amount: 80_000, pool_index: 1, asset_index: 0 }, - Note { pool: 1, amount: 30_000, pool_index: 2, asset_index: 0 }, - Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, - Note { pool: 2, amount: 15_000, pool_index: 1, asset_index: 0 }, - Note { pool: 3, amount: 60_000, pool_index: 0, asset_index: 0 }, - Note { pool: 0, amount: 500_000, pool_index: 0, asset_index: 0 }, + Note { + pool: 1, + amount: 120_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 1, + amount: 80_000, + pool_index: 1, + asset_index: 0, + }, + Note { + pool: 1, + amount: 30_000, + pool_index: 2, + asset_index: 0, + }, + Note { + pool: 2, + amount: 200_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 2, + amount: 15_000, + pool_index: 1, + asset_index: 0, + }, + Note { + pool: 3, + amount: 60_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 0, + amount: 500_000, + pool_index: 0, + asset_index: 0, + }, ]; let outputs = vec![ - Output { pool: 1, amount: 150_000, asset_index: 0 }, - Output { pool: 2, amount: 100_000, asset_index: 0 }, + Output { + pool: 1, + amount: 150_000, + asset_index: 0, + }, + Output { + pool: 2, + amount: 100_000, + asset_index: 0, + }, ]; let f_unit = 5_000u64; @@ -789,7 +863,9 @@ mod tests { assert!( total_input >= total_output + sel.fee, "total input {} should cover outputs {} + fee {}", - total_input, total_output, sel.fee + total_input, + total_output, + sel.fee ); // Fee should be positive @@ -803,11 +879,30 @@ mod tests { fn test_select_notes_dust_filtered() { // Notes below f_unit (5000) should be filtered out let notes = vec![ - Note { pool: 1, amount: 120, pool_index: 0, asset_index: 0 }, // dust - Note { pool: 1, amount: 4_000, pool_index: 1, asset_index: 0 }, // dust - Note { pool: 2, amount: 1_000_000, pool_index: 0, asset_index: 0 }, // only usable note + Note { + pool: 1, + amount: 120, + pool_index: 0, + asset_index: 0, + }, // dust + Note { + pool: 1, + amount: 4_000, + pool_index: 1, + asset_index: 0, + }, // dust + Note { + pool: 2, + amount: 1_000_000, + pool_index: 0, + asset_index: 0, + }, // only usable note ]; - let outputs = vec![Output { pool: 2, amount: 500_000, asset_index: 0 }]; + let outputs = vec![Output { + pool: 2, + amount: 500_000, + asset_index: 0, + }]; let f_unit = 5_000u64; let sel = select_notes(¬es, &outputs, f_unit, false, false, 0) @@ -821,29 +916,61 @@ mod tests { #[test] fn test_zsa_note_below_fee_unit_is_not_dust() { let notes = vec![ - Note { pool: 2, amount: 1, pool_index: 0, asset_index: 1 }, - Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, + Note { + pool: 2, + amount: 1, + pool_index: 0, + asset_index: 1, + }, + Note { + pool: 2, + amount: 100_000, + pool_index: 1, + asset_index: 0, + }, ]; - let outputs = vec![Output { pool: 2, amount: 1, asset_index: 1 }]; + let outputs = vec![Output { + pool: 2, + amount: 1, + asset_index: 1, + }]; let sel = select_notes(¬es, &outputs, 5_000, false, false, 0) .expect("sub-fee-unit ZSA note should remain selectable"); - assert!( - sel.inputs - .iter() - .any(|note| note.asset_index == 1 && note.amount == 1) - ); + assert!(sel + .inputs + .iter() + .any(|note| note.asset_index == 1 && note.amount == 1)); } #[test] fn test_select_notes_recipient_pays_fee() { let notes = vec![ - Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, - Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, - Note { pool: 2, amount: 50_000, pool_index: 2, asset_index: 0 }, + Note { + pool: 2, + amount: 200_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 2, + amount: 100_000, + pool_index: 1, + asset_index: 0, + }, + Note { + pool: 2, + amount: 50_000, + pool_index: 2, + asset_index: 0, + }, ]; - let outputs = vec![Output { pool: 2, amount: 150_000, asset_index: 0 }]; + let outputs = vec![Output { + pool: 2, + amount: 150_000, + asset_index: 0, + }]; let f_unit = 5_000u64; // First recipient has 200_000, fee will be well under that @@ -854,18 +981,45 @@ mod tests { let total_input: u64 = sel.inputs.iter().map(|n| n.amount).sum(); let total_output: u64 = outputs.iter().map(|o| o.amount).sum(); assert!(total_input >= total_output); - assert!(sel.fee <= 200_000, "fee must not exceed first recipient amount"); + assert!( + sel.fee <= 200_000, + "fee must not exceed first recipient amount" + ); } #[test] fn test_select_notes_recipient_pays_fee_too_high() { let notes = vec![ - Note { pool: 2, amount: 200_000, pool_index: 0, asset_index: 0 }, - Note { pool: 2, amount: 100_000, pool_index: 1, asset_index: 0 }, - Note { pool: 1, amount: 300_000, pool_index: 0, asset_index: 0 }, - Note { pool: 0, amount: 500_000, pool_index: 0, asset_index: 0 }, + Note { + pool: 2, + amount: 200_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 2, + amount: 100_000, + pool_index: 1, + asset_index: 0, + }, + Note { + pool: 1, + amount: 300_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 0, + amount: 500_000, + pool_index: 0, + asset_index: 0, + }, ]; - let outputs = vec![Output { pool: 2, amount: 150_000, asset_index: 0 }]; + let outputs = vec![Output { + pool: 2, + amount: 150_000, + asset_index: 0, + }]; let f_unit = 5_000u64; // First recipient only has 1_000 zats — fee will exceed that @@ -875,20 +1029,33 @@ mod tests { // This may or may not find a solution depending on fee structure. // Just verify it doesn't panic. if let Some(sel) = result { - assert!(sel.fee <= 1_000, "if solution found, fee must fit recipient"); + assert!( + sel.fee <= 1_000, + "if solution found, fee must fit recipient" + ); } } #[test] fn test_select_notes_insufficient_funds() { - let notes = vec![ - Note { pool: 2, amount: 10_000, pool_index: 0, asset_index: 0 }, - ]; - let outputs = vec![Output { pool: 2, amount: 1_000_000, asset_index: 0 }]; + let notes = vec![Note { + pool: 2, + amount: 10_000, + pool_index: 0, + asset_index: 0, + }]; + let outputs = vec![Output { + pool: 2, + amount: 1_000_000, + asset_index: 0, + }]; let f_unit = 5_000u64; let result = select_notes(¬es, &outputs, f_unit, false, false, 0); - assert!(result.is_none(), "should return None for insufficient funds"); + assert!( + result.is_none(), + "should return None for insufficient funds" + ); } #[test] @@ -943,11 +1110,30 @@ mod tests { #[test] fn test_zsa_selection_uses_per_asset_fee_as_tiebreaker() { let notes = vec![ - Note { pool: 2, amount: 20_082_510_000, pool_index: 0, asset_index: 0 }, - Note { pool: 2, amount: 200_000_000, pool_index: 1, asset_index: 0 }, - Note { pool: 2, amount: 499_500, pool_index: 2, asset_index: 1 }, + Note { + pool: 2, + amount: 20_082_510_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 2, + amount: 200_000_000, + pool_index: 1, + asset_index: 0, + }, + Note { + pool: 2, + amount: 499_500, + pool_index: 2, + asset_index: 1, + }, ]; - let outputs = vec![Output { pool: 2, amount: 1_000, asset_index: 1 }]; + let outputs = vec![Output { + pool: 2, + amount: 1_000, + asset_index: 1, + }]; let selection = select_notes(¬es, &outputs, 5_000, false, false, 0) .expect("ZSA transfer should be selectable"); diff --git a/rust/src/plugin/db.rs b/rust/src/plugin/db.rs index ab180d4f0..01258939d 100644 --- a/rust/src/plugin/db.rs +++ b/rust/src/plugin/db.rs @@ -11,7 +11,7 @@ pub struct PluginRow { pub author: Option, pub description: Option, pub min_app_version: String, - pub types: String, // JSON array: ["memo"] + pub types: String, // JSON array: ["memo"] pub enabled: bool, pub install_dir: String, pub script: String, diff --git a/rust/src/plugin/mod.rs b/rust/src/plugin/mod.rs index 23e8c061b..5723caa15 100644 --- a/rust/src/plugin/mod.rs +++ b/rust/src/plugin/mod.rs @@ -11,7 +11,7 @@ pub mod db; pub mod rhai_api; use anyhow::{anyhow, bail, Context, Result}; -use rhai::{AST, Dynamic, Engine, Scope}; +use rhai::{Dynamic, Engine, Scope, AST}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::io::Cursor; @@ -22,8 +22,8 @@ use std::sync::OnceLock; use crate::api::coin::Coin; use crate::plugin::db as plugin_db; use crate::plugin::rhai_api::{ - create_sandboxed_engine, extract_prefixes, extract_sections, with_memo_bytes, - ParsedMemoCell, ParsedMemoSection, + create_sandboxed_engine, extract_prefixes, extract_sections, with_memo_bytes, ParsedMemoCell, + ParsedMemoSection, }; // ── AST cache ─────────────────────────────────────────────────────────── @@ -199,9 +199,7 @@ pub async fn parse_memo_with_plugins(c: &Coin, memo_bytes: &[u8]) -> Result = { - PLUGIN_INDEX.lock().unwrap().clone() - }; + let plugins: Vec = { PLUGIN_INDEX.lock().unwrap().clone() }; let plugins = if plugins.is_empty() { refresh_plugin_index(c).await?; PLUGIN_INDEX.lock().unwrap().clone() @@ -263,8 +261,7 @@ pub async fn install_plugin_from_url(c: &Coin, url: &str) -> Result { /// Install a plugin from an archive (zip). Works entirely in memory — no disk writes. pub async fn install_plugin_from_bytes(c: &Coin, archive: &[u8]) -> Result { let cursor = Cursor::new(archive); - let mut zip = - zip::ZipArchive::new(cursor).context("Failed to open plugin archive")?; + let mut zip = zip::ZipArchive::new(cursor).context("Failed to open plugin archive")?; // Read manifest.json from zip let manifest_entry = zip @@ -289,8 +286,8 @@ pub async fn install_plugin_from_bytes(c: &Coin, archive: &[u8]) -> Result RhaiResult { let idx = offset as usize; let guard = CURRENT_MEMO.lock().unwrap(); Ok(if idx + 3 < guard.len() { - u32::from_le_bytes([ - guard[idx], - guard[idx + 1], - guard[idx + 2], - guard[idx + 3], - ]) as i64 + u32::from_le_bytes([guard[idx], guard[idx + 1], guard[idx + 2], guard[idx + 3]]) as i64 } else { 0 }) @@ -346,10 +341,10 @@ mod tests { let engine = create_sandboxed_engine(); // Build a DK00 memo: prefix + from_id(1) + data_len(32u64 LE) + 32 zero bytes let mut data = vec![0u8; 45]; - data[0..4].copy_from_slice(b"DK00"); // prefix - data[4] = 1; // from_id = 1 + data[0..4].copy_from_slice(b"DK00"); // prefix + data[4] = 1; // from_id = 1 data[5..13].copy_from_slice(&32u64.to_le_bytes()); // data_len = 32 - // data[13..45] = zeros (VerifyingKey placeholder) + // data[13..45] = zeros (VerifyingKey placeholder) let script = r#" fn get_prefixes() { return ["444b3030"]; } @@ -373,8 +368,8 @@ mod tests { assert_eq!(sections.len(), 1); assert_eq!(sections[0].title, "DKG Message"); assert_eq!(sections[0].rows[0][1].value, "DKG Round 0"); - assert_eq!(sections[0].rows[1][1].value, "1"); // from_id - assert_eq!(sections[0].rows[2][1].value, "32"); // data_len + assert_eq!(sections[0].rows[1][1].value, "1"); // from_id + assert_eq!(sections[0].rows[2][1].value, "32"); // data_len }); } } diff --git a/rust/src/recover.rs b/rust/src/recover.rs index bd650c1dc..bf7a9ba59 100644 --- a/rust/src/recover.rs +++ b/rust/src/recover.rs @@ -2,9 +2,7 @@ use anyhow::Result; use bip39::Mnemonic; use sapling_crypto::zip32::ExtendedSpendingKey; use tracing::debug; -use zcash_protocol::{ - consensus::{MainNetwork, NetworkConstants}, -}; +use zcash_protocol::consensus::{MainNetwork, NetworkConstants}; use hmac::{Hmac, Mac}; use sha2::{Sha256, Sha512}; @@ -193,13 +191,16 @@ mod tests { // let s = m.to_seed(""); let s = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; let m = ledger_derivation_from_seed(s)?; - let k = derive_hardened_ed25519(&m, &[ - 0x8000_0000, - 0x8000_0001, - 0x8000_0002, - 0x8000_0002, - 0x8000_0000 | 1000000000, - ])?; + let k = derive_hardened_ed25519( + &m, + &[ + 0x8000_0000, + 0x8000_0001, + 0x8000_0002, + 0x8000_0002, + 0x8000_0000 | 1000000000, + ], + )?; println!("{}", hex::encode(k.key)); println!("{}", hex::encode(k.chain_code)); diff --git a/rust/src/sync.rs b/rust/src/sync.rs index e8c6e1a1d..153dd92f5 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -27,10 +27,7 @@ use crate::{ store_account_transparent_addr, }, lwd::CompactBlock, - warp::{ - legacy::CommitmentTreeFrontier, - sync::warp_sync, - }, + warp::{legacy::CommitmentTreeFrontier, sync::warp_sync}, }; use bincode::config; use sqlx::pool::PoolConnection; @@ -44,8 +41,8 @@ use zcash_protocol::consensus::{NetworkUpgrade, Parameters}; pub const DEFAULT_ACTIONS_PER_SYNC: u32 = 10000u32; pub const DEFAULT_TRANSPARENT_LIMIT: u32 = 100u32; -pub use zcash_trees::types::{BlockHeader, Issuance, Note, Transaction, WarpSyncMessage, UTXO}; pub use zcash_trees::types::SyncError; +pub use zcash_trees::types::{BlockHeader, Issuance, Note, Transaction, WarpSyncMessage, UTXO}; pub struct NoteExtended { pub id: u32, @@ -128,7 +125,12 @@ pub async fn synchronize_impl + Send + 'static>( .fetch_one(&mut *connection) .await?; if let (Some(account), Some(height)) = r { - debug!("Account {} - current DB sync height: {}, next sync height: {}", account, height, height + 1); + debug!( + "Account {} - current DB sync height: {}, next sync height: {}", + account, + height, + height + 1 + ); account_heights.insert(account, height + 1); let (use_internal,): (bool,) = @@ -141,14 +143,20 @@ pub async fn synchronize_impl + Send + 'static>( // Check which pools this account has let t_count: (i64,) = sqlx::query_as( - "SELECT COUNT(*) FROM transparent_address_accounts WHERE account = ?" - ).bind(account).fetch_one(&mut *connection).await?; + "SELECT COUNT(*) FROM transparent_address_accounts WHERE account = ?", + ) + .bind(account) + .fetch_one(&mut *connection) + .await?; debug!( "Account {} - has {} transparent addresses, use_internal={}", account, t_count.0, use_internal ); } else { - debug!("Account {} - NO sync_heights entry found, will be skipped", account); + debug!( + "Account {} - NO sync_heights entry found, will be skipped", + account + ); } } @@ -156,7 +164,10 @@ pub async fn synchronize_impl + Send + 'static>( let mut unique_heights: Vec = account_heights.values().cloned().collect(); unique_heights.sort_unstable(); unique_heights.dedup(); - debug!("Unique sync start heights for accounts: {:?}", unique_heights); + debug!( + "Unique sync start heights for accounts: {:?}", + unique_heights + ); let (tx_progress, mut rx_progress) = channel::(1); @@ -191,7 +202,12 @@ pub async fn synchronize_impl + Send + 'static>( continue; } - debug!("Syncing accounts {:?} from height {} to {}", accounts_to_sync.iter().map(|(a, _)| a).collect::>(), start_height, end_height); + debug!( + "Syncing accounts {:?} from height {} to {}", + accounts_to_sync.iter().map(|(a, _)| a).collect::>(), + start_height, + end_height + ); let pool = c.get_pool()?; // Update the sync heights for these accounts @@ -530,7 +546,11 @@ pub async fn get_tree_state( network: &Network, client: &mut Client, height: u32, -) -> Result<(CommitmentTreeFrontier, CommitmentTreeFrontier, CommitmentTreeFrontier)> { +) -> Result<( + CommitmentTreeFrontier, + CommitmentTreeFrontier, + CommitmentTreeFrontier, +)> { let min_height: u32 = network .activation_height(zcash_protocol::consensus::NetworkUpgrade::Sapling) .unwrap() @@ -626,14 +646,12 @@ fn resolve_diversifier_index( diversifier: &[u8], ) -> Option { match pool { - 1 => cache - .sapling - .get(&account) - .and_then(|keys| crate::db::resolve_sapling_diversifier_index(&keys.dfvk, scope, diversifier)), - 2 => cache - .orchard - .get(&account) - .and_then(|keys| crate::db::resolve_orchard_diversifier_index(&keys.fvk, scope, diversifier)), + 1 => cache.sapling.get(&account).and_then(|keys| { + crate::db::resolve_sapling_diversifier_index(&keys.dfvk, scope, diversifier) + }), + 2 => cache.orchard.get(&account).and_then(|keys| { + crate::db::resolve_orchard_diversifier_index(&keys.fvk, scope, diversifier) + }), _ => None, } } @@ -688,7 +706,9 @@ pub async fn shielded_sync( let mut new_messages = vec![]; mem::swap(&mut new_messages, &mut messages); for msg in new_messages { - match handle_message(&network, &mut db_tx, msg, &tx_progress, &key_cache).await { + match handle_message(&network, &mut db_tx, msg, &tx_progress, &key_cache) + .await + { Ok(_) => {} Err(e) => { info!("ERROR HANDLING MESSAGE: {:?}", e); diff --git a/rust/src/vault/crypto.rs b/rust/src/vault/crypto.rs index 12416c017..79fba9fb9 100644 --- a/rust/src/vault/crypto.rs +++ b/rust/src/vault/crypto.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; use std::io::{Read, Write}; -use anyhow::{Result, anyhow}; +use anyhow::{anyhow, Result}; use argon2::{Algorithm, Argon2, Params, Version}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use chacha20poly1305::{ChaCha20Poly1305, Key, KeyInit, Nonce, aead::Aead}; +use chacha20poly1305::{aead::Aead, ChaCha20Poly1305, Key, KeyInit, Nonce}; use rand_core::{OsRng, RngCore}; use x25519_dalek::{PublicKey, StaticSecret}; @@ -38,25 +38,31 @@ impl AccountPayload { let name_len = r.read_u16::()? as usize; let mut name_buf = vec![0u8; name_len]; r.read_exact(&mut name_buf)?; - let name = String::from_utf8(name_buf) - .map_err(|e| anyhow!("Invalid name: {}", e))?; + let name = String::from_utf8(name_buf).map_err(|e| anyhow!("Invalid name: {}", e))?; let mut entropy = [0u8; 32]; r.read_exact(&mut entropy)?; let aindex = r.read_u32::()?; let use_internal = r.read_u8()? != 0; let birth_height = r.read_u32::()?; - Ok(Self { timestamp, name, entropy, aindex, use_internal, birth_height }) + Ok(Self { + timestamp, + name, + entropy, + aindex, + use_internal, + birth_height, + }) } } enum LogEntry { Init { - pk: [u8; 32], // X25519 public key, plaintext + pk: [u8; 32], // X25519 public key, plaintext master_key_protected_sk: [u8; 60], // nonce(12) || ciphertext+tag(48), ChaCha20-Poly1305(SK, MasterKey) - argon2_salt: [u8; 16], // random salt for Argon2id, generated at initialization + argon2_salt: [u8; 16], // random salt for Argon2id, generated at initialization }, AddDevice { - device_id: [u8; 20], // RIPEMD-160 hash, stable per (device, app) pair + device_id: [u8; 20], // RIPEMD-160 hash, stable per (device, app) pair prf_key_protected_sk: [u8; 60], // nonce(12) || ciphertext+tag(48), ChaCha20-Poly1305(SK, PRFKey) }, Account { @@ -73,18 +79,29 @@ impl LogEntry { /// Account: type(1) | len(2 BE) | ephemeral_pk(32) | nonce(12) | ciphertext(var) fn write_to(&self, mut w: W) -> Result<()> { match self { - LogEntry::Init { pk, master_key_protected_sk, argon2_salt } => { + LogEntry::Init { + pk, + master_key_protected_sk, + argon2_salt, + } => { w.write_u8(0)?; w.write_all(pk)?; w.write_all(master_key_protected_sk)?; w.write_all(argon2_salt)?; } - LogEntry::AddDevice { device_id, prf_key_protected_sk } => { + LogEntry::AddDevice { + device_id, + prf_key_protected_sk, + } => { w.write_u8(1)?; w.write_all(device_id)?; w.write_all(prf_key_protected_sk)?; } - LogEntry::Account { ephemeral_pk, nonce, ciphertext } => { + LogEntry::Account { + ephemeral_pk, + nonce, + ciphertext, + } => { w.write_u8(2)?; w.write_u16::((32 + 12 + ciphertext.len()) as u16)?; w.write_all(ephemeral_pk)?; @@ -105,14 +122,21 @@ impl LogEntry { r.read_exact(&mut master_key_protected_sk)?; let mut argon2_salt = [0u8; 16]; r.read_exact(&mut argon2_salt)?; - Ok(LogEntry::Init { pk, master_key_protected_sk, argon2_salt }) + Ok(LogEntry::Init { + pk, + master_key_protected_sk, + argon2_salt, + }) } 1 => { let mut device_id = [0u8; 20]; r.read_exact(&mut device_id)?; let mut prf_key_protected_sk = [0u8; 60]; r.read_exact(&mut prf_key_protected_sk)?; - Ok(LogEntry::AddDevice { device_id, prf_key_protected_sk }) + Ok(LogEntry::AddDevice { + device_id, + prf_key_protected_sk, + }) } 2 => { let payload_len = (r.read_u16::()?) as usize; @@ -123,7 +147,11 @@ impl LogEntry { let ct_len = payload_len - 32 - 12; let mut ciphertext = vec![0u8; ct_len]; r.read_exact(&mut ciphertext)?; - Ok(LogEntry::Account { ephemeral_pk, nonce, ciphertext }) + Ok(LogEntry::Account { + ephemeral_pk, + nonce, + ciphertext, + }) } _ => Err(anyhow!("Invalid LogEntry tag: {}", tag)), } @@ -136,10 +164,12 @@ fn derive_key_from_password(password: &str, salt: &[u8; 16]) -> Result<[u8; 32]> 3, // iterations 2, // parallelism Some(32), // output length - ).map_err(|e| anyhow!("Argon2 params failed: {}", e))?; + ) + .map_err(|e| anyhow!("Argon2 params failed: {}", e))?; let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, params); let mut key = [0u8; 32]; - argon2.hash_password_into(password.as_bytes(), salt, &mut key) + argon2 + .hash_password_into(password.as_bytes(), salt, &mut key) .map_err(|e| anyhow!("Argon2 hashing failed: {}", e))?; Ok(key) } @@ -159,7 +189,8 @@ pub fn derive_master_key(password: &str) -> Result> { OsRng.fill_bytes(&mut nonce_bytes); let nonce = Nonce::from_slice(&nonce_bytes); - let ciphertext = cipher.encrypt(nonce, sk.as_bytes() as &[u8]) + let ciphertext = cipher + .encrypt(nonce, sk.as_bytes() as &[u8]) .map_err(|e| anyhow!("Encryption failed: {}", e))?; let mut master_key_protected_sk = [0u8; 60]; @@ -190,9 +221,11 @@ pub fn register_device( let mut cursor = std::io::Cursor::new(init_bytes); let init_entry = LogEntry::read_from(&mut cursor)?; let (master_key_protected_sk, salt) = match &init_entry { - LogEntry::Init { pk: _, master_key_protected_sk, argon2_salt } => { - (*master_key_protected_sk, *argon2_salt) - } + LogEntry::Init { + pk: _, + master_key_protected_sk, + argon2_salt, + } => (*master_key_protected_sk, *argon2_salt), _ => return Err(anyhow!("Expected Init entry")), }; @@ -200,7 +233,8 @@ pub fn register_device( let master_key = derive_key_from_password(master_password, &salt)?; let cipher = ChaCha20Poly1305::new(Key::from_slice(&master_key)); let nonce = Nonce::from_slice(&master_key_protected_sk[..12]); - let sk_bytes = cipher.decrypt(nonce, &master_key_protected_sk[12..] as &[u8]) + let sk_bytes = cipher + .decrypt(nonce, &master_key_protected_sk[12..] as &[u8]) .map_err(|e| anyhow!("Wrong vault password: {}", e))?; // 3. Hash device_id string to 20 bytes (RIPEMD-160) @@ -221,7 +255,8 @@ pub fn register_device( let mut nonce_bytes = [0u8; 12]; OsRng.fill_bytes(&mut nonce_bytes); let nonce = Nonce::from_slice(&nonce_bytes); - let ciphertext = cipher.encrypt(nonce, sk_bytes.as_slice() as &[u8]) + let ciphertext = cipher + .encrypt(nonce, sk_bytes.as_slice() as &[u8]) .map_err(|e| anyhow!("Encryption failed: {}", e))?; let mut prf_key_protected_sk = [0u8; 60]; @@ -229,7 +264,10 @@ pub fn register_device( prf_key_protected_sk[12..].copy_from_slice(&ciphertext); // 6. Create AddDevice entry - let entry = LogEntry::AddDevice { device_id, prf_key_protected_sk }; + let entry = LogEntry::AddDevice { + device_id, + prf_key_protected_sk, + }; let mut buf = Vec::with_capacity(81); entry.write_to(&mut buf)?; Ok(buf) @@ -254,7 +292,8 @@ pub fn encrypt_account(account: AccountPayload, pk: PublicKey) -> Result OsRng.fill_bytes(&mut nonce_bytes); let nonce = Nonce::from_slice(&nonce_bytes); - let ciphertext = cipher.encrypt(nonce, plaintext.as_slice() as &[u8]) + let ciphertext = cipher + .encrypt(nonce, plaintext.as_slice() as &[u8]) .map_err(|e| anyhow!("Encryption failed: {}", e))?; let entry = LogEntry::Account { @@ -271,12 +310,17 @@ pub fn encrypt_account(account: AccountPayload, pk: PublicKey) -> Result pub fn recover(vault_bytes: &[u8], master_password: &str) -> Result> { let entries = parse_entries(vault_bytes)?; - let (_, master_key_protected_sk, salt) = entries.iter().find_map(|e| match e { - LogEntry::Init { pk, master_key_protected_sk, argon2_salt } => { - Some((*pk, *master_key_protected_sk, *argon2_salt)) - } - _ => None, - }).ok_or_else(|| anyhow!("No Init LogEntry found"))?; + let (_, master_key_protected_sk, salt) = entries + .iter() + .find_map(|e| match e { + LogEntry::Init { + pk, + master_key_protected_sk, + argon2_salt, + } => Some((*pk, *master_key_protected_sk, *argon2_salt)), + _ => None, + }) + .ok_or_else(|| anyhow!("No Init LogEntry found"))?; // Derive master key from password + salt let master_key = derive_key_from_password(master_password, &salt)?; @@ -284,7 +328,10 @@ pub fn recover(vault_bytes: &[u8], master_password: &str) -> Result { - decrypt_sk(prf_key.as_bytes(), prf_key_protected_sk).ok() - } - _ => None, - }).ok_or_else(|| anyhow!("No matching device entry found"))?; + let sk_bytes = entries + .iter() + .rev() + .find_map(|e| match e { + LogEntry::AddDevice { + device_id: did, + prf_key_protected_sk, + } if *did == device_id => decrypt_sk(prf_key.as_bytes(), prf_key_protected_sk).ok(), + _ => None, + }) + .ok_or_else(|| anyhow!("No matching device entry found"))?; tracing::info!("Recovered sk via PRF ({} bytes)", sk_bytes.len()); @@ -335,8 +387,8 @@ fn parse_entries(vault_bytes: &[u8]) -> Result> { // Compute frame size based on tag (frame includes the tag byte itself) let frame_size = match tag { - 0 => 109usize, // tag(1) + pk(32) + protected_sk(60) + salt(16) - 1 => 81, // tag(1) + device_id(20) + protected_sk(60) + 0 => 109usize, // tag(1) + pk(32) + protected_sk(60) + salt(16) + 1 => 81, // tag(1) + device_id(20) + protected_sk(60) 2 => { // tag(1) + len(2 BE) + payload(var) if pos + 3 > len { @@ -350,9 +402,7 @@ fn parse_entries(vault_bytes: &[u8]) -> Result> { 3 + payload_len } _ => { - tracing::warn!( - "parse_entries: invalid tag {tag} at offset {pos}, skipping byte" - ); + tracing::warn!("parse_entries: invalid tag {tag} at offset {pos}, skipping byte"); pos += 1; continue; } @@ -390,16 +440,24 @@ fn parse_entries(vault_bytes: &[u8]) -> Result> { fn decrypt_sk(key: &[u8], protected_sk: &[u8; 60]) -> Result> { let cipher = ChaCha20Poly1305::new(Key::from_slice(key)); let nonce = Nonce::from_slice(&protected_sk[..12]); - cipher.decrypt(nonce, &protected_sk[12..] as &[u8]) + cipher + .decrypt(nonce, &protected_sk[12..] as &[u8]) .map_err(|e| anyhow!("Decryption failed: {}", e)) } fn decrypt_accounts(entries: &[LogEntry], sk_bytes: &[u8]) -> Result> { - let sk = StaticSecret::from(<[u8; 32]>::try_from(sk_bytes).map_err(|_| anyhow!("Invalid sk length"))?); + let sk = StaticSecret::from( + <[u8; 32]>::try_from(sk_bytes).map_err(|_| anyhow!("Invalid sk length"))?, + ); let mut deduped: HashMap<([u8; 32], u32), RestoredAccount> = HashMap::new(); for entry in entries { - if let LogEntry::Account { ephemeral_pk, nonce, ciphertext } = entry { + if let LogEntry::Account { + ephemeral_pk, + nonce, + ciphertext, + } = entry + { let ephemeral_pk = PublicKey::from(*ephemeral_pk); let shared_secret = sk.diffie_hellman(&ephemeral_pk); @@ -434,8 +492,13 @@ fn decrypt_accounts(entries: &[LogEntry], sk_bytes: &[u8]) -> Result { pub fn new(io_handler: DartVaultIO) -> Self { - Self { - io_handler, - } + Self { io_handler } } -} \ No newline at end of file +} diff --git a/rust/src/warp/decrypter.rs b/rust/src/warp/decrypter.rs index d609ea6a0..c85803bef 100644 --- a/rust/src/warp/decrypter.rs +++ b/rust/src/warp/decrypter.rs @@ -22,13 +22,13 @@ use orchard::{ note_encryption::{CompactAction, IronwoodDomain, OrchardDomain}, zsa::OrchardZSADomain, }; -use zcash_note_encryption::note_bytes::{NoteBytes, NoteBytesData}; use sapling_crypto::{ note_encryption::{ plaintext_version_is_valid, SaplingDomain, Zip212Enforcement, KDF_SAPLING_PERSONALIZATION, }, SaplingIvk, }; +use zcash_note_encryption::note_bytes::{NoteBytes, NoteBytesData}; use zcash_note_encryption::EphemeralKeyBytes; const COMPACT_NOTE_SIZE: usize = 52; @@ -85,7 +85,8 @@ pub fn try_sapling_decrypt( use zcash_note_encryption::Domain; let pivk = sapling_crypto::keys::PreparedIncomingViewingKey::new(ivk); let d = SaplingDomain::new(zip212_enforcement); - if let Some((note, recipient)) = d.parse_note_plaintext_without_memo_ivk(&pivk, plaintext.as_ref()) + if let Some((note, recipient)) = + d.parse_note_plaintext_without_memo_ivk(&pivk, plaintext.as_ref()) { let cmx = note.cmu(); if cmx.to_bytes() == *co.cmu { @@ -125,12 +126,16 @@ pub fn try_orchard_decrypt( ) -> Result> { let zip212_enforcement = zip212(network, height); let bb = ivk.to_bytes(); - let ivk_bytes: [u8; 32] = bb[32..64].try_into() + let ivk_bytes: [u8; 32] = bb[32..64] + .try_into() .map_err(|_| anyhow::anyhow!("Invalid ivk length"))?; let ivk_fq = Option::::from(Fq::from_repr(ivk_bytes)) .ok_or_else(|| anyhow::anyhow!("Invalid ivk Fq repr"))?; - let epk_bytes: [u8; 32] = ca.ephemeral_key.clone().try_into() + let epk_bytes: [u8; 32] = ca + .ephemeral_key + .clone() + .try_into() .map_err(|_| anyhow::anyhow!("Invalid ephemeral key length"))?; let epk = Option::::from(Point::from_bytes(&epk_bytes)) .ok_or_else(|| anyhow::anyhow!("Invalid ephemeral key bytes"))? @@ -158,7 +163,9 @@ pub fn try_orchard_decrypt( if plaintext[0] == 0x03 { use zcash_note_encryption::Domain; let pivk = orchard::keys::PreparedIncomingViewingKey::new(ivk); - let nullifier_bytes: [u8; 32] = ca.nullifier.clone() + let nullifier_bytes: [u8; 32] = ca + .nullifier + .clone() .try_into() .map_err(|_| anyhow::anyhow!("Invalid nullifier length"))?; let rho = Option::::from(Rho::from_bytes(&nullifier_bytes)) @@ -166,13 +173,13 @@ pub fn try_orchard_decrypt( let note_plaintext = NoteBytesData::<84>::from_slice(&plaintext[..84]) .ok_or_else(|| anyhow::anyhow!("Invalid orchard note plaintext"))?; - let parsed = OrchardZSADomain { rho }.parse_note_plaintext_without_memo_ivk( - &pivk, - note_plaintext.as_ref(), - ); + let parsed = OrchardZSADomain { rho } + .parse_note_plaintext_without_memo_ivk(&pivk, note_plaintext.as_ref()); tracing::debug!( "ZSA parsed result: height={} vout={} is_some={}", - height, vout, parsed.is_some() + height, + vout, + parsed.is_some() ); if let Some((note, recipient)) = parsed { let cmx = ExtractedNoteCommitment::from(note.commitment()); @@ -236,25 +243,33 @@ pub fn try_orchard_decrypt( } use zcash_note_encryption::Domain; let pivk = orchard::keys::PreparedIncomingViewingKey::new(ivk); - let nullifier_bytes: [u8; 32] = ca.nullifier.clone() + let nullifier_bytes: [u8; 32] = ca + .nullifier + .clone() .try_into() .map_err(|_| anyhow::anyhow!("Invalid nullifier length"))?; let rho = Option::::from(Rho::from_bytes(&nullifier_bytes)) .ok_or_else(|| anyhow::anyhow!("Invalid Rho bytes"))?; - let note_ciphertext: [u8; 52] = ca.ciphertext[..52].try_into() + let note_ciphertext: [u8; 52] = ca.ciphertext[..52] + .try_into() .map_err(|_| anyhow::anyhow!("ciphertext too short"))?; - let cmx_bytes: [u8; 32] = ca.cmx.clone() + let cmx_bytes: [u8; 32] = ca + .cmx + .clone() .try_into() .map_err(|_| anyhow::anyhow!("Invalid cmx length"))?; - let ephemeral_key_bytes: [u8; 32] = ca.ephemeral_key.clone() + let ephemeral_key_bytes: [u8; 32] = ca + .ephemeral_key + .clone() .try_into() .map_err(|_| anyhow::anyhow!("Invalid ephemeral key length"))?; let cca = CompactAction::from_parts( Option::::from(Nullifier::from_bytes(&rho.to_bytes())) .ok_or_else(|| anyhow::anyhow!("Invalid nullifier"))?, - Option::::from( - ExtractedNoteCommitment::from_bytes(&cmx_bytes) - ).ok_or_else(|| anyhow::anyhow!("Invalid cmx"))?, + Option::::from(ExtractedNoteCommitment::from_bytes( + &cmx_bytes, + )) + .ok_or_else(|| anyhow::anyhow!("Invalid cmx"))?, EphemeralKeyBytes(ephemeral_key_bytes), note_ciphertext, ); @@ -290,7 +305,11 @@ pub fn try_orchard_decrypt( diversifier: recipient.diversifier().as_array().to_vec(), ivtx, cmx: cmx.to_bytes().to_vec(), - asset_base: if is_zec { vec![] } else { note.asset().to_bytes().to_vec() }, + asset_base: if is_zec { + vec![] + } else { + note.asset().to_bytes().to_vec() + }, ..Note::default() }; return Ok(Some((note, dbn))); diff --git a/rust/src/warp/sync.rs b/rust/src/warp/sync.rs index 4f84584ed..719dde94c 100644 --- a/rust/src/warp/sync.rs +++ b/rust/src/warp/sync.rs @@ -9,10 +9,10 @@ use tracing::debug; use zcash_protocol::consensus::{NetworkUpgrade, Parameters}; use zcash_trees::network::Network; -use orchard::note::AssetBase; use orchard::issuance::auth::IssueValidatingKey; -use orchard::note::AssetId; use orchard::issuance::auth::ZSASchnorr; +use orchard::note::AssetBase; +use orchard::note::AssetId; use crate::{ lwd::CompactBlock, @@ -80,9 +80,7 @@ pub async fn warp_sync( ) .await?; - let ironwood_active = network - .activation_height(NetworkUpgrade::Nu6_3) - .is_some(); + let ironwood_active = network.activation_height(NetworkUpgrade::Nu6_3).is_some(); let ironwood_hasher = OrchardHasher::default(); let mut ironwood_dec = if ironwood_active { Some( @@ -102,9 +100,7 @@ pub async fn warp_sync( None }; - let ironwood_has_keys = ironwood_dec - .as_ref() - .map_or(false, |d| !d.has_no_keys()); + let ironwood_has_keys = ironwood_dec.as_ref().map_or(false, |d| !d.has_no_keys()); if sap_dec.has_no_keys() && orch_dec.has_no_keys() && !ironwood_has_keys { debug!("No keys to sync"); return Ok(()); diff --git a/rust/src/warp/sync/shielded.rs b/rust/src/warp/sync/shielded.rs index 543901616..005dbe125 100644 --- a/rust/src/warp/sync/shielded.rs +++ b/rust/src/warp/sync/shielded.rs @@ -2,20 +2,20 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::mem::swap; -use zcash_trees::network::Network; use anyhow::{Context as _, Result}; use bincode::config::legacy; use futures::TryStreamExt; use rayon::prelude::*; use sqlx::{Row, SqliteConnection}; use tokio::sync::mpsc::Sender; -use tracing::{enabled, debug}; +use tracing::{debug, enabled}; +use zcash_trees::network::Network; -use ::orchard::issuance::auth::{IssueValidatingKey, ZSASchnorr}; -use ::orchard::note::{AssetBase, AssetId}; use crate::lwd::{CompactBlock, CompactIssueNote, CompactTx}; use crate::warp::{Edge, Hasher, Witness, MERKLE_DEPTH}; use crate::Hash32; +use ::orchard::issuance::auth::{IssueValidatingKey, ZSASchnorr}; +use ::orchard::note::{AssetBase, AssetId}; use zcash_trees::types::{Note, Transaction, WarpSyncMessage, UTXO}; pub mod ironwood; @@ -208,7 +208,11 @@ impl Synchronizer

{ }) }); - let mut notes: Vec<(

::Note, Note, &

::NK)> = outputs + let mut notes: Vec<( +

::Note, + Note, + &

::NK, + )> = outputs .flat_map_iter(|(height, ivtx, vout, o)| { self.keys.iter().flat_map(move |(account, scope, ivk, nk)| { P::try_decrypt( @@ -243,7 +247,9 @@ impl Synchronizer

{ let mut note_vout = actions_len; for iss in &tx.issuances { - let desc_hash: [u8; 32] = iss.asset_desc_hash.as_slice() + let desc_hash: [u8; 32] = iss + .asset_desc_hash + .as_slice() .try_into() .map_err(|_| anyhow::anyhow!("Invalid asset_desc_hash length"))?; let ik = IssueValidatingKey::::decode(&iss.ik) @@ -381,7 +387,10 @@ impl Synchronizer

{ if depth == 0 { // Build lookup for issuance cmxs per (height, ivtx) let issuance_cmx_map: std::collections::HashMap<(u32, u32), &[[u8; 32]]> = - issuance_cmxs.iter().map(|(h, i, c)| ((*h, *i), c.as_slice())).collect(); + issuance_cmxs + .iter() + .map(|(h, i, c)| ((*h, *i), c.as_slice())) + .collect(); for cb in blocks.iter() { for (ivtx, vtx) in cb.vtx.iter().enumerate() { diff --git a/rust/src/warp/sync/shielded/orchard.rs b/rust/src/warp/sync/shielded/orchard.rs index 3a77ce292..6fd90c907 100644 --- a/rust/src/warp/sync/shielded/orchard.rs +++ b/rust/src/warp/sync/shielded/orchard.rs @@ -1,3 +1,4 @@ +use crate::keys::ScopeExt; use anyhow::Result; use orchard::{ keys::{FullViewingKey, IncomingViewingKey}, @@ -6,7 +7,6 @@ use orchard::{ Address, Note, }; use sqlx::SqliteConnection; -use crate::keys::ScopeExt; use crate::{ lwd::{CompactIssueNote, CompactOrchardAction, CompactTx}, @@ -98,7 +98,10 @@ impl ShieldedProtocol for OrchardProtocol { issue_note: &CompactIssueNote, asset_base: &AssetBase, ) -> Result> { - let recipient_bytes: [u8; 43] = issue_note.recipient.as_slice().try_into() + let recipient_bytes: [u8; 43] = issue_note + .recipient + .as_slice() + .try_into() .map_err(|_| anyhow::anyhow!("Invalid issuance note recipient length"))?; let parsed_addr = Address::from_raw_address_bytes(&recipient_bytes); if parsed_addr.is_none().into() { @@ -127,7 +130,11 @@ impl ShieldedProtocol for OrchardProtocol { diversifier: our_addr.diversifier().as_array().to_vec(), ivtx, cmx: cmx_bytes.to_vec(), - asset_base: if is_zec { vec![] } else { note.asset().to_bytes().to_vec() }, + asset_base: if is_zec { + vec![] + } else { + note.asset().to_bytes().to_vec() + }, ..types::Note::default() }; Ok(Some((note, dbn))) @@ -145,7 +152,10 @@ fn construct_issuance_note( issue_note: &CompactIssueNote, asset_base: &AssetBase, ) -> Result<(Note, Hash32)> { - let recipient_bytes: [u8; 43] = issue_note.recipient.as_slice().try_into() + let recipient_bytes: [u8; 43] = issue_note + .recipient + .as_slice() + .try_into() .map_err(|_| anyhow::anyhow!("Invalid issuance note recipient length"))?; let addr = Address::from_raw_address_bytes(&recipient_bytes); if addr.is_none().into() { @@ -155,7 +165,10 @@ fn construct_issuance_note( let value = NoteValue::from_raw(issue_note.value); let rho = Rho::from_bytes( - issue_note.rho.as_slice().try_into() + issue_note + .rho + .as_slice() + .try_into() .map_err(|_| anyhow::anyhow!("Invalid issuance note rho length"))?, ); if rho.is_none().into() { @@ -163,7 +176,10 @@ fn construct_issuance_note( } let rho = rho.unwrap(); let rseed = RandomSeed::from_bytes( - issue_note.rseed.as_slice().try_into() + issue_note + .rseed + .as_slice() + .try_into() .map_err(|_| anyhow::anyhow!("Invalid issuance note rseed length"))?, &rho, ); diff --git a/rust/src/warp/sync/shielded/sapling.rs b/rust/src/warp/sync/shielded/sapling.rs index a006e1fc7..74bf12c63 100644 --- a/rust/src/warp/sync/shielded/sapling.rs +++ b/rust/src/warp/sync/shielded/sapling.rs @@ -1,7 +1,7 @@ +use crate::keys::sapling_ivk_nk_for_scope; use anyhow::Result; use sapling_crypto::{zip32::DiversifiableFullViewingKey, Note, NullifierDerivingKey, SaplingIvk}; use sqlx::SqliteConnection; -use crate::keys::sapling_ivk_nk_for_scope; use crate::{ lwd::{CompactSaplingOutput, CompactSaplingSpend, CompactTx}, diff --git a/rust/tests/parse_shield_tx.rs b/rust/tests/parse_shield_tx.rs index 13a2470f8..edc18daab 100644 --- a/rust/tests/parse_shield_tx.rs +++ b/rust/tests/parse_shield_tx.rs @@ -52,7 +52,8 @@ fn parse_shield_tx() { println!("spends: {}", sb.shielded_spends().len()); println!("outputs: {}", sb.shielded_outputs().len()); for (i, out) in sb.shielded_outputs().iter().enumerate() { - println!(" output[{}]: enc_ciphertext_len={}, out_ciphertext_len={}", + println!( + " output[{}]: enc_ciphertext_len={}, out_ciphertext_len={}", i, out.enc_ciphertext().as_ref().len(), out.out_ciphertext().len(), @@ -65,7 +66,10 @@ fn parse_shield_tx() { println!("\n=== Orchard Bundle ==="); if let Some(ob) = tx.orchard_bundle() { - println!("has orchard bundle, value_balance: {:?}", ob.value_balance()); + println!( + "has orchard bundle, value_balance: {:?}", + ob.value_balance() + ); } else { println!("NONE"); } diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 4d84d6391..6edc0b283 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -72,17 +72,33 @@ async fn test_orchard_transfer() { println!("Sender account restored: id={sender_id}"); // -- 3. Sync sender from LWD server to current height -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); println!("Current height: {height}"); synchronize_impl( - (), vec![sender_id], height, 10000, 100, 10000, false, &sender, - ).await.expect("sync sender"); + (), + vec![sender_id], + height, + 10000, + 100, + 10000, + false, + &sender, + ) + .await + .expect("sync sender"); println!("Sender synced to height: {height}"); // -- 4. Check ZEC balance (0=T,1=S,2=O,3=IW) -- - let bal = rlz::api::sync::balance(&sender).await.expect("sender balance"); - println!("ZEC balance: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); + let bal = rlz::api::sync::balance(&sender) + .await + .expect("sender balance"); + println!( + "ZEC balance: T={} S={} O={} IW={}", + bal.0[0], bal.0[1], bal.0[2], bal.0[3] + ); let orchard_bal = bal.0[2]; assert!(orchard_bal > 0, "sender should have Orchard balance"); let send_amount = orchard_bal / 2; @@ -164,13 +180,26 @@ async fn test_orchard_transfer() { .expect("set recipient account"); // Sync recipient account (just needs the UA, no notes needed) - let height = get_current_height(&recipient).await.expect("get current height"); + let height = get_current_height(&recipient) + .await + .expect("get current height"); synchronize_impl( - (), vec![recipient_id], height, 10000, 100, 10000, false, &recipient, - ).await.expect("sync recipient"); + (), + vec![recipient_id], + height, + 10000, + 100, + 10000, + false, + &recipient, + ) + .await + .expect("sync recipient"); println!("Recipient synced"); - let recipient_addresses = get_addresses(ALL_POOLS, &recipient).await.expect("get recipient addresses"); + let recipient_addresses = get_addresses(ALL_POOLS, &recipient) + .await + .expect("get recipient addresses"); let recipient_ua = recipient_addresses.ua.expect("recipient UA"); println!("Recipient UA: {recipient_ua}"); @@ -197,17 +226,25 @@ async fn test_orchard_transfer() { let pczt = rlz::api::pay::prepare(&[pay_recipient], options, &sender) .await .expect("plan O2O transfer"); - assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); + assert!( + pczt.n_spends.iter().sum::() > 0, + "should have spends" + ); println!(" spends: {:?}", pczt.n_spends); let signed = sign_transaction(&pczt, &sender).await.expect("sign"); std::fs::write("/tmp/zsa_postsigned.pczt", &signed.pczt).expect("save postsigned pczt"); let tx_bytes = extract_transaction(&signed).await.expect("extract"); std::fs::write("/tmp/zsa_tx.bin", &tx_bytes).expect("save tx bytes"); - println!("Transfer tx: {} bytes (saved /tmp/zsa_tx.bin)", tx_bytes.len()); + println!( + "Transfer tx: {} bytes (saved /tmp/zsa_tx.bin)", + tx_bytes.len() + ); // -- 11. Broadcast the transfer -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &sender) .await .expect("broadcast transfer"); @@ -215,11 +252,15 @@ async fn test_orchard_transfer() { // -- 12. Wait for at least 1 block to be mined -- println!("Waiting for mining..."); - let start_height = get_current_height(&sender).await.expect("get current height"); + let start_height = get_current_height(&sender) + .await + .expect("get current height"); let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let current = get_current_height(&sender).await.expect("get current height"); + let current = get_current_height(&sender) + .await + .expect("get current height"); attempts += 1; if current > start_height { println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); @@ -230,20 +271,47 @@ async fn test_orchard_transfer() { } } - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); synchronize_impl( - (), vec![sender_id, recipient_id], height, 10000, 100, 10000, false, &coin, - ).await.expect("re-sync after transfer"); + (), + vec![sender_id, recipient_id], + height, + 10000, + 100, + 10000, + false, + &coin, + ) + .await + .expect("re-sync after transfer"); // Verify sender balance decreased - let bal = rlz::api::sync::balance(&sender).await.expect("sender balance"); - println!("Sender ZEC balance after transfer: T={} S={} O={} IW={}", bal.0[0], bal.0[1], bal.0[2], bal.0[3]); - assert!(bal.0[2] < orchard_bal, "sender Orchard balance should have decreased"); + let bal = rlz::api::sync::balance(&sender) + .await + .expect("sender balance"); + println!( + "Sender ZEC balance after transfer: T={} S={} O={} IW={}", + bal.0[0], bal.0[1], bal.0[2], bal.0[3] + ); + assert!( + bal.0[2] < orchard_bal, + "sender Orchard balance should have decreased" + ); // Switch to recipient and verify receipt - let recv_bal = rlz::api::sync::balance(&recipient).await.expect("recipient balance"); - println!("Recipient ZEC balance: T={} S={} O={} IW={}", recv_bal.0[0], recv_bal.0[1], recv_bal.0[2], recv_bal.0[3]); - assert!(recv_bal.0[2] >= send_amount, "recipient should have received the ZEC"); + let recv_bal = rlz::api::sync::balance(&recipient) + .await + .expect("recipient balance"); + println!( + "Recipient ZEC balance: T={} S={} O={} IW={}", + recv_bal.0[0], recv_bal.0[1], recv_bal.0[2], recv_bal.0[3] + ); + assert!( + recv_bal.0[2] >= send_amount, + "recipient should have received the ZEC" + ); // Clean up let _ = std::fs::remove_file(&db_path); @@ -303,12 +371,23 @@ async fn test_zsa_issuance() { println!("Account restored: id={account_id}"); // -- 3. Sync from LWD server to current height -- - let height = get_current_height(&account).await.expect("get current height"); + let height = get_current_height(&account) + .await + .expect("get current height"); println!("Current height: {height}"); synchronize_impl( - (), vec![account_id], height, 10000, 100, 10000, false, &account, - ).await.expect("sync"); + (), + vec![account_id], + height, + 10000, + 100, + 10000, + false, + &account, + ) + .await + .expect("sync"); println!("Synced to height: {height}"); // -- 4. Issue a new ZSA asset: 1M units, finalized -- @@ -319,9 +398,9 @@ async fn test_zsa_issuance() { let tx_bytes = rlz::api::issuance::issue_asset( asset_name.clone(), issue_amount, - true, // first_issuance - true, // finalize - None, // desc_hash (computed from name) + true, // first_issuance + true, // finalize + None, // desc_hash (computed from name) account_id, &account, ) @@ -330,7 +409,9 @@ async fn test_zsa_issuance() { println!("Issuance tx: {} bytes", tx_bytes.len()); // -- 5. Broadcast the issuance -- - let height = get_current_height(&account).await.expect("get current height"); + let height = get_current_height(&account) + .await + .expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &account) .await .expect("broadcast issuance"); @@ -338,11 +419,15 @@ async fn test_zsa_issuance() { // -- 6. Wait for at least 1 block to be mined -- println!("Waiting for mining..."); - let start_height = get_current_height(&account).await.expect("get current height"); + let start_height = get_current_height(&account) + .await + .expect("get current height"); let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let current = get_current_height(&account).await.expect("get current height"); + let current = get_current_height(&account) + .await + .expect("get current height"); attempts += 1; if current > start_height { println!("New block mined: {start_height} -> {current} (after {attempts} attempts)"); @@ -354,10 +439,21 @@ async fn test_zsa_issuance() { } // -- 7. Re-sync and verify the asset appears -- - let height = get_current_height(&account).await.expect("get current height"); + let height = get_current_height(&account) + .await + .expect("get current height"); synchronize_impl( - (), vec![account_id], height, 10000, 100, 10000, false, &account, - ).await.expect("re-sync after issuance"); + (), + vec![account_id], + height, + 10000, + 100, + 10000, + false, + &account, + ) + .await + .expect("re-sync after issuance"); println!("Re-synced to height: {height}"); let holdings = rlz::api::zsa::list_zsa_holdings(&account) @@ -447,12 +543,23 @@ async fn test_zsa_transfer() { println!("Sender account restored: id={sender_id}"); // -- 3. Sync sender from LWD server -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); println!("Current height: {height}"); synchronize_impl( - (), vec![sender_id], height, 10000, 100, 10000, false, &sender, - ).await.expect("sync sender"); + (), + vec![sender_id], + height, + 10000, + 100, + 10000, + false, + &sender, + ) + .await + .expect("sync sender"); println!("Sender synced to height: {height}"); // -- 4. Issue a new ZSA asset: 1M units, finalized -- @@ -463,8 +570,8 @@ async fn test_zsa_transfer() { let tx_bytes = rlz::api::issuance::issue_asset( asset_name.clone(), issue_amount, - true, // first_issuance - true, // finalize + true, // first_issuance + true, // finalize None, sender_id, &sender, @@ -474,7 +581,9 @@ async fn test_zsa_transfer() { println!("Issuance tx: {} bytes", tx_bytes.len()); // -- 5. Broadcast issuance -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &sender) .await .expect("broadcast issuance"); @@ -482,12 +591,16 @@ async fn test_zsa_transfer() { // -- 6. Wait for 2 blocks so issuance is well-confirmed -- println!("Waiting for 2 blocks..."); - let start_height = get_current_height(&sender).await.expect("get current height"); + let start_height = get_current_height(&sender) + .await + .expect("get current height"); let target = start_height + 2; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let current = get_current_height(&sender).await.expect("get current height"); + let current = get_current_height(&sender) + .await + .expect("get current height"); attempts += 1; if current >= target { println!("Reached height {current} >= {target} (after {attempts} attempts)"); @@ -499,10 +612,21 @@ async fn test_zsa_transfer() { } // -- 7. Re-sync and verify the asset -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); synchronize_impl( - (), vec![sender_id], height, 10000, 100, 10000, false, &sender, - ).await.expect("re-sync after issuance"); + (), + vec![sender_id], + height, + 10000, + 100, + 10000, + false, + &sender, + ) + .await + .expect("re-sync after issuance"); println!("Re-synced to height: {height}"); let holdings = rlz::api::zsa::list_zsa_holdings(&sender) @@ -513,12 +637,17 @@ async fn test_zsa_transfer() { .iter() .find(|h| h.asset_name == asset_name) .expect("issued asset not found"); - assert!(zsa.balance >= issue_amount, "balance should be at least issued amount"); + assert!( + zsa.balance >= issue_amount, + "balance should be at least issued amount" + ); let zsa_balance = zsa.balance; let zsa_base = zsa.asset_base.clone(); println!( "Sender ZSA: name={} balance={} base={}", - asset_name, zsa_balance, hex::encode(&zsa_base) + asset_name, + zsa_balance, + hex::encode(&zsa_base) ); // -- 8. Restore recipient account -- @@ -546,14 +675,27 @@ async fn test_zsa_transfer() { println!("Recipient account restored: id={recipient_id}"); // Sync recipient (just needs the UA) - let height = get_current_height(&recipient).await.expect("get current height"); + let height = get_current_height(&recipient) + .await + .expect("get current height"); synchronize_impl( - (), vec![recipient_id], height, 10000, 100, 10000, false, &recipient, - ).await.expect("sync recipient"); + (), + vec![recipient_id], + height, + 10000, + 100, + 10000, + false, + &recipient, + ) + .await + .expect("sync recipient"); println!("Recipient synced"); // Get recipient's UA for the transfer - let recipient_addresses = get_addresses(ALL_POOLS, &recipient).await.expect("get recipient addresses"); + let recipient_addresses = get_addresses(ALL_POOLS, &recipient) + .await + .expect("get recipient addresses"); let recipient_ua = recipient_addresses.ua.expect("recipient UA"); println!("Recipient UA: {recipient_ua}"); @@ -582,11 +724,13 @@ async fn test_zsa_transfer() { let pczt = rlz::api::pay::prepare(&[pay_recipient], options, &sender) .await .expect("plan ZSA transfer"); - assert!(pczt.n_spends.iter().sum::() > 0, "should have spends"); + assert!( + pczt.n_spends.iter().sum::() > 0, + "should have spends" + ); println!(" spends: {:?}", pczt.n_spends); - let tx_plan = - rlz::api::pay::to_plan(&pczt, &sender).expect("render ZSA transaction plan"); + let tx_plan = rlz::api::pay::to_plan(&pczt, &sender).expect("render ZSA transaction plan"); assert!( tx_plan .outputs @@ -600,7 +744,9 @@ async fn test_zsa_transfer() { println!("ZSA transfer tx: {} bytes", tx_bytes.len()); // -- 10. Broadcast the ZSA transfer -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); let txid = broadcast_transaction(height, &tx_bytes, &sender) .await .expect("broadcast ZSA transfer"); @@ -608,12 +754,16 @@ async fn test_zsa_transfer() { // -- 11. Wait for 2 blocks -- println!("Waiting for 2 blocks..."); - let start_height = get_current_height(&sender).await.expect("get current height"); + let start_height = get_current_height(&sender) + .await + .expect("get current height"); let target = start_height + 2; let mut attempts = 0; loop { tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let current = get_current_height(&sender).await.expect("get current height"); + let current = get_current_height(&sender) + .await + .expect("get current height"); attempts += 1; if current >= target { println!("Reached height {current} >= {target} (after {attempts} attempts)"); @@ -625,10 +775,21 @@ async fn test_zsa_transfer() { } // -- 12. Re-sync both accounts -- - let height = get_current_height(&sender).await.expect("get current height"); + let height = get_current_height(&sender) + .await + .expect("get current height"); synchronize_impl( - (), vec![sender_id, recipient_id], height, 10000, 100, 10000, false, &sender, - ).await.expect("re-sync after transfer"); + (), + vec![sender_id, recipient_id], + height, + 10000, + 100, + 10000, + false, + &sender, + ) + .await + .expect("re-sync after transfer"); println!("Synced to height: {height}"); // -- 13. Verify sender ZSA balance decreased -- @@ -653,7 +814,9 @@ async fn test_zsa_transfer() { for h in &recv_holdings { println!( " {}: balance={} base={}", - h.asset_name, h.balance, hex::encode(&h.asset_base) + h.asset_name, + h.balance, + hex::encode(&h.asset_base) ); } let recv_zsa = recv_holdings diff --git a/tests/tests/conftest.py b/tests/tests/conftest.py index 095202fcd..9f0cc9593 100644 --- a/tests/tests/conftest.py +++ b/tests/tests/conftest.py @@ -42,9 +42,7 @@ def seed(): @pytest.fixture(scope="session") def zkool_binary(): """Path to zkool_graphql binary.""" - return os.path.join( - os.path.dirname(__file__), "..", "..", "target", "release", "zkool_graphql" - ) + return os.path.join(os.path.dirname(__file__), "..", "..", "target", "release", "zkool_graphql") @pytest.fixture diff --git a/tests/tests/dkg.py b/tests/tests/dkg.py index 998942b51..4fdc07eb0 100644 --- a/tests/tests/dkg.py +++ b/tests/tests/dkg.py @@ -56,9 +56,12 @@ def start(self, zkool_binary: str, remove_db=True): self.process = subprocess.Popen( [ zkool_binary, - "-d", self.db_path, - "-p", str(self.port), - "-l", self.lwd_url, + "-d", + self.db_path, + "-p", + str(self.port), + "-l", + self.lwd_url, ], stdout=open(log_path, "w"), stderr=subprocess.STDOUT, diff --git a/tests/tests/test_account_management.py b/tests/tests/test_account_management.py index 48d8bf31a..04fb521e7 100644 --- a/tests/tests/test_account_management.py +++ b/tests/tests/test_account_management.py @@ -116,7 +116,7 @@ def _dump_log(): result = await client.execute_async( GraphQLRequest( edit_account_mutation, - variable_values={"account": test_account_id, "name": "RenamedAccount"} + variable_values={"account": test_account_id, "name": "RenamedAccount"}, ) ) assert result["editAccount"] == True, "editAccount should return true" @@ -139,7 +139,9 @@ def _dump_log(): ) accounts = result["accounts"] assert len(accounts) == 1 - assert accounts[0]["name"] == "RenamedAccount", f"Expected 'RenamedAccount', got '{accounts[0]['name']}'" + assert accounts[0]["name"] == "RenamedAccount", ( + f"Expected 'RenamedAccount', got '{accounts[0]['name']}'" + ) print("✓ Verified name change via accounts query") print("\n=== Step 4: Send funds to test account to generate notes ===") @@ -175,8 +177,8 @@ def _dump_log(): variable_values={ "account": funding_id, "address": test_address, - "amount": "0.05" - } + "amount": "0.05", + }, ) ) txid1 = result["pay"] @@ -213,7 +215,9 @@ def _dump_log(): print(f"Found {len(notes)} notes for test account") assert len(notes) >= 1, "Should have at least one note" for note in notes[:3]: - print(f" - Note ID: {note['id']}, Value: {note['value']} ZEC, Pool: {note['pool']}, Scope: {note['scope']}") + print( + f" - Note ID: {note['id']}, Value: {note['value']} ZEC, Pool: {note['pool']}, Scope: {note['scope']}" + ) assert notes[0]["value"] == "0.05000000", f"Expected 0.05 ZEC, got {notes[0]['value']}" print("\n=== Step 6: Test memos_by_transaction query ===") @@ -243,7 +247,9 @@ def _dump_log(): """ ) result = await client.execute_async( - GraphQLRequest(memos_query, variable_values={"account": test_account_id, "tx": tx_id}) + GraphQLRequest( + memos_query, variable_values={"account": test_account_id, "tx": tx_id} + ) ) memos = result["memosByTransaction"] print(f"Found {len(memos)} memos for transaction {tx_id}") @@ -285,8 +291,8 @@ def _dump_log(): "account": test_account_id, "address": receiver_address, "amount": "0.025", - "memo": "Test memo for account management" - } + "memo": "Test memo for account management", + }, ) ) txid2 = result["pay"] @@ -310,8 +316,7 @@ def _dump_log(): receiver_tx_id = receiver_txs[0]["id"] result = await client.execute_async( GraphQLRequest( - memos_query, - variable_values={"account": receiver_id, "tx": receiver_tx_id} + memos_query, variable_values={"account": receiver_id, "tx": receiver_tx_id} ) ) memos = result["memosByTransaction"] @@ -346,7 +351,9 @@ def _dump_log(): ) reset_height = result["accounts"][0]["height"] print(f"Height after reset: {reset_height}") - assert reset_height < original_height, f"Height should be lower after reset, was {original_height}, now {reset_height}" + assert reset_height < original_height, ( + f"Height should be lower after reset, was {original_height}, now {reset_height}" + ) print("\n=== Step 9: Re-sync account after reset ===") await client.execute_async( @@ -374,7 +381,9 @@ def _dump_log(): print("✓ Deleted receiver account") # Verify account is deleted - result = await client.execute_async(GraphQLRequest(gql("query { accounts { id name } }"))) + result = await client.execute_async( + GraphQLRequest(gql("query { accounts { id name } }")) + ) accounts = result["accounts"] account_names = [a["name"] for a in accounts] assert "Receiver" not in account_names, "Receiver account should be deleted" diff --git a/tests/tests/test_dkg.py b/tests/tests/test_dkg.py index 57acf1f7a..cbfde0bff 100644 --- a/tests/tests/test_dkg.py +++ b/tests/tests/test_dkg.py @@ -44,6 +44,7 @@ async def cleanup(): try: from utils import kill_existing_zkool_processes + await kill_existing_zkool_processes() print("=== Setting up 3-out-of-3 FROST DKG Test ===") @@ -138,7 +139,9 @@ async def cleanup(): """ ) result = await participant.execute( - GraphQLRequest(address_query, variable_values={"account": participant.funding_account}) + GraphQLRequest( + address_query, variable_values={"account": participant.funding_account} + ) ) participant.funding_address = result["addressByAccount"]["ironwood"] @@ -175,9 +178,7 @@ async def cleanup(): print("\n=== Step 4: Fund each participant's funding address ===") async with gql_client_factory(graphql_url) as client: - recipients = [ - {"address": p.funding_address, "amount": "0.01"} for p in participants - ] + recipients = [{"address": p.funding_address, "amount": "0.01"} for p in participants] pay_mutation = gql( """ @@ -212,7 +213,9 @@ async def cleanup(): ) for i, participant in enumerate(participants, 1): await participant.execute( - GraphQLRequest(sync_mutation, variable_values={"account": participant.funding_account}) + GraphQLRequest( + sync_mutation, variable_values={"account": participant.funding_account} + ) ) print(f"Synchronized participant {i} funding account") @@ -228,7 +231,9 @@ async def cleanup(): ) for i, participant in enumerate(participants, 1): result = await participant.execute( - GraphQLRequest(balance_query, variable_values={"account": participant.funding_account}) + GraphQLRequest( + balance_query, variable_values={"account": participant.funding_account} + ) ) balance = result["balanceByAccount"]["ironwood"] print(f"Participant {i} funding account balance: {balance}") @@ -249,7 +254,9 @@ async def cleanup(): target_address = participants[j - 1].dkg_address await sender.execute( - GraphQLRequest(set_address_mutation, variable_values={"id": j, "address": target_address}) + GraphQLRequest( + set_address_mutation, variable_values={"id": j, "address": target_address} + ) ) print(f"Participant {i} set address for participant {j}") @@ -266,6 +273,7 @@ async def cleanup(): print(f"Initiated DKG on participant {i}") print("\n=== Step 10: Wait for DKG completion ===") + async def all_dkg_completed(): return all(p.get_frost_account_id() is not None for p in participants) @@ -290,7 +298,9 @@ async def all_dkg_completed(): assert participant.frost_account, f"No FROST account found for participant {i}" result = await participant.execute( - GraphQLRequest(address_query, variable_values={"account": participant.frost_account}) + GraphQLRequest( + address_query, variable_values={"account": participant.frost_account} + ) ) frost_address = result["addressByAccount"]["ironwood"] print(f"Participant {i} shared address: {frost_address}") @@ -312,7 +322,9 @@ async def all_dkg_completed(): } """ ) - await client.execute_async(GraphQLRequest(sync_mutation, variable_values={"account": main_wallet})) + await client.execute_async( + GraphQLRequest(sync_mutation, variable_values={"account": main_wallet}) + ) balance_query = gql( """ @@ -341,7 +353,11 @@ async def all_dkg_completed(): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": main_wallet, "address": shared_address, "amount": "0.1"}, + variable_values={ + "account": main_wallet, + "address": shared_address, + "amount": "0.1", + }, ) ) txid = result["pay"] @@ -364,7 +380,9 @@ async def all_dkg_completed(): ) for i, participant in enumerate(participants, 1): await participant.execute( - GraphQLRequest(sync_mutation, variable_values={"account": participant.frost_account}) + GraphQLRequest( + sync_mutation, variable_values={"account": participant.frost_account} + ) ) print(f"Synchronized participant {i} FROST account") @@ -380,7 +398,9 @@ async def all_dkg_completed(): ) for i, participant in enumerate(participants, 1): result = await participant.execute( - GraphQLRequest(balance_query, variable_values={"account": participant.frost_account}) + GraphQLRequest( + balance_query, variable_values={"account": participant.frost_account} + ) ) final_balance = result["balanceByAccount"]["ironwood"] print(f"Participant {i} FROST balance: {final_balance}") diff --git a/tests/tests/test_frost.py b/tests/tests/test_frost.py index bba84c911..a53cdd943 100644 --- a/tests/tests/test_frost.py +++ b/tests/tests/test_frost.py @@ -41,6 +41,7 @@ async def cleanup(): try: from utils import kill_existing_zkool_processes + await kill_existing_zkool_processes() print("=== Setting up 3-out-of-3 FROST SIGN Test ===") @@ -65,6 +66,7 @@ async def cleanup(): default_participant = DkgParticipant(DEFAULT_PORT, default_db, LWD_URL) default_participant.start(zkool_binary) import asyncio + await asyncio.sleep(2) print("\n=== Step 1: Start participant instances ===") @@ -159,8 +161,8 @@ async def cleanup(): variable_values={ "account": coordinator_frost_account, "address": receiver_address, - "amount": "0.05" - } + "amount": "0.05", + }, ) ) pczt = result["prepareSend"] @@ -193,8 +195,8 @@ async def cleanup(): "account": frost_account, "coordinator": 2, "funding": funding_account, - "pczt": pczt - } + "pczt": pczt, + }, ) ) sign_result = result["frostSign"] diff --git a/tests/tests/test_jwt.py b/tests/tests/test_jwt.py index 8a7e6cc13..29d53713c 100644 --- a/tests/tests/test_jwt.py +++ b/tests/tests/test_jwt.py @@ -27,14 +27,13 @@ def generate_jwt_keypair(): private_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, - encryption_algorithm=serialization.NoEncryption() - ).decode('utf-8') + encryption_algorithm=serialization.NoEncryption(), + ).decode("utf-8") # Serialize public key to PEM format (SubjectPublicKeyInfo) public_pem = public_key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo - ).decode('utf-8') + encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo + ).decode("utf-8") return private_pem, public_pem @@ -105,9 +104,7 @@ def create_jwt_token(private_pem: str, account_id: int) -> str: from cryptography.hazmat.primitives import serialization private_key = serialization.load_pem_private_key( - private_pem.encode('utf-8'), - password=None, - backend=default_backend() + private_pem.encode("utf-8"), password=None, backend=default_backend() ) # Sign with ES256 @@ -147,9 +144,12 @@ async def start_server(with_jwt=False): cmd = [ zkool_binary, - "-d", DB_PATH, - "-p", str(PORT), - "-l", lwd_url, + "-d", + DB_PATH, + "-p", + str(PORT), + "-l", + lwd_url, ] if with_jwt: cmd.extend(["-j", JWT_KEY_PATH]) @@ -326,7 +326,11 @@ async def start_server(with_jwt=False): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": admin_id, "address": account1_address, "amount": "0.05"} + variable_values={ + "account": admin_id, + "address": account1_address, + "amount": "0.05", + }, ) ) txid = result["pay"] @@ -413,7 +417,11 @@ async def start_server(with_jwt=False): await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": admin_id, "address": account2_address, "amount": "0.05"} + variable_values={ + "account": admin_id, + "address": account2_address, + "amount": "0.05", + }, ) ) height_before = await get_current_height(client) @@ -433,7 +441,11 @@ async def start_server(with_jwt=False): result = await jwt1_client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": account1_id, "address": account2_address, "amount": "0.025"} + variable_values={ + "account": account1_id, + "address": account2_address, + "amount": "0.025", + }, ) ) txid = result["pay"] @@ -457,7 +469,11 @@ async def start_server(with_jwt=False): result = await no_jwt_client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": account1_id, "address": account2_address, "amount": "0.025"} + variable_values={ + "account": account1_id, + "address": account2_address, + "amount": "0.025", + }, ) ) print(f"ERROR: Should not be able to send without JWT!") @@ -471,7 +487,11 @@ async def start_server(with_jwt=False): result = await jwt2_client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": account1_id, "address": account2_address, "amount": "0.025"} + variable_values={ + "account": account1_id, + "address": account2_address, + "amount": "0.025", + }, ) ) print(f"ERROR: Should not be able to send from account 1 using JWT 2!") @@ -542,23 +562,29 @@ async def start(self): async def run_subscription(): try: self.ws = await websockets.connect( - ws_url, - close_timeout=60, - subprotocols=["graphql-ws"] + ws_url, close_timeout=60, subprotocols=["graphql-ws"] ) # Send connection init with JWT init_payload = {"authToken": self.jwt_token} - await self.ws.send(json.dumps({"type": "connection_init", "payload": init_payload})) + await self.ws.send( + json.dumps({"type": "connection_init", "payload": init_payload}) + ) # Wait for connection_ack try: - init_msg = json.loads(await asyncio.wait_for(self.ws.recv(), timeout=5.0)) + init_msg = json.loads( + await asyncio.wait_for(self.ws.recv(), timeout=5.0) + ) if init_msg.get("type") != "connection_ack": - print(f" [Account {self.account_id}] Warning: Expected connection_ack, got: {init_msg}") + print( + f" [Account {self.account_id}] Warning: Expected connection_ack, got: {init_msg}" + ) return except asyncio.TimeoutError: - print(f" [Account {self.account_id}] Warning: No connection_ack received") + print( + f" [Account {self.account_id}] Warning: No connection_ack received" + ) return # Subscribe to account @@ -576,8 +602,8 @@ async def run_subscription(): value } } - """ - } + """, + }, } await self.ws.send(json.dumps(subscription_query)) await asyncio.sleep(1) @@ -602,12 +628,20 @@ async def run_subscription(): if isinstance(payload, dict): if "errors" in payload: for error in payload["errors"]: - print(f" [Account {self.account_id}] Subscription error: {error.get('message', str(error))}") + print( + f" [Account {self.account_id}] Subscription error: {error.get('message', str(error))}" + ) elif "data" in payload: - event_data = payload["data"].get("events") if isinstance(payload["data"], dict) else None + event_data = ( + payload["data"].get("events") + if isinstance(payload["data"], dict) + else None + ) if event_data and isinstance(event_data, dict): self.events.append(event_data) - print(f" [Account {self.account_id}] Event: type={event_data.get('type')}, txid={event_data.get('txid', 'N/A')}") + print( + f" [Account {self.account_id}] Event: type={event_data.get('type')}, txid={event_data.get('txid', 'N/A')}" + ) except (asyncio.TimeoutError, json.JSONDecodeError): continue @@ -639,7 +673,7 @@ async def stop(self): } } """), - variable_values={"account": account2_id} + variable_values={"account": account2_id}, ) ) account2_address = result["newAddresses"]["ironwood"] @@ -662,7 +696,11 @@ async def stop(self): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": account1_id, "address": account2_address, "amount": "0.01"} + variable_values={ + "account": account1_id, + "address": account2_address, + "amount": "0.01", + }, ) ) txid_from_account1 = result["pay"] @@ -691,7 +729,9 @@ async def stop(self): account1_tx_events = [e for e in account1_sub.events if e["type"] == "TX"] print(f"Account 1 (sender) JWT received {len(account1_tx_events)} TX events") - account1_own_events = [e for e in account1_tx_events if not e.get('txid', '').lower().startswith('failed')] + account1_own_events = [ + e for e in account1_tx_events if not e.get("txid", "").lower().startswith("failed") + ] if account1_own_events: print(f" ✓ Account 1 (sender) correctly received their own TX event(s)") @@ -707,7 +747,9 @@ async def stop(self): print(f"Account 2 (receiver) JWT received {len(account2_tx_events)} TX events") if account2_tx_events: - print(f" ERROR: Account 2 should NOT receive TX events for transactions sent TO them!") + print( + f" ERROR: Account 2 should NOT receive TX events for transactions sent TO them!" + ) for e in account2_tx_events: print(f" - txid: {e.get('txid')}, value: {e.get('value')}") assert False, "Account 2 should not receive TX events for incoming transactions!" @@ -726,9 +768,7 @@ async def test_blocked_subscription(jwt_token, account_id): """Try to subscribe to an account we don't have access to.""" try: ws = await websockets.connect( - ws_url, - close_timeout=60, - subprotocols=["graphql-ws"] + ws_url, close_timeout=60, subprotocols=["graphql-ws"] ) init_payload = {"authToken": jwt_token} @@ -749,8 +789,8 @@ async def test_blocked_subscription(jwt_token, account_id): type } } - """ - } + """, + }, } await ws.send(json.dumps(subscription_query)) @@ -765,7 +805,10 @@ async def test_blocked_subscription(jwt_token, account_id): payload = data.get("payload", {}) if "errors" in payload: await ws.close() - return {"blocked": True, "error": payload["errors"][0].get("message")} + return { + "blocked": True, + "error": payload["errors"][0].get("message"), + } except asyncio.TimeoutError: continue @@ -800,9 +843,7 @@ async def collect_subscription_events(jwt_token, account_id, duration): events = [] try: ws = await websockets.connect( - ws_url, - close_timeout=60, - subprotocols=["graphql-ws"] + ws_url, close_timeout=60, subprotocols=["graphql-ws"] ) init_payload = {} @@ -827,8 +868,8 @@ async def collect_subscription_events(jwt_token, account_id, duration): height } } - """ - } + """, + }, } await ws.send(json.dumps(subscription_query)) @@ -870,7 +911,6 @@ async def collect_subscription_events(jwt_token, account_id, duration): else: print(f" Note: No BLOCK events received (events may be delayed)") - print("\n✅ Subscription access control test passed!") print("\n✅ JWT authentication test passed!") diff --git a/tests/tests/test_reorg.py b/tests/tests/test_reorg.py index feef8a1a3..41e276242 100644 --- a/tests/tests/test_reorg.py +++ b/tests/tests/test_reorg.py @@ -39,10 +39,10 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): # Clear mempool to avoid conflicts from previous test runs print("Clearing mempool...") import httpx + async with httpx.AsyncClient() as rpc_client: await rpc_client.post( - rpc_url, - json={"jsonrpc": "2.0", "id": 1, "method": "clearmempool"} + rpc_url, json={"jsonrpc": "2.0", "id": 1, "method": "clearmempool"} ) print("Mempool cleared") @@ -137,7 +137,11 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": funding_id, "address": test_address, "amount": "0.1"} + variable_values={ + "account": funding_id, + "address": test_address, + "amount": "0.1", + }, ) ) txid = result["pay"] @@ -158,6 +162,7 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): # Get block hash via RPC (GraphQL doesn't expose block hashes) import httpx + async with httpx.AsyncClient() as rpc_client: response = await rpc_client.post( rpc_url, @@ -165,8 +170,8 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): "jsonrpc": "2.0", "id": 1, "method": "getblockhash", - "params": [height_before] - } + "params": [height_before], + }, ) block_hash = response.json().get("result") print(f"Block hash at height {height_before}: {block_hash}") @@ -198,7 +203,9 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): balance_before_reorg = result["balanceByAccount"]["ironwood"] print(f"Test account balance before reorg: {balance_before_reorg} ZEC") - assert float(balance_before_reorg) > 0, f"Balance should be > 0, got {balance_before_reorg}" + assert float(balance_before_reorg) > 0, ( + f"Balance should be > 0, got {balance_before_reorg}" + ) print("✓ Balance is > 0 as expected") print("\n=== Step 8: Invalidate block to trigger reorg ===") @@ -214,8 +221,8 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): "jsonrpc": "2.0", "id": 1, "method": "invalidateblock", - "params": [block_hash] - } + "params": [block_hash], + }, ) print(f"Invalidate block response: {response.json()}") # Mine 10 blocks to ensure that the new chain is longer @@ -230,8 +237,7 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): print("Clearing mempool to prevent transaction from being re-included...") async with httpx.AsyncClient() as rpc_client: await rpc_client.post( - rpc_url, - json={"jsonrpc": "2.0", "id": 1, "method": "clearmempool"} + rpc_url, json={"jsonrpc": "2.0", "id": 1, "method": "clearmempool"} ) print("Mempool cleared") @@ -252,8 +258,7 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): print("\n=== Debug: Check transaction status ===") async with httpx.AsyncClient() as rpc_client: response = await rpc_client.post( - rpc_url, - json={"jsonrpc": "2.0", "id": 1, "method": "getrawmempool"} + rpc_url, json={"jsonrpc": "2.0", "id": 1, "method": "getrawmempool"} ) mempool = response.json().get("result", []) print(f"Mempool: {len(mempool)} transactions") @@ -264,7 +269,12 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): response = await rpc_client.post( rpc_url, - json={"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": [txid, 1]} + json={ + "jsonrpc": "2.0", + "id": 1, + "method": "getrawtransaction", + "params": [txid, 1], + }, ) tx_result = response.json() if "result" in tx_result: @@ -282,11 +292,13 @@ async def test_reorg(gql_client_factory, rpc_url, seed, zkool_binary, lwd_url): balance_after_reorg = result["balanceByAccount"]["ironwood"] print(f"Test account balance after reorg: {balance_after_reorg} ZEC") - assert float(balance_after_reorg) == 0, f"Balance should be 0 after reorg, got {balance_after_reorg}" + assert float(balance_after_reorg) == 0, ( + f"Balance should be 0 after reorg, got {balance_after_reorg}" + ) print("✓ Balance is 0 as expected (transaction was in orphaned chain)") print("\n✅ Reorganization test passed!") finally: await stop_zkool_instance(process) - #cleanup_test_files(DB_PATH, LOG_PATH) + # cleanup_test_files(DB_PATH, LOG_PATH) diff --git a/tests/tests/test_subscriptions.py b/tests/tests/test_subscriptions.py index 80cd89f03..1a5686605 100644 --- a/tests/tests/test_subscriptions.py +++ b/tests/tests/test_subscriptions.py @@ -19,7 +19,9 @@ @pytest.mark.asyncio -async def test_websocket_subscriptions(gql_client_factory, rpc_url, seed, zkool_binary, ws_url, lwd_url): +async def test_websocket_subscriptions( + gql_client_factory, rpc_url, seed, zkool_binary, ws_url, lwd_url +): """Test WebSocket subscriptions using raw websockets library.""" if not seed: pytest.skip("SEED not set") @@ -162,11 +164,13 @@ async def subscribe_to_account(account_id): dkgAccount } } - """ - } + """, + }, } await ws.send(json.dumps(subscription_query)) - print(f"Subscription request sent for account {account_id}, id: {subscription_query['id']}") + print( + f"Subscription request sent for account {account_id}, id: {subscription_query['id']}" + ) return subscription_query["id"] # Subscribe to funding account @@ -193,7 +197,9 @@ async def collect_all_events(): event_data = payload["data"].get("events") if event_data: all_events.append(event_data) - print(f"Received event: type={event_data['type']}, height={event_data['height']}, txid={event_data.get('txid', 'N/A')}") + print( + f"Received event: type={event_data['type']}, height={event_data['height']}, txid={event_data.get('txid', 'N/A')}" + ) # Start event collector in background collector_task = asyncio.create_task(collect_all_events()) @@ -219,7 +225,11 @@ async def collect_all_events(): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": funding_id, "address": receiver_address, "amount": "0.01"}, + variable_values={ + "account": funding_id, + "address": receiver_address, + "amount": "0.01", + }, ) ) txid = result["pay"] @@ -233,7 +243,9 @@ async def collect_all_events(): print("All events") for i, event in enumerate(all_events): - print(f" Event {i+1}: type={event['type']}, height={event['height']}, txid={event.get('txid', 'N/A')}") + print( + f" Event {i + 1}: type={event['type']}, height={event['height']}, txid={event.get('txid', 'N/A')}" + ) # Define the query unconfirmed_query = gql( @@ -283,10 +295,14 @@ async def collect_all_events(): await asyncio.sleep(3) # Filter events for funding account - funding_events = [e for e in all_events if e.get("txid") == txid or e.get("type") == "BLOCK"] + funding_events = [ + e for e in all_events if e.get("txid") == txid or e.get("type") == "BLOCK" + ] print(f"Funding account events: {len(funding_events)}") for i, event in enumerate(funding_events): - print(f" Event {i+1}: type={event['type']}, height={event['height']}, txid={event.get('txid', 'N/A')}") + print( + f" Event {i + 1}: type={event['type']}, height={event['height']}, txid={event.get('txid', 'N/A')}" + ) assert len(funding_events) >= 1, "Should receive at least one event" @@ -295,13 +311,19 @@ async def collect_all_events(): block_event = next((e for e in funding_events if e["type"] == "BLOCK"), None) if tx_event: - print(f"✓ Tx event found: txid={tx_event['txid']}, height={tx_event['height']}, value={tx_event['value']}") - assert tx_event["txid"].lower() == txid.lower(), "Tx event txid should match sent txid" + print( + f"✓ Tx event found: txid={tx_event['txid']}, height={tx_event['height']}, value={tx_event['value']}" + ) + assert tx_event["txid"].lower() == txid.lower(), ( + "Tx event txid should match sent txid" + ) if block_event: print(f"✓ Block event found: height={block_event['height']}") # Block height should be >= height_before (may be the same if we received a stale event) - assert block_event["height"] >= height_before, f"Block height should be >= {height_before}, got {block_event['height']}" + assert block_event["height"] >= height_before, ( + f"Block height should be >= {height_before}, got {block_event['height']}" + ) print("\n=== Test 2: Incoming transaction subscription ===") @@ -320,7 +342,11 @@ async def collect_all_events(): result = await client.execute_async( GraphQLRequest( pay_mutation, - variable_values={"account": funding_id, "address": receiver_address, "amount": "0.005"}, + variable_values={ + "account": funding_id, + "address": receiver_address, + "amount": "0.005", + }, ) ) txid2 = result["pay"] @@ -340,7 +366,9 @@ async def collect_all_events(): if receiver_events: incoming_tx = next((e for e in receiver_events if e["type"] == "TX"), None) if incoming_tx: - print(f"✓ Incoming Tx event found: txid={incoming_tx['txid']}, value={incoming_tx['value']}") + print( + f"✓ Incoming Tx event found: txid={incoming_tx['txid']}, value={incoming_tx['value']}" + ) assert incoming_tx["txid"].lower() == txid2.lower() print("\n=== Test 3: Multiple block events ===") @@ -356,26 +384,35 @@ async def collect_all_events(): await mine_blocks(rpc_url, 3) await asyncio.sleep(3) # Give time for blocks to propagate height_after = await get_current_height(client) - print(f"Height after mining: {height_after}, mined: {height_after - height_before} blocks") + print( + f"Height after mining: {height_after}, mined: {height_after - height_before} blocks" + ) # Filter block events from all collected events block_events = [e for e in all_events if e["type"] == "BLOCK"] print(f"Block events received: {len(block_events)}") - assert len(block_events) >= 1, f"Should receive at least 1 block event, got {len(block_events)}" + assert len(block_events) >= 1, ( + f"Should receive at least 1 block event, got {len(block_events)}" + ) for i, block in enumerate(block_events): expected_height = height_before + i + 1 - print(f"Block {i+1}: expected height {expected_height}, got {block['height']}") + print(f"Block {i + 1}: expected height {expected_height}, got {block['height']}") # The last block event should match the final height if i == len(block_events) - 1: - assert block["height"] == height_after, f"Last block height should be {height_after}, got {block['height']}" + assert block["height"] == height_after, ( + f"Last block height should be {height_after}, got {block['height']}" + ) - print(f"✓ Received {len(block_events)} block event(s) (note: not all blocks may generate events due to upstream polling)") + print( + f"✓ Received {len(block_events)} block event(s) (note: not all blocks may generate events due to upstream polling)" + ) if block_events: last_block = block_events[-1] - assert height_before <= last_block["height"] <= height_after, \ + assert height_before <= last_block["height"] <= height_after, ( f"Block height should be between {height_before} and {height_after}, got {last_block['height']}" + ) print(f"✓ Last block event height {last_block['height']} is within expected range") print("\n✅ All subscription tests passed!") diff --git a/tests/tests/test_transactions.py b/tests/tests/test_transactions.py index bb38a85d0..7a5cdf602 100644 --- a/tests/tests/test_transactions.py +++ b/tests/tests/test_transactions.py @@ -171,11 +171,27 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko ) addresses = result["addressByAccount"] print(f"Account 1 addresses:") - print(f" Unified: {addresses['ua'][:50]}..." if addresses['ua'] else " Unified: None") - print(f" Transparent: {addresses['transparent'][:50]}..." if addresses['transparent'] else " Transparent: None") - print(f" Sapling: {addresses['sapling'][:50]}..." if addresses['sapling'] else " Sapling: None") - print(f" Orchard: {addresses['orchard'][:50]}..." if addresses['orchard'] else " Orchard: None") - print(f" Ironwood: {addresses['ironwood'][:50]}..." if addresses['ironwood'] else " Ironwood: None") + print(f" Unified: {addresses['ua'][:50]}..." if addresses["ua"] else " Unified: None") + print( + f" Transparent: {addresses['transparent'][:50]}..." + if addresses["transparent"] + else " Transparent: None" + ) + print( + f" Sapling: {addresses['sapling'][:50]}..." + if addresses["sapling"] + else " Sapling: None" + ) + print( + f" Orchard: {addresses['orchard'][:50]}..." + if addresses["orchard"] + else " Orchard: None" + ) + print( + f" Ironwood: {addresses['ironwood'][:50]}..." + if addresses["ironwood"] + else " Ironwood: None" + ) assert addresses["ironwood"], "Ironwood address should be present" @@ -198,7 +214,9 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko GraphQLRequest(new_addresses_mutation, variable_values={"account": account1_id}) ) new_addresses = result["newAddresses"] - print(f"Generated new addresses for account 1, diversifier index: {new_addresses['diversifierIndex']}") + print( + f"Generated new addresses for account 1, diversifier index: {new_addresses['diversifierIndex']}" + ) assert new_addresses["ironwood"], "New Ironwood address should be present" print("\n=== Step 7: Send transaction from funding to account 1 ===") @@ -220,8 +238,8 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko variable_values={ "account": funding_id, "address": addresses["ironwood"], - "amount": "0.05" - } + "amount": "0.05", + }, ) ) txid = result["pay"] @@ -263,7 +281,9 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko print(f" Orchard: {balance['orchard']} ZEC") print(f" Ironwood: {balance['ironwood']} ZEC") print(f" Total: {balance['total']} ZEC") - assert balance["ironwood"] == "0.05000000", f"Expected 0.05 ZEC in Ironwood, got {balance['ironwood']}" + assert balance["ironwood"] == "0.05000000", ( + f"Expected 0.05 ZEC in Ironwood, got {balance['ironwood']}" + ) print("\n=== Step 9: Test transactions_by_account query ===") transactions_query = gql( @@ -280,7 +300,9 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko """ ) result = await client.execute_async( - GraphQLRequest(transactions_query, variable_values={"account": account1_id, "height": None}) + GraphQLRequest( + transactions_query, variable_values={"account": account1_id, "height": None} + ) ) transactions = result["transactionsByAccount"] print(f"Found {len(transactions)} transactions for account 1") @@ -304,8 +326,7 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko ) result = await client.execute_async( GraphQLRequest( - transaction_by_id_query, - variable_values={"account": account1_id, "txid": txid} + transaction_by_id_query, variable_values={"account": account1_id, "txid": txid} ) ) transaction = result["transactionById"] @@ -328,8 +349,8 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko variable_values={ "account": account1_id, "address": account2_address, - "amount": "0.025" - } + "amount": "0.025", + }, ) ) txid2 = result["pay"] @@ -349,13 +370,17 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko print("\n=== Step 12: Verify transaction history for both accounts ===") result = await client.execute_async( - GraphQLRequest(transactions_query, variable_values={"account": account1_id, "height": None}) + GraphQLRequest( + transactions_query, variable_values={"account": account1_id, "height": None} + ) ) account1_txs = result["transactionsByAccount"] print(f"Account 1 has {len(account1_txs)} transactions") result = await client.execute_async( - GraphQLRequest(transactions_query, variable_values={"account": account2_id, "height": None}) + GraphQLRequest( + transactions_query, variable_values={"account": account2_id, "height": None} + ) ) account2_txs = result["transactionsByAccount"] print(f"Account 2 has {len(account2_txs)} transactions") @@ -364,8 +389,7 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko print("\n=== Step 13: Test transactions_by_account with height filter ===") result = await client.execute_async( GraphQLRequest( - transactions_query, - variable_values={"account": account1_id, "height": 1} + transactions_query, variable_values={"account": account1_id, "height": 1} ) ) all_txs = result["transactionsByAccount"] @@ -376,13 +400,15 @@ async def test_transactions_and_addresses(gql_client_factory, rpc_url, seed, zko result = await client.execute_async( GraphQLRequest( transactions_query, - variable_values={"account": account1_id, "height": current_height - 1} + variable_values={"account": account1_id, "height": current_height - 1}, ) ) filtered_txs = result["transactionsByAccount"] print(f"Transactions from height {current_height - 1}: {len(filtered_txs)}") print(f"All transactions: {len(all_txs)}") - assert len(filtered_txs) <= len(all_txs), "Filtered should have fewer or equal transactions" + assert len(filtered_txs) <= len(all_txs), ( + "Filtered should have fewer or equal transactions" + ) print("\n✅ Transactions and addresses test passed!") diff --git a/tests/tests/test_tx_details.py b/tests/tests/test_tx_details.py index 224cb0a14..353c9536c 100644 --- a/tests/tests/test_tx_details.py +++ b/tests/tests/test_tx_details.py @@ -202,8 +202,8 @@ def _dump_log(): variable_values={ "account": funding_id, "address": account1_address, - "amount": "0.05" - } + "amount": "0.05", + }, ) ) txid1 = result["pay"] @@ -225,8 +225,8 @@ def _dump_log(): variable_values={ "account": account1_id, "address": account2_address, - "amount": "0.025" - } + "amount": "0.025", + }, ) ) txid2 = result["pay"] @@ -277,9 +277,13 @@ def _dump_log(): break assert tx_with_notes is not None, "Should have at least one transaction with notes" - print(f"Transaction {tx_with_notes['txid'][:16]}... has {len(tx_with_notes['notes'])} notes:") + print( + f"Transaction {tx_with_notes['txid'][:16]}... has {len(tx_with_notes['notes'])} notes:" + ) for note in tx_with_notes["notes"]: - print(f" - Note ID: {note['id']}, Value: {note['value']} ZEC, Pool: {note['pool']}, Scope: {note['scope']}") + print( + f" - Note ID: {note['id']}, Value: {note['value']} ZEC, Pool: {note['pool']}, Scope: {note['scope']}" + ) print("\n=== Step 7: Test Transaction.outputs() field ===") tx_outputs_query = gql( @@ -312,10 +316,14 @@ def _dump_log(): break assert tx_with_outputs is not None, "Should have at least one transaction with outputs" - print(f"Transaction {tx_with_outputs['txid'][:16]}... has {len(tx_with_outputs['outputs'])} outputs:") + print( + f"Transaction {tx_with_outputs['txid'][:16]}... has {len(tx_with_outputs['outputs'])} outputs:" + ) for output in tx_with_outputs["outputs"]: - memo_str = f", Memo: {output['memo'][:30]}..." if output['memo'] else "" - print(f" - Output ID: {output['id']}, Pool: {output['pool']}, Vout: {output['vout']}, Value: {output['value']} ZEC{memo_str}") + memo_str = f", Memo: {output['memo'][:30]}..." if output["memo"] else "" + print( + f" - Output ID: {output['id']}, Pool: {output['pool']}, Vout: {output['vout']}, Value: {output['value']} ZEC{memo_str}" + ) print("\n=== Step 8: Test Transaction.spends() field ===") tx_spends_query = gql( @@ -347,9 +355,13 @@ def _dump_log(): break if tx_with_spends: - print(f"Transaction {tx_with_spends['txid'][:16]}... has {len(tx_with_spends['spends'])} spends:") + print( + f"Transaction {tx_with_spends['txid'][:16]}... has {len(tx_with_spends['spends'])} spends:" + ) for spend in tx_with_spends["spends"]: - print(f" - Spend Note ID: {spend['id']}, Value: {spend['value']} ZEC, Pool: {spend['pool']}") + print( + f" - Spend Note ID: {spend['id']}, Value: {spend['value']} ZEC, Pool: {spend['pool']}" + ) else: print("No spends found (transaction may not have spent any notes yet)") @@ -380,7 +392,9 @@ def _dump_log(): print(f"Account 2 has {len(notes)} notes with transaction details:") for note in notes[:2]: print(f" - Note ID: {note['id']}, Value: {note['value']} ZEC") - print(f" Transaction: {note['tx']['txid'][:16]}..., Height: {note['tx']['height']}, TX Value: {note['tx']['value']} ZEC") + print( + f" Transaction: {note['tx']['txid'][:16]}..., Height: {note['tx']['height']}, TX Value: {note['tx']['value']} ZEC" + ) assert notes[0]["tx"] is not None, "Note should have associated transaction" assert notes[0]["tx"]["txid"] is not None, "Transaction should have txid" diff --git a/tests/tests/test_zebra_wallet.py b/tests/tests/test_zebra_wallet.py index 4d1ed731c..7cefb2e16 100644 --- a/tests/tests/test_zebra_wallet.py +++ b/tests/tests/test_zebra_wallet.py @@ -120,7 +120,7 @@ async def test_zebra_wallet_sync(gql_client_factory, rpc_url, seed, zkool_binary with open(LOG_PATH) as f: log_content = f.read() print(f"\n=== Server log (last 50 lines) ===") - log_lines = log_content.strip().split('\n') + log_lines = log_content.strip().split("\n") for line in log_lines[-50:]: print(f" {line}") print(f"=== End server log ===\n") diff --git a/tests/tests/utils.py b/tests/tests/utils.py index 467ee976f..6659258f3 100644 --- a/tests/tests/utils.py +++ b/tests/tests/utils.py @@ -73,9 +73,7 @@ async def gql_client(url: str, timeout: float = 300.0): """ http_timeout = httpx.Timeout(timeout, connect=60.0) transport = HTTPXAsyncTransport(url=url, timeout=http_timeout) - client = Client( - transport=transport, fetch_schema_from_transport=False, execute_timeout=timeout - ) + client = Client(transport=transport, fetch_schema_from_transport=False, execute_timeout=timeout) try: yield client finally: @@ -152,9 +150,9 @@ def dump_server_log(log_path: str, label: str = "SERVER LOG") -> str: except OSError: return "" if content: - print(f"\n{'='*60}\n{label} ({log_path})\n{'='*60}") + print(f"\n{'=' * 60}\n{label} ({log_path})\n{'=' * 60}") print(content) - print(f"{'='*60}\n") + print(f"{'=' * 60}\n") return content @@ -340,6 +338,8 @@ async def pay(client, account_id: int, recipients: list[dict]) -> str: Transaction ID """ result = await client.execute_async( - GraphQLRequest(PAY_MUTATION, variable_values={"account": account_id, "recipients": recipients}) + GraphQLRequest( + PAY_MUTATION, variable_values={"account": account_id, "recipients": recipients} + ) ) return result["pay"] diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index 955ee3038..603b58756 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -4,7 +4,7 @@ #include "flutter/generated_plugin_registrant.h" -FlutterWindow::FlutterWindow(const flutter::DartProject& project) +FlutterWindow::FlutterWindow(const flutter::DartProject &project) : project_(project) {} FlutterWindow::~FlutterWindow() {} @@ -27,9 +27,7 @@ bool FlutterWindow::OnCreate() { RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); + flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); // Flutter can complete the first frame before the "show window" callback is // registered. The following call ensures a frame is pending to ensure the @@ -62,9 +60,9 @@ FlutterWindow::MessageHandler(HWND hwnd, UINT const message, } switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; } return Win32Window::MessageHandler(hwnd, message, wparam, lparam); diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h index 6da0652f0..7fa026bf2 100644 --- a/windows/runner/flutter_window.h +++ b/windows/runner/flutter_window.h @@ -10,19 +10,19 @@ // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { - public: +public: // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); + explicit FlutterWindow(const flutter::DartProject &project); virtual ~FlutterWindow(); - protected: +protected: // Win32Window: bool OnCreate() override; void OnDestroy() override; LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override; - private: +private: // The project to run. flutter::DartProject project_; @@ -30,4 +30,4 @@ class FlutterWindow : public Win32Window { std::unique_ptr flutter_controller_; }; -#endif // RUNNER_FLUTTER_WINDOW_H_ +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index 54c3bc089..6b07d012e 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -19,8 +19,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, flutter::DartProject project(L"data"); - std::vector command_line_arguments = - GetCommandLineArguments(); + std::vector command_line_arguments = GetCommandLineArguments(); project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); diff --git a/windows/runner/resource.h b/windows/runner/resource.h index 66a65d1e4..d5d958dc4 100644 --- a/windows/runner/resource.h +++ b/windows/runner/resource.h @@ -2,15 +2,15 @@ // Microsoft Visual C++ generated include file. // Used by Runner.rc // -#define IDI_APP_ICON 101 +#define IDI_APP_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp index 3a0b46511..e22aaf3f4 100644 --- a/windows/runner/utils.cpp +++ b/windows/runner/utils.cpp @@ -24,7 +24,7 @@ void CreateAndAttachConsole() { std::vector GetCommandLineArguments() { // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); if (argv == nullptr) { return std::vector(); } @@ -41,14 +41,14 @@ std::vector GetCommandLineArguments() { return command_line_arguments; } -std::string Utf8FromUtf16(const wchar_t* utf16_string) { +std::string Utf8FromUtf16(const wchar_t *utf16_string) { if (utf16_string == nullptr) { return std::string(); } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character + unsigned int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr) - + 1; // remove the trailing null character int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { @@ -56,8 +56,8 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { } utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, input_length, + utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/windows/runner/utils.h b/windows/runner/utils.h index 3879d5475..ff43ce2ce 100644 --- a/windows/runner/utils.h +++ b/windows/runner/utils.h @@ -10,10 +10,10 @@ void CreateAndAttachConsole(); // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string // encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); +std::string Utf8FromUtf16(const wchar_t *utf16_string); // Gets the command line arguments passed in as a std::vector, // encoded in UTF-8. Returns an empty std::vector on failure. std::vector GetCommandLineArguments(); -#endif // RUNNER_UTILS_H_ +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 60608d0fe..145247bb9 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -11,7 +11,8 @@ namespace { /// /// Redefined in case the developer's machine has a Windows SDK older than /// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +/// See: +/// https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE #define DWMWA_USE_IMMERSIVE_DARK_MODE 20 #endif @@ -23,8 +24,9 @@ constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; /// A value of 0 indicates apps should use dark mode. A non-zero or missing /// value indicates apps should use light mode. constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = + L"AppsUseLightTheme"; // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -45,7 +47,7 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { return; } auto enable_non_client_dpi_scaling = - reinterpret_cast( + reinterpret_cast( GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); @@ -53,15 +55,15 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { FreeLibrary(user32_module); } -} // namespace +} // namespace // Manages the Win32Window's window class registration. class WindowClassRegistrar { - public: +public: ~WindowClassRegistrar() = default; // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { + static WindowClassRegistrar *GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); } @@ -70,23 +72,23 @@ class WindowClassRegistrar { // Returns the name of the window class, registering the class if it hasn't // previously been registered. - const wchar_t* GetWindowClass(); + const wchar_t *GetWindowClass(); // Unregisters the window class. Should only be called if there are no // instances of the window. void UnregisterWindowClass(); - private: +private: WindowClassRegistrar() = default; - static WindowClassRegistrar* instance_; + static WindowClassRegistrar *instance_; bool class_registered_ = false; }; -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; -const wchar_t* WindowClassRegistrar::GetWindowClass() { +const wchar_t *WindowClassRegistrar::GetWindowClass() { if (!class_registered_) { WNDCLASS window_class{}; window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); @@ -111,21 +113,18 @@ void WindowClassRegistrar::UnregisterWindowClass() { class_registered_ = false; } -Win32Window::Win32Window() { - ++g_active_window_count; -} +Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { --g_active_window_count; Destroy(); } -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring &title, const Point &origin, + const Size &size) { Destroy(); - const wchar_t* window_class = + const wchar_t *window_class = WindowClassRegistrar::GetInstance()->GetWindowClass(); const POINT target_point = {static_cast(origin.x), @@ -149,24 +148,21 @@ bool Win32Window::Create(const std::wstring& title, return OnCreate(); } -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} +bool Win32Window::Show() { return ShowWindow(window_handle_, SW_SHOWNORMAL); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); + auto window_struct = reinterpret_cast(lparam); SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast(window_struct->lpCreateParams)); - auto that = static_cast(window_struct->lpCreateParams); + auto that = static_cast(window_struct->lpCreateParams); EnableFullDpiSupportIfAvailable(window); that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { + } else if (Win32Window *that = GetThisFromHandle(window)) { return that->MessageHandler(window, message, wparam, lparam); } @@ -174,48 +170,46 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, } LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); } + return 0; + } - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -233,8 +227,8 @@ void Win32Window::Destroy() { } } -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( GetWindowLongPtr(window, GWLP_USERDATA)); } @@ -255,9 +249,7 @@ RECT Win32Window::GetClientArea() { return frame; } -HWND Win32Window::GetHandle() { - return window_handle_; -} +HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { quit_on_close_ = quit_on_close; @@ -275,10 +267,10 @@ void Win32Window::OnDestroy() { void Win32Window::UpdateTheme(HWND const window) { DWORD light_mode; DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); + LSTATUS result = + RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, nullptr, + &light_mode, &light_mode_size); if (result == ERROR_SUCCESS) { BOOL enable_dark_mode = light_mode == 0; diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index e901dde68..5a8c5a6b5 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -11,7 +11,7 @@ // inherited from by classes that wish to specialize with custom // rendering and input handling class Win32Window { - public: +public: struct Point { unsigned int x; unsigned int y; @@ -34,7 +34,7 @@ class Win32Window { // consistent size this function will scale the inputted width and height as // as appropriate for the default monitor. The window is invisible until // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); + bool Create(const std::wstring &title, const Point &origin, const Size &size); // Show the current window. Returns true if the window was successfully shown. bool Show(); @@ -55,12 +55,11 @@ class Win32Window { // Return a RECT representing the bounds of the current client area. RECT GetClientArea(); - protected: +protected: // Processes and route salient window messages for mouse handling, // size change and DPI. Delegates handling of these to member overloads that // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, + virtual LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept; @@ -71,7 +70,7 @@ class Win32Window { // Called when Destroy is called. virtual void OnDestroy(); - private: +private: friend class WindowClassRegistrar; // OS callback called by message pump. Handles the WM_NCCREATE message which @@ -79,13 +78,12 @@ class Win32Window { // non-client DPI scaling so that the non-client area automatically // responds to changes in DPI. All other messages are handled by // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept; // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; + static Win32Window *GetThisFromHandle(HWND const window) noexcept; // Update the window frame's theme to match the system theme. static void UpdateTheme(HWND const window); @@ -99,4 +97,4 @@ class Win32Window { HWND child_content_ = nullptr; }; -#endif // RUNNER_WIN32_WINDOW_H_ +#endif // RUNNER_WIN32_WINDOW_H_ From 71bab2b46676d08df269802015fc1d4f37c76832 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 17:59:22 +0200 Subject: [PATCH 047/189] feat: enhance migration with streaming and progress tracking --- lib/pages/migrate.dart | 58 ++- lib/services/block_height_service.dart | 141 +++++++ lib/src/rust/api/migrate.dart | 5 +- lib/src/rust/frb_generated.dart | 357 ++++++++++-------- lib/store.dart | 104 +++-- lib/store.g.dart | 4 +- rust/src/api/migrate.rs | 124 ++++-- rust/src/frb_generated.rs | 378 +++++++++++-------- rust/src/migrate/mod.rs | 62 +-- rust/src/pay/plan.rs | 9 +- test/services/block_height_service_test.dart | 139 +++++++ 11 files changed, 960 insertions(+), 421 deletions(-) create mode 100644 lib/services/block_height_service.dart create mode 100644 test/services/block_height_service_test.dart diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index e993c0410..27aad4f3e 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -5,6 +5,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart' show logger; import 'package:zkool/src/rust/api/migrate.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; @@ -19,6 +20,7 @@ class MigratePage extends StatefulWidget { class _MigratePageState extends State with WidgetsBindingObserver { StreamSubscription? _sub; + StreamSubscription? _blockHeightSubscription; MigrationStatus? _status; Timer? _countdown; int _countdownSecs = 0; @@ -26,15 +28,21 @@ class _MigratePageState extends State with WidgetsBindingObserver { bool _started = false; bool _didShowCompleteDialog = false; bool _handlingLeave = false; - double _speedIndex = 1; // default: Fast (60s) + double _speedIndex = 1; // default: Fast (15m) - static const _speedLabels = ["Very Fast", "Fast", "Medium", "Slow"]; - static const _speedMeanMs = [15000, 60000, 300000, 3600000]; + static const _targetBlockSpacingMs = 75000; + static const _speedLabels = ["Ultra Fast", "Fast", "Medium", "Slow"]; + static const _speedMeanMs = [ + 60000, + 12 * _targetBlockSpacingMs, + 48 * _targetBlockSpacingMs, + 144 * _targetBlockSpacingMs, + ]; static const _speedDescriptions = [ - "~15s between steps", "~1m between steps", - "~5m between steps", + "~15m between steps", "~1h between steps", + "~3h between steps", ]; Stream _runCancellableMigration({ @@ -51,9 +59,18 @@ class _MigratePageState extends State with WidgetsBindingObserver { controller = StreamController( onListen: () { sourceSubscription = source.listen( - controller.add, - onError: controller.addError, - onDone: controller.close, + (status) { + _updateBlockHeightSubscription(migration, status); + controller.add(status); + }, + onError: (Object error, StackTrace stackTrace) { + unawaited(_stopBlockHeightSubscription()); + controller.addError(error, stackTrace); + }, + onDone: () { + unawaited(_stopBlockHeightSubscription()); + controller.close(); + }, ); }, onPause: () => sourceSubscription?.pause(), @@ -62,6 +79,7 @@ class _MigratePageState extends State with WidgetsBindingObserver { await Future.wait([ migration.cancel(), if (sourceSubscription != null) sourceSubscription!.cancel(), + _stopBlockHeightSubscription(), ]); }, ); @@ -69,6 +87,29 @@ class _MigratePageState extends State with WidgetsBindingObserver { return controller.stream; } + void _updateBlockHeightSubscription( + NoteMigration migration, + MigrationStatus status, + ) { + final waitingForBoundary = status.nextAction.startsWith("Waiting for anchor block"); + if (waitingForBoundary) { + _blockHeightSubscription ??= blockHeightService.heights.listen( + (height) => migration.updateHeight(height: height), + onError: (Object error, StackTrace stackTrace) { + logger.e("Block height polling failed", error: error, stackTrace: stackTrace); + }, + ); + } else { + unawaited(_stopBlockHeightSubscription()); + } + } + + Future _stopBlockHeightSubscription() async { + final subscription = _blockHeightSubscription; + _blockHeightSubscription = null; + await subscription?.cancel(); + } + @override void initState() { super.initState(); @@ -135,6 +176,7 @@ class _MigratePageState extends State with WidgetsBindingObserver { WidgetsBinding.instance.removeObserver(this); _sub?.cancel(); _sub = null; + unawaited(_stopBlockHeightSubscription()); _countdown?.cancel(); _countdown = null; super.dispose(); diff --git a/lib/services/block_height_service.dart b/lib/services/block_height_service.dart new file mode 100644 index 000000000..31a5462fc --- /dev/null +++ b/lib/services/block_height_service.dart @@ -0,0 +1,141 @@ +import 'dart:async'; + +typedef FetchBlockHeight = Future Function(); + +/// Polls the lightwalletd server while at least one component is listening. +/// +/// Every new subscriber receives a freshly fetched height. After that, +/// subscribers are notified only when the height changes. +class BlockHeightService { + BlockHeightService({ + required FetchBlockHeight fetchHeight, + this.pollInterval = const Duration(seconds: 10), + }) : _fetchHeight = fetchHeight; + + final FetchBlockHeight _fetchHeight; + final Duration pollInterval; + final Set> _subscribers = {}; + + Timer? _timer; + Future? _fetchInProgress; + int? _lastHeight; + bool _pollInProgress = false; + int _subscriberCount = 0; + + int? get lastHeight => _lastHeight; + int get subscriberCount => _subscriberCount; + bool get isPolling => _subscriberCount > 0; + + /// Returns a stream backed by the shared polling loop. + /// + /// Each subscriber receives a freshly polled initial height, followed by + /// observed tip-height changes. + Stream get heights => Stream.multi((controller) { + var cancelled = false; + var registered = false; + _subscriberCount++; + + controller.onCancel = () { + if (cancelled) return; + + cancelled = true; + _subscriberCount--; + if (registered) { + _removeSubscriber(controller); + } + }; + + unawaited( + Future( + () async { + try { + final height = await fetchCurrent(); + if (cancelled) return; + + _subscribers.add(controller); + registered = true; + controller.add(height); + _scheduleNextPoll(); + } catch (error, stackTrace) { + if (cancelled) return; + + // Keep the subscriber active so the shared polling loop can retry. + _subscribers.add(controller); + registered = true; + controller.addError(error, stackTrace); + _requestPoll(); + } + }, + ), + ); + }); + + /// Fetches one height without keeping the polling loop alive. + Future fetchCurrent() async { + final height = await _fetchShared(); + _recordHeight(height); + return height; + } + + void _removeSubscriber(MultiStreamController controller) { + _subscribers.remove(controller); + if (_subscribers.isEmpty) { + _timer?.cancel(); + _timer = null; + } + } + + void _requestPoll() { + if (_subscribers.isEmpty) return; + + if (_pollInProgress) return; + + _timer?.cancel(); + _timer = null; + unawaited(_poll()); + } + + void _scheduleNextPoll() { + if (_subscribers.isEmpty || _pollInProgress || _timer != null) return; + _timer = Timer(pollInterval, _requestPoll); + } + + Future _poll() async { + _pollInProgress = true; + try { + final height = await _fetchShared(); + _recordHeight(height); + } catch (error, stackTrace) { + for (final subscriber in _subscribers.toList()) { + subscriber.addError(error, stackTrace); + } + } finally { + _pollInProgress = false; + _scheduleNextPoll(); + } + } + + Future _fetchShared() { + final inProgress = _fetchInProgress; + if (inProgress != null) return inProgress; + + late final Future request; + request = _fetchHeight().whenComplete(() { + if (identical(_fetchInProgress, request)) { + _fetchInProgress = null; + } + }); + _fetchInProgress = request; + return request; + } + + void _recordHeight(int height) { + final changed = height != _lastHeight; + _lastHeight = height; + if (!changed) return; + + for (final subscriber in _subscribers.toList()) { + subscriber.add(height); + } + } +} diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index 6636f2cfb..291ed0519 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -9,7 +9,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'migrate.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `do_step`, `run_migration` +// These functions are ignored because they are not marked as `pub`: `current_migration_status`, `do_step`, `run_migration`, `synchronize_to`, `wait_for_anchor_boundary`, `wallet_height` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). @@ -25,6 +25,9 @@ abstract class NoteMigration implements RustOpaqueInterface { factory NoteMigration() => RustLib.instance.api.crateApiMigrateNoteMigrationNew(); Stream run({required Coin c, required BigInt meanDelayMs}); + + /// Supplies a height observed by the shared Dart block-height service. + void updateHeight({required int height}); } @freezed diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 57fce034f..7cc428d55 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -90,7 +90,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -492919685; + int get rustContentHash => 151776773; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( stem: 'rlz', @@ -135,6 +135,8 @@ abstract class RustLibApi extends BaseApi { Stream crateApiMigrateNoteMigrationRun({required NoteMigration that, required Coin c, required BigInt meanDelayMs}); + void crateApiMigrateNoteMigrationUpdateHeight({required NoteMigration that, required int height}); + Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}); Future crateApiSweepTransparentScannerNew(); @@ -846,6 +848,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["that", "sink", "c", "meanDelayMs"], ); + @override + void crateApiMigrateNoteMigrationUpdateHeight({required NoteMigration that, required int height}) { + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); + sse_encode_u_32(height, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationUpdateHeightConstMeta, + argValues: [that, height], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMigrateNoteMigrationUpdateHeightConstMeta => const TaskConstMeta( + debugName: "NoteMigration_update_height", + argNames: ["that", "height"], + ); + @override Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}) { return handler.executeNormal( @@ -853,7 +881,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -877,7 +905,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, @@ -908,7 +936,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(endHeight, serializer); sse_encode_u_32(gapLimit, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -935,7 +963,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pool_balance, @@ -962,7 +990,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(txBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -987,7 +1015,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_recipient(recipients, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1013,7 +1041,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(height, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1038,7 +1066,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1062,7 +1090,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1090,7 +1118,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(tmpDir, serializer); sse_encode_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1114,7 +1142,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24)!; }, codec: SseCodec( decodeSuccessData: sse_decode_sapling_params_status, @@ -1139,7 +1167,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1164,7 +1192,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1189,7 +1217,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1216,7 +1244,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_String(dbFilepath, serializer); sse_encode_opt_String(password, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1242,7 +1270,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_32(account, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1269,7 +1297,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_8(serverType, serializer); sse_encode_String(url, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1295,7 +1323,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_String(proxy, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1321,7 +1349,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_bool(useTor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1349,7 +1377,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(addresses, serializer); sse_encode_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_contact, @@ -1375,7 +1403,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -1401,7 +1429,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_folder, @@ -1426,7 +1454,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(packet, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, @@ -1452,7 +1480,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1478,7 +1506,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1504,7 +1532,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1530,7 +1558,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1558,7 +1586,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_dkg_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1588,7 +1616,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_signing_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1614,7 +1642,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1639,7 +1667,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_signing_event(a, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1665,7 +1693,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(path, serializer); sse_encode_box_autoadd_raptor_q_params(params, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_list_prim_u_8_strict, @@ -1689,7 +1717,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1716,7 +1744,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(passphrase, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -1741,7 +1769,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1766,7 +1794,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -1793,7 +1821,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(c, serializer); sse_encode_bool(aggregate, serializer); sse_encode_u_8(poolFilter, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -1821,7 +1849,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_u_32_f_64, @@ -1848,7 +1876,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(from, serializer); sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_string_f_64_bool, @@ -1873,7 +1901,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -1899,7 +1927,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1926,7 +1954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -1952,7 +1980,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact_match, @@ -1976,7 +2004,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_frost_sign_params, @@ -2001,7 +2029,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 58, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2026,7 +2054,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 58, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 59, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2050,7 +2078,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 59)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2077,7 +2105,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 61, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2103,7 +2131,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 61, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 62, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2128,7 +2156,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 62, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 63, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, @@ -2154,7 +2182,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 63, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2180,7 +2208,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_seed, @@ -2207,7 +2235,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(pools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 66, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2233,7 +2261,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 66, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2259,7 +2287,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); sse_encode_String(currency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 68, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -2284,7 +2312,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 68, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2309,7 +2337,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -2334,7 +2362,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2361,7 +2389,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 72, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -2387,7 +2415,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 72, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2413,7 +2441,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74)!; }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2439,7 +2467,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2464,7 +2492,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -2489,7 +2517,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 77, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2515,7 +2543,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 77, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2540,7 +2568,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!; }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2565,7 +2593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 80, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2589,7 +2617,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 80, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 81, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2615,7 +2643,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 81, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 82, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -2640,7 +2668,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 82, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2665,7 +2693,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 84, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2690,7 +2718,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 84, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 85, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -2717,7 +2745,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(passphrase, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 85, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 86, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2743,7 +2771,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 86, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 87, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -2767,7 +2795,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 87, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 88, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2791,7 +2819,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 88, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2816,7 +2844,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 90, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2841,7 +2869,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 90, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 91, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2866,7 +2894,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 91, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 92, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2890,7 +2918,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 92)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2918,7 +2946,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 94, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2943,7 +2971,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(append, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 94, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, @@ -2969,7 +2997,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -2994,7 +3022,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3019,7 +3047,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3045,7 +3073,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3070,7 +3098,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3096,7 +3124,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3122,7 +3150,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3147,7 +3175,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3173,7 +3201,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3198,7 +3226,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 105, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3236,7 +3264,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_prim_u_8_strict(descHash, serializer); sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 105, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 106, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3261,7 +3289,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 106, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 107, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -3286,7 +3314,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 107, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 108, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -3311,7 +3339,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 108, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 109, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3336,7 +3364,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 109, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 110, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -3361,7 +3389,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 110, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 111, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3386,7 +3414,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 111, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 112, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -3411,7 +3439,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 112, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 113, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -3436,7 +3464,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 113, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 114, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -3461,7 +3489,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 114, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -3486,7 +3514,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 115, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -3511,7 +3539,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 116, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -3538,7 +3566,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 117, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3565,7 +3593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 118, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3590,7 +3618,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 119, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 120, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -3616,7 +3644,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 120, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -3641,7 +3669,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 121, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3667,7 +3695,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 122, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 123, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -3692,7 +3720,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 123)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -3719,7 +3747,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -3746,7 +3774,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 125, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -3772,7 +3800,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 126, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 127, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3799,7 +3827,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 127, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3824,7 +3852,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 128, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 129, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -3848,7 +3876,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 129, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 130, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -3874,7 +3902,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 130)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -3900,7 +3928,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3926,7 +3954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 132, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3952,7 +3980,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 133, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 134, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3979,7 +4007,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 134, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4006,7 +4034,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(oldPosition, serializer); sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 135, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 136, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4031,7 +4059,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 136, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4057,7 +4085,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 137, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4083,7 +4111,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 138, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4108,7 +4136,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 139, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4133,7 +4161,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 140, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 141, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4160,7 +4188,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 141, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4187,7 +4215,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 142, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4214,7 +4242,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_64(idAsset, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 143, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 144, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4241,7 +4269,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(id, serializer); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 144, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 145, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4272,7 +4300,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(t, serializer); sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 145, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 146, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4297,7 +4325,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 146)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4323,7 +4351,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4351,7 +4379,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4378,7 +4406,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 149, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4405,7 +4433,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 150, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4432,7 +4460,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 151, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 152, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4457,7 +4485,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 152, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 153, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4482,7 +4510,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 153, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4511,7 +4539,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_signing_event_Sse(sink, serializer); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 154, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4539,7 +4567,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 155, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4564,7 +4592,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 156, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 157, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -4593,7 +4621,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 157, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 158, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4634,7 +4662,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(checkpointAge, serializer); sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 158, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 159, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4662,7 +4690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 159)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -4687,7 +4715,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 161, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4713,7 +4741,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 161)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4737,7 +4765,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -4761,7 +4789,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 163, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -4785,7 +4813,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 164, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 165, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -4809,7 +4837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 165, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -4833,7 +4861,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 166, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 167, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -4860,7 +4888,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ufvk, serializer); sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 167)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -4885,7 +4913,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4910,7 +4938,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 169, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 170, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4936,7 +4964,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 170, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 171, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4965,7 +4993,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_String(addresses, serializer); sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 171, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 172, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4992,7 +5020,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(currency, serializer); sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 172, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 173, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5017,7 +5045,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 173)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5043,7 +5071,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 175)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -9803,6 +9831,9 @@ class NoteMigrationImpl extends RustOpaque implements NoteMigration { Stream run({required Coin c, required BigInt meanDelayMs}) => RustLib.instance.api.crateApiMigrateNoteMigrationRun(that: this, c: c, meanDelayMs: meanDelayMs); + + /// Supplies a height observed by the shared Dart block-height service. + void updateHeight({required int height}) => RustLib.instance.api.crateApiMigrateNoteMigrationUpdateHeight(that: this, height: height); } @sealed diff --git a/lib/store.dart b/lib/store.dart index 30fc99f23..a931f6d71 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -12,6 +12,7 @@ import 'package:toastification/toastification.dart'; import 'package:flutter/material.dart'; import 'package:zkool/main.dart'; import 'package:zkool/router.dart'; +import 'package:zkool/services/block_height_service.dart'; import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/coin.dart'; import 'package:zkool/src/rust/api/contacts.dart'; @@ -68,6 +69,9 @@ class CoinContext { } final coinContext = CoinContext(); +final blockHeightService = BlockHeightService( + fetchHeight: () => getCurrentHeight(c: coinContext.coin), +); @freezed sealed class SyncState with _$SyncState { @@ -527,7 +531,8 @@ class CurrentHeight extends _$CurrentHeight { @override Future build() async { - return await _doFetch(); + _cachedHeight = blockHeightService.lastHeight; + return _cachedHeight; } /// Get current height, cached up to 15s. Respects offline mode. @@ -547,11 +552,17 @@ class CurrentHeight extends _$CurrentHeight { } Future _doFetch() async { - _cachedHeight = await getCurrentHeight(c: coinContext.coin); + _cachedHeight = await blockHeightService.fetchCurrent(); _lastFetch = DateTime.now(); state = AsyncData(_cachedHeight); return _cachedHeight; } + + void updateFromService(int height) { + _cachedHeight = height; + _lastFetch = DateTime.now(); + state = AsyncData(height); + } } Mempool mempool = Mempool(); @@ -665,12 +676,18 @@ void runLogListener() async { @Riverpod(keepAlive: true) class SynchronizerNotifier extends _$SynchronizerNotifier { bool syncInProgress = false; - bool _autoSyncActive = false; + StreamSubscription? _autoSyncSubscription; + bool _handlingAutoSyncHeight = false; + bool _forceNextAutoSync = false; + int? _pendingAutoSyncHeight; StreamSubscription? syncProgressSubscription; int retryCount = 0; @override SyncState build() { + ref.onDispose(() { + unawaited(_autoSyncSubscription?.cancel()); + }); return SyncState( start: 0, end: 0, @@ -708,7 +725,10 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { ); } - Future startSynchronize(List accounts) async { + Future startSynchronize( + List accounts, { + int? currentHeight, + }) async { if (syncInProgress) return; final c = coinContext.coin; @@ -718,6 +738,7 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { syncInProgress = true; retryCount = 0; final completer = Completer(); + var requestedHeight = currentHeight; while (true) { try { @@ -725,13 +746,14 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) { showSnackbar("Starting Synchronization"); } - final currentHeight = await getCurrentHeight(c: c); + final syncHeight = requestedHeight ?? await blockHeightService.fetchCurrent(); + requestedHeight = null; - begin(accounts, currentHeight); + begin(accounts, syncHeight); final progress = synchronize( accounts: accounts.map((a) => a.id).toList(), - currentHeight: currentHeight, + currentHeight: syncHeight, actionsPerSync: int.parse(settings.actionsPerSync), transparentLimit: 100, checkpointAge: 500_000, @@ -804,29 +826,57 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } } - void autoSync({bool now = false}) async { - if (_autoSyncActive) return; - _autoSyncActive = true; - try { - final settings = await ref.read(appSettingsProvider.future); - final interval = int.tryParse(settings.syncInterval) ?? 0; + Future autoSync({bool now = false}) async { + final settings = await ref.read(appSettingsProvider.future); + final interval = int.tryParse(settings.syncInterval) ?? 0; - if (settings.offline || interval <= 0) { - return; - } - try { - final currentHeight = await ref.read(currentHeightProvider.notifier).fetch(); - if (currentHeight != null) { - await syncIfNeeded(currentHeight, now: now); + if (settings.offline || interval <= 0) { + await _autoSyncSubscription?.cancel(); + _autoSyncSubscription = null; + return; + } + + if (_autoSyncSubscription == null) { + var forceFirstHeight = now; + _autoSyncSubscription = blockHeightService.heights.listen( + (height) { + ref.read(currentHeightProvider.notifier).updateFromService(height); + _queueAutoSync(height, force: forceFirstHeight); + forceFirstHeight = false; + }, + onError: (Object error, StackTrace stackTrace) { + logger.e("Block height polling failed", error: error, stackTrace: stackTrace); + }, + ); + } else if (now) { + final height = blockHeightService.lastHeight ?? await blockHeightService.fetchCurrent(); + _queueAutoSync(height, force: true); + } + } + + void _queueAutoSync(int height, {required bool force}) { + _pendingAutoSyncHeight = max(_pendingAutoSyncHeight ?? height, height); + _forceNextAutoSync |= force; + if (_handlingAutoSyncHeight) return; + unawaited(_drainAutoSyncQueue()); + } + + Future _drainAutoSyncQueue() async { + _handlingAutoSyncHeight = true; + try { + while (_pendingAutoSyncHeight != null) { + final height = _pendingAutoSyncHeight!; + final force = _forceNextAutoSync; + _pendingAutoSyncHeight = null; + _forceNextAutoSync = false; + try { + await syncIfNeeded(height, now: force); + } on AnyhowException catch (error, stackTrace) { + logger.e("AutoSync failed", error: error, stackTrace: stackTrace); } - } on AnyhowException catch (e) { - logger.e(e); - // ignore - } finally { - if (interval > 0) Timer(Duration(seconds: 15), () => autoSync()); } } finally { - _autoSyncActive = false; + _handlingAutoSyncHeight = false; } } @@ -844,7 +894,7 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } } if (accountsToSync.isNotEmpty) { - await startSynchronize(accountsToSync); + await startSynchronize(accountsToSync, currentHeight: currentHeight); } } } diff --git a/lib/store.g.dart b/lib/store.g.dart index fb1041d50..bbacee2c9 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -735,7 +735,7 @@ final class CurrentHeightProvider extends $AsyncNotifierProvider CurrentHeight(); } -String _$currentHeightHash() => r'83f6fa7bfb3bee9f854fdc8c7ecc96c04075c8be'; +String _$currentHeightHash() => r'0710021baa0ed9a9ad29fc8d49cefd60f3712134'; abstract class _$CurrentHeight extends $AsyncNotifier { FutureOr build(); @@ -825,7 +825,7 @@ final class SynchronizerNotifierProvider extends $NotifierProvider r'049414ae8378414353563749d26326461231fee4'; +String _$synchronizerNotifierHash() => r'3bab6681ff1ee0f1161575e4690f143aa9e72f7b'; abstract class _$SynchronizerNotifier extends $Notifier { SyncState build(); diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index ee1538929..60a9bdafa 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use tokio::sync::watch; use tokio_util::sync::CancellationToken; #[cfg(feature = "flutter")] @@ -36,13 +37,16 @@ pub enum MigrationEvent { #[cfg_attr(feature = "flutter", frb(opaque))] pub struct NoteMigration { cancellation_token: CancellationToken, + block_height_tx: watch::Sender>, } impl NoteMigration { #[cfg_attr(feature = "flutter", frb(sync))] pub fn new() -> Self { + let (block_height_tx, _) = watch::channel(None); Self { cancellation_token: CancellationToken::new(), + block_height_tx, } } @@ -53,18 +57,31 @@ impl NoteMigration { c: &Coin, mean_delay_ms: u64, ) -> Result<()> { - run_migration(sink, c, mean_delay_ms, self.cancellation_token.clone()).await + run_migration( + sink, + c, + mean_delay_ms, + self.cancellation_token.clone(), + self.block_height_tx.clone(), + ) + .await } pub fn cancel(&self) { self.cancellation_token.cancel(); } + + /// Supplies a height observed by the shared Dart block-height service. + #[cfg_attr(feature = "flutter", frb(sync))] + pub fn update_height(&self, height: u32) { + self.block_height_tx.send_replace(Some(height)); + } } /// Single-shot step (kept for FRB generated-code compatibility). #[cfg_attr(feature = "flutter", frb)] pub async fn step_migration(c: &Coin) -> Result { - let (event, _status) = do_step(c, 0, 0, true, true).await?; + let (event, _status) = do_step(c, 0, 0, true, true, crate::migrate::ANCHOR_BUCKET_SIZE).await?; Ok(match event { crate::migrate::MigrationEvent::SplitComplete { fee } => { MigrationEvent::SplitComplete { fee } @@ -89,6 +106,7 @@ async fn run_migration( c: &Coin, mean_delay_ms: u64, cancellation_token: CancellationToken, + block_height_tx: watch::Sender>, ) -> Result<()> { use rand_core::{OsRng, RngCore}; use zcash_protocol::consensus::{BlockHeight, NetworkUpgrade, Parameters}; @@ -117,6 +135,12 @@ async fn run_migration( let mut acc_split = 0u64; let mut acc_migrate = 0u64; let mut last_action_height: Option = None; + let anchor_bucket_size = crate::migrate::migration_anchor_bucket_size(mean_delay_ms); + tracing::info!( + "Migration anchor interval: {} blocks for mean delay {}ms", + anchor_bucket_size, + mean_delay_ms, + ); let mut status = current_migration_status(c, acc_split, acc_migrate).await?; sink.add(status.clone()).ok(); @@ -165,13 +189,20 @@ async fn run_migration( // only query the tip height; do not fetch or synchronize tree state. let align_to_boundary = status.phase == "migrating"; if align_to_boundary { + block_height_tx.send_replace(None); let reached_boundary = tokio::select! { biased; _ = cancellation_token.cancelled() => { tracing::info!("Note migration cancelled"); false } - result = wait_for_anchor_boundary(&sink, c, &mut client, &status) => { + result = wait_for_anchor_boundary( + &sink, + c, + block_height_tx.subscribe(), + &status, + anchor_bucket_size, + ) => { result?; true } @@ -179,6 +210,9 @@ async fn run_migration( if !reached_boundary { break; } + + status.next_action = "Preparing migration transaction...".into(); + sink.add(status.clone()).ok(); } let (event, next_status) = tokio::select! { @@ -193,6 +227,7 @@ async fn run_migration( acc_migrate, align_to_boundary, !align_to_boundary, + anchor_bucket_size, ) => result?, }; @@ -245,6 +280,7 @@ async fn do_step( acc_migrate: u64, allow_migrate: bool, sync_before: bool, + anchor_bucket_size: u32, ) -> Result<(crate::migrate::MigrationEvent, MigrationStatus)> { let network = c.network(); let mut connection = c.get_connection().await?; @@ -264,9 +300,15 @@ async fn do_step( // transaction instead of broadcasting it immediately. crate::migrate::MigrationEvent::NothingToDo } else { - crate::migrate::step(&network, &mut connection, &mut client, c.account) - .await - .map_err(|e| anyhow::anyhow!("step: {e}"))? + crate::migrate::step( + &network, + &mut connection, + &mut client, + c.account, + anchor_bucket_size, + ) + .await + .map_err(|e| anyhow::anyhow!("step: {e}"))? }; let status = current_migration_status(c, acc_split, acc_migrate).await?; @@ -352,71 +394,91 @@ async fn synchronize_to(c: &Coin, height: u32) -> Result { .await } -/// Poll only the network height until the next shared anchor boundary. Tree -/// state is synchronized exactly once, while that boundary is the current tip. +/// Wait for heights supplied by Dart's shared block-height service. Tree state +/// is synchronized exactly once, while the boundary is the current tip. #[cfg(feature = "flutter")] async fn wait_for_anchor_boundary( sink: &StreamSink, c: &Coin, - client: &mut crate::Client, + mut block_heights: watch::Receiver>, status: &MigrationStatus, + anchor_bucket_size: u32, ) -> Result<()> { - const HEIGHT_POLL_INTERVAL: std::time::Duration = std::time::Duration::from_secs(10); - - let observed_height = client.latest_height().await?; - let db_height = wallet_height(c).await?; - let mut boundary = crate::migrate::next_anchor_bucket_height(observed_height.max(db_height)); - let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", boundary); + waiting.next_action = "Waiting for anchor block...".into(); sink.add(waiting).ok(); + let mut boundary = None; loop { - let tip = client.latest_height().await?; - if tip > boundary { + block_heights.changed().await?; + let Some(tip) = *block_heights.borrow_and_update() else { + continue; + }; + + let target = match boundary { + Some(boundary) => boundary, + None => { + let db_height = wallet_height(c).await?; + let boundary = crate::migrate::next_anchor_bucket_height( + tip.max(db_height), + anchor_bucket_size, + ); + let mut waiting = status.clone(); + waiting.next_action = format!("Waiting for anchor block {}...", boundary); + sink.add(waiting).ok(); + boundary + } + }; + + if tip > target { // If height polling missed the boundary, do not fetch its // historical tree state. Wait for a boundary that is observed as // the current tip. - boundary = crate::migrate::next_anchor_bucket_height(tip.saturating_add(1)); + let next_boundary = crate::migrate::next_anchor_bucket_height( + tip.saturating_add(1), + anchor_bucket_size, + ); + boundary = Some(next_boundary); let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", boundary); + waiting.next_action = format!("Waiting for anchor block {}...", next_boundary); sink.add(waiting).ok(); continue; } - if tip == boundary { + boundary = Some(target); + if tip == target { tracing::info!( "Migration anchor boundary reached: tip={}, boundary={}", tip, - boundary, + target, ); - synchronize_to(c, boundary).await?; + synchronize_to(c, target).await?; let synced_height = wallet_height(c).await?; - if synced_height == boundary { + if synced_height == target { return Ok(()); } - if synced_height > boundary { + if synced_height > target { // Another sync advanced the wallet while we were waiting. // Move to a future boundary instead of preparing from a // checkpoint that no longer represents the current tip. - boundary = crate::migrate::next_anchor_bucket_height( + let next_boundary = crate::migrate::next_anchor_bucket_height( tip.max(synced_height).saturating_add(1), + anchor_bucket_size, ); + boundary = Some(next_boundary); let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", boundary); + waiting.next_action = format!("Waiting for anchor block {}...", next_boundary); sink.add(waiting).ok(); continue; } - tracing::warn!( + anyhow::bail!( "Migration boundary sync did not advance: wallet={}, boundary={}", synced_height, - boundary, + target, ); } - - tokio::time::sleep(HEIGHT_POLL_INTERVAL).await; } } diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 2614287cd..433c9e52e 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -492919685; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 151776773; // Section: executor @@ -712,6 +712,55 @@ fn wire__crate__api__migrate__NoteMigration_run_impl( }, ) } +fn wire__crate__api__migrate__NoteMigration_update_height_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "NoteMigration_update_height", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_height = ::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::migrate::NoteMigration::update_height(&*api_that_guard, api_height); + })?; + Ok(output_ok) + })()) + }, + ) +} fn wire__crate__api__sweep__TransparentScanner_cancel_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -8781,272 +8830,272 @@ fn pde_ffi_dispatcher_primary_impl( wire__crate__api__migrate__NoteMigration_cancel_impl(port, ptr, rust_vec_len, data_len) } 12 => wire__crate__api__migrate__NoteMigration_run_impl(port, ptr, rust_vec_len, data_len), - 13 => wire__crate__api__sweep__TransparentScanner_cancel_impl( + 14 => wire__crate__api__sweep__TransparentScanner_cancel_impl( port, ptr, rust_vec_len, data_len, ), - 14 => { + 15 => { wire__crate__api__sweep__TransparentScanner_new_impl(port, ptr, rust_vec_len, data_len) } - 15 => { + 16 => { wire__crate__api__sweep__TransparentScanner_run_impl(port, ptr, rust_vec_len, data_len) } - 16 => wire__crate__api__sync__balance_impl(port, ptr, rust_vec_len, data_len), - 17 => wire__crate__api__pay__broadcast_transaction_impl(port, ptr, rust_vec_len, data_len), - 18 => wire__crate__api__pay__build_puri_impl(port, ptr, rust_vec_len, data_len), - 19 => wire__crate__api__sync__cache_block_time_impl(port, ptr, rust_vec_len, data_len), - 20 => wire__crate__api__frost__cancel_dkg_impl(port, ptr, rust_vec_len, data_len), - 21 => wire__crate__api__sync__cancel_sync_impl(port, ptr, rust_vec_len, data_len), - 22 => wire__crate__api__db__change_db_password_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__coin__close_pool_impl(port, ptr, rust_vec_len, data_len), - 25 => wire__crate__api__coin__coin_get_name_impl(port, ptr, rust_vec_len, data_len), - 27 => wire__crate__api__coin__coin_open_database_impl(port, ptr, rust_vec_len, data_len), - 28 => wire__crate__api__coin__coin_set_account_impl(port, ptr, rust_vec_len, data_len), - 31 => wire__crate__api__coin__coin_set_use_tor_impl(port, ptr, rust_vec_len, data_len), - 32 => wire__crate__api__contacts__create_contact_impl(port, ptr, rust_vec_len, data_len), - 33 => { + 17 => wire__crate__api__sync__balance_impl(port, ptr, rust_vec_len, data_len), + 18 => wire__crate__api__pay__broadcast_transaction_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__pay__build_puri_impl(port, ptr, rust_vec_len, data_len), + 20 => wire__crate__api__sync__cache_block_time_impl(port, ptr, rust_vec_len, data_len), + 21 => wire__crate__api__frost__cancel_dkg_impl(port, ptr, rust_vec_len, data_len), + 22 => wire__crate__api__sync__cancel_sync_impl(port, ptr, rust_vec_len, data_len), + 23 => wire__crate__api__db__change_db_password_impl(port, ptr, rust_vec_len, data_len), + 25 => wire__crate__api__coin__close_pool_impl(port, ptr, rust_vec_len, data_len), + 26 => wire__crate__api__coin__coin_get_name_impl(port, ptr, rust_vec_len, data_len), + 28 => wire__crate__api__coin__coin_open_database_impl(port, ptr, rust_vec_len, data_len), + 29 => wire__crate__api__coin__coin_set_account_impl(port, ptr, rust_vec_len, data_len), + 32 => wire__crate__api__coin__coin_set_use_tor_impl(port, ptr, rust_vec_len, data_len), + 33 => wire__crate__api__contacts__create_contact_impl(port, ptr, rust_vec_len, data_len), + 34 => { wire__crate__api__account__create_new_category_impl(port, ptr, rust_vec_len, data_len) } - 34 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), - 35 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), - 36 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), - 37 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), - 38 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), - 39 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), - 40 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), - 41 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__sapling__download_sapling_params_impl( + 35 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), + 36 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), + 37 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), + 38 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), + 39 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), + 40 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), + 42 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), + 43 => wire__crate__api__sapling__download_sapling_params_impl( port, ptr, rust_vec_len, data_len, ), - 43 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), - 44 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), - 45 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), - 46 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__contacts__export_contacts_vcard_impl( + 44 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), + 45 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), + 46 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__contacts__export_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 48 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), - 49 => wire__crate__api__account__fetch_address_tx_count_impl( + 49 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__account__fetch_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 50 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), - 51 => wire__crate__api__transaction__fetch_category_amounts_impl( + 51 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__transaction__fetch_category_amounts_impl( port, ptr, rust_vec_len, data_len, ), - 52 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( + 53 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 53 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), - 54 => wire__crate__api__transaction__fill_missing_tx_prices_impl( + 54 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), + 55 => wire__crate__api__transaction__fill_missing_tx_prices_impl( port, ptr, rust_vec_len, data_len, ), - 55 => wire__crate__api__contacts__find_contacts_for_address_impl( + 56 => wire__crate__api__contacts__find_contacts_for_address_impl( port, ptr, rust_vec_len, data_len, ), - 56 => wire__crate__api__frost__frost_sign_params_default_impl( + 57 => wire__crate__api__frost__frost_sign_params_default_impl( port, ptr, rust_vec_len, data_len, ), - 57 => wire__crate__api__account__generate_next_change_address_impl( + 58 => wire__crate__api__account__generate_next_change_address_impl( port, ptr, rust_vec_len, data_len, ), - 58 => { + 59 => { wire__crate__api__account__generate_next_dindex_impl(port, ptr, rust_vec_len, data_len) } - 60 => { + 61 => { wire__crate__api__account__get_account_addresses_impl(port, ptr, rust_vec_len, data_len) } - 61 => wire__crate__api__account__get_account_fingerprint_impl( + 62 => wire__crate__api__account__get_account_fingerprint_impl( port, ptr, rust_vec_len, data_len, ), - 62 => wire__crate__api__account__get_account_frost_params_impl( + 63 => wire__crate__api__account__get_account_frost_params_impl( port, ptr, rust_vec_len, data_len, ), - 63 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), - 64 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), - 65 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), - 66 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), - 67 => { + 64 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), + 65 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), + 66 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), + 67 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), + 68 => { wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) } - 68 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), - 69 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), - 70 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 71 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 72 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), - 74 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), - 75 => { + 69 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), + 70 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), + 71 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 72 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 73 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), + 75 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), + 76 => { wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) } - 76 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), - 77 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), - 79 => wire__crate__api__network__get_supported_vs_currencies_impl( + 77 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), + 78 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), + 80 => wire__crate__api__network__get_supported_vs_currencies_impl( port, ptr, rust_vec_len, data_len, ), - 80 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), - 81 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 83 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 84 => wire__crate__api__account__has_transparent_pub_key_impl( + 81 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), + 82 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), + 83 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 84 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 85 => wire__crate__api__account__has_transparent_pub_key_impl( port, ptr, rust_vec_len, data_len, ), - 85 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), - 86 => wire__crate__api__contacts__import_contacts_vcard_impl( + 86 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), + 87 => wire__crate__api__contacts__import_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 87 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), - 88 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), - 89 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 90 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), - 93 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), - 94 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), - 95 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), - 96 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), - 97 => { + 88 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), + 90 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 92 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), + 94 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), + 95 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), + 96 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), + 97 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), + 98 => { wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) } - 104 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 105 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 106 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 107 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 108 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 109 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 110 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 105 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 106 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 107 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 108 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 109 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 110 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 114 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 115 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 124 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 128 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 129 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 136 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 138 => { + 125 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 129 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 138 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 139 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 139 => wire__crate__api__openalias__resolve_openalias_all_impl( + 140 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 140 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 141 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 141 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 144 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 149 => { + 142 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 150 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 150 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 151 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__account__show_ledger_sapling_address_impl( + 151 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 152 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 153 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 153 => wire__crate__api__account__show_ledger_transparent_address_impl( + 154 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 154 => wire__crate__api__account__sign_ledger_transaction_impl( + 155 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 155 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 160 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 162 => { + 156 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 159 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 161 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 163 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 163 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 172 => wire__crate__api__transaction__update_historical_prices_impl( + 164 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 172 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 173 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, @@ -9066,37 +9115,40 @@ fn pde_ffi_dispatcher_sync_impl( match func_id { 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), - 23 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), - 26 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), - 29 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), - 30 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), - 59 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), - 73 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), - 78 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), - 92 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), - 98 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), - 99 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), - 100 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), - 101 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 102 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 103 => { + 13 => { + wire__crate__api__migrate__NoteMigration_update_height_impl(ptr, rust_vec_len, data_len) + } + 24 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), + 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), + 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), + 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), + 60 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), + 74 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), + 79 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), + 93 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), + 99 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), + 100 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), + 101 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), + 102 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), + 103 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 104 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 123 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 130 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 146 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 147 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 159 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 161 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 124 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 147 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 148 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 160 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 162 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 167 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 173 => { + 168 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 174 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 174 => { + 175 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index c7dec9f0b..74200285e 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -24,9 +24,13 @@ pub const MIN_SD: u64 = 100 * COST_PER_ACTION; /// Caps transaction size to avoid oversized bundles that nodes reject. const MAX_SPLIT_INPUTS: usize = 50; -/// Migration anchors are rounded down to this block interval. +/// Maximum migration anchor interval specified by the migration protocol. pub const ANCHOR_BUCKET_SIZE: u32 = 144; +/// Zcash's target block spacing, used to scale the anchor interval to the +/// selected migration speed. +const TARGET_BLOCK_SPACING_MS: u64 = 75_000; + /// Fee padding embedded in each standard denomination. /// Covers Orchard input + change (2 actions in sum mode) and Ironwood /// output (2 actions, padded) = 4 × COST_PER_ACTION = 20,000 zats. @@ -162,17 +166,21 @@ async fn fetch_unspent_orchard_notes_with_cmx( .map_err(Into::into) } -fn anchor_bucket_height(height: u32) -> u32 { - height - height % ANCHOR_BUCKET_SIZE +pub(crate) fn migration_anchor_bucket_size(mean_delay_ms: u64) -> u32 { + let blocks = + mean_delay_ms.saturating_add(TARGET_BLOCK_SPACING_MS - 1) / TARGET_BLOCK_SPACING_MS; + u32::try_from(blocks) + .unwrap_or(u32::MAX) + .clamp(1, ANCHOR_BUCKET_SIZE) } /// Return the first migration anchor boundary at or above `height`. -pub(crate) fn next_anchor_bucket_height(height: u32) -> u32 { - let remainder = height % ANCHOR_BUCKET_SIZE; +pub(crate) fn next_anchor_bucket_height(height: u32, bucket_size: u32) -> u32 { + let remainder = height % bucket_size; if remainder == 0 { height } else { - height.saturating_add(ANCHOR_BUCKET_SIZE - remainder) + height.saturating_add(bucket_size - remainder) } } @@ -182,6 +190,7 @@ pub async fn step( connection: &mut SqliteConnection, client: &mut Client, account: u32, + anchor_bucket_size: u32, ) -> Result { let height = client.latest_height().await?; let checkpoint_height = crate::sync::get_db_height(&mut *connection, account) @@ -349,11 +358,15 @@ pub async fn step( */ // ── Migrating phase ── - let anchor_height = anchor_bucket_height(checkpoint_height); + anyhow::ensure!( + checkpoint_height % anchor_bucket_size == 0, + "Migration checkpoint {checkpoint_height} is not on a \ + {anchor_bucket_size}-block anchor boundary", + ); + let anchor_height = checkpoint_height; - // A witness can only be rewound to an anchor whose tree already - // contains the note. The latest checkpoint must also contain the note - // so its witness is available for Witness::rewind(). + // The selected note must exist at the current boundary checkpoint. + // Migration never rewinds a witness to a historical anchor. let mut sorted_sd: Vec<&OrchardZecNote> = sd_notes .iter() .copied() @@ -361,8 +374,8 @@ pub async fn step( .collect(); if sorted_sd.is_empty() { info!( - "Migration waiting: no SD note can be rewound from checkpoint {} to anchor {}", - checkpoint_height, anchor_height, + "Migration waiting: no SD note is available at checkpoint {}", + checkpoint_height, ); return Ok(MigrationEvent::NothingToDo); } @@ -447,21 +460,22 @@ mod tests { } #[test] - fn test_anchor_bucket_height() { - assert_eq!(anchor_bucket_height(0), 0); - assert_eq!(anchor_bucket_height(143), 0); - assert_eq!(anchor_bucket_height(144), 144); - assert_eq!(anchor_bucket_height(145), 144); - assert_eq!(anchor_bucket_height(288), 288); + fn test_next_anchor_bucket_height() { + assert_eq!(next_anchor_bucket_height(0, 144), 0); + assert_eq!(next_anchor_bucket_height(1, 144), 144); + assert_eq!(next_anchor_bucket_height(143, 144), 144); + assert_eq!(next_anchor_bucket_height(144, 144), 144); + assert_eq!(next_anchor_bucket_height(145, 144), 288); + assert_eq!(next_anchor_bucket_height(145, 4), 148); } #[test] - fn test_next_anchor_bucket_height() { - assert_eq!(next_anchor_bucket_height(0), 0); - assert_eq!(next_anchor_bucket_height(1), 144); - assert_eq!(next_anchor_bucket_height(143), 144); - assert_eq!(next_anchor_bucket_height(144), 144); - assert_eq!(next_anchor_bucket_height(145), 288); + fn test_migration_anchor_bucket_size() { + assert_eq!(migration_anchor_bucket_size(60_000), 1); + assert_eq!(migration_anchor_bucket_size(900_000), 12); + assert_eq!(migration_anchor_bucket_size(3_600_000), 48); + assert_eq!(migration_anchor_bucket_size(10_800_000), 144); + assert_eq!(migration_anchor_bucket_size(u64::MAX), 144); } #[test] diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index fc9040f49..fdb4a4a29 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -615,6 +615,11 @@ pub async fn plan_transaction( "Anchor height {anchor_height} is ahead of checkpoint {}", h.height, ); + anyhow::ensure!( + !migration || anchor_height == h.height, + "Migration anchor {anchor_height} no longer matches checkpoint {}", + h.height, + ); let (ts, to, ti) = crate::sync::get_tree_state(network, client, anchor_height).await?; let es = ts.to_edge(&SaplingHasher::default()); let eo = to.to_edge(&OrchardHasher::default()); @@ -785,7 +790,7 @@ pub async fn plan_transaction( &eo, &ero, orchard_note_version, - (anchor_height < h.height).then_some(eo.1), + (!migration && anchor_height < h.height).then_some(eo.1), ) .await?; @@ -808,7 +813,7 @@ pub async fn plan_transaction( &ei, &ero, orchard::NoteVersion::V3, - (anchor_height < h.height).then_some(ei.1), + (!migration && anchor_height < h.height).then_some(ei.1), ) .await?; diff --git a/test/services/block_height_service_test.dart b/test/services/block_height_service_test.dart new file mode 100644 index 000000000..1eaf253ab --- /dev/null +++ b/test/services/block_height_service_test.dart @@ -0,0 +1,139 @@ +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/services/block_height_service.dart'; + +void main() { + test('polls only while subscribed', () async { + final requests = StreamController>(); + final service = BlockHeightService( + fetchHeight: () { + final request = Completer(); + requests.add(request); + return request.future; + }, + pollInterval: const Duration(hours: 1), + ); + + final heights = []; + final subscription = service.heights.listen(heights.add); + final request = await requests.stream.first; + + expect(service.subscriberCount, 1); + expect(service.isPolling, isTrue); + + request.complete(42); + await pumpEventQueue(); + expect(heights, [42]); + + await subscription.cancel(); + expect(service.subscriberCount, 0); + expect(service.isPolling, isFalse); + + await requests.close(); + }); + + test('shares one poller and fetches a fresh height for late subscribers', () async { + var polls = 0; + final service = BlockHeightService( + fetchHeight: () async { + polls++; + return 100; + }, + pollInterval: const Duration(hours: 1), + ); + + final firstHeights = []; + final first = service.heights.listen(firstHeights.add); + await pumpEventQueue(); + + final secondHeights = []; + final second = service.heights.listen(secondHeights.add); + await pumpEventQueue(); + + expect(polls, 2); + expect(firstHeights, [100]); + expect(secondHeights, [100]); + expect(service.subscriberCount, 2); + + await first.cancel(); + expect(service.isPolling, isTrue); + await second.cancel(); + expect(service.isPolling, isFalse); + }); + + test('shares an in-flight fetch between new subscribers', () async { + var polls = 0; + final request = Completer(); + final service = BlockHeightService( + fetchHeight: () { + polls++; + return request.future; + }, + pollInterval: const Duration(hours: 1), + ); + + final firstHeights = []; + final secondHeights = []; + final first = service.heights.listen(firstHeights.add); + final second = service.heights.listen(secondHeights.add); + await pumpEventQueue(); + + expect(polls, 1); + request.complete(100); + await pumpEventQueue(); + expect(firstHeights, [100]); + expect(secondHeights, [100]); + + await first.cancel(); + await second.cancel(); + }); + + test('does not register after cancellation during the initial poll', () async { + var polls = 0; + final request = Completer(); + final service = BlockHeightService( + fetchHeight: () { + polls++; + return request.future; + }, + pollInterval: const Duration(milliseconds: 1), + ); + + final subscription = service.heights.listen((_) {}); + await pumpEventQueue(); + expect(polls, 1); + + await subscription.cancel(); + request.complete(100); + await pumpEventQueue(); + + expect(service.subscriberCount, 0); + expect(service.isPolling, isFalse); + expect(polls, 1); + }); + + test('emits only when the block height changes after the initial value', () async { + var polls = 0; + final secondHeight = Completer(); + final service = BlockHeightService( + fetchHeight: () async { + polls++; + if (polls < 3) return 100; + return 101; + }, + pollInterval: const Duration(milliseconds: 1), + ); + + final heights = []; + final subscription = service.heights.listen((height) { + heights.add(height); + if (height == 101) secondHeight.complete(); + }); + + await secondHeight.future.timeout(const Duration(seconds: 1)); + expect(heights, [100, 101]); + + await subscription.cancel(); + }); +} From 9759d6a5fbf2be9025b6ea24a0e7e408a8712347 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 18:36:25 +0200 Subject: [PATCH 048/189] chore: update dependencies --- Cargo.lock | 321 +----------------- Cargo.toml | 12 + macos/Flutter/GeneratedPluginRegistrant.swift | 10 +- .../xcshareddata/swiftpm/Package.resolved | 21 +- rust/Cargo.toml | 9 +- 5 files changed, 38 insertions(+), 335 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5edc2e715..132a3f5fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -893,9 +893,6 @@ name = "bitflags" version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" -dependencies = [ - "serde_core", -] [[package]] name = "bitvec" @@ -2195,17 +2192,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if 1.0.4", - "home", - "windows-sys 0.48.0", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -2314,12 +2300,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - [[package]] name = "flate2" version = "1.1.9" @@ -3387,22 +3367,6 @@ dependencies = [ "tokio-native-tls", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes 1.12.1", - "http-body-util", - "hyper 1.11.0", - "hyper-util", - "native-tls", - "tokio 1.53.1", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.20" @@ -3421,11 +3385,9 @@ dependencies = [ "percent-encoding", "pin-project-lite 0.2.17", "socket2 0.6.5", - "system-configuration 0.7.0", "tokio 1.53.1", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -4114,10 +4076,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ - "bitflags 2.13.1", "libc", - "plain", - "redox_syscall 0.9.0", ] [[package]] @@ -4412,12 +4371,6 @@ dependencies = [ "pxfm", ] -[[package]] -name = "multimap" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" - [[package]] name = "native-tls" version = "0.2.18" @@ -4845,7 +4798,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if 1.0.4", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", "windows-link", ] @@ -4945,17 +4898,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap 2.14.0", -] - [[package]] name = "phf" version = "0.11.3" @@ -5074,12 +5016,6 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - [[package]] name = "polling" version = "3.11.0" @@ -5172,16 +5108,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.119", -] - [[package]] name = "primeorder" version = "0.13.6" @@ -5252,27 +5178,6 @@ dependencies = [ "prost-derive", ] -[[package]] -name = "prost-build" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" -dependencies = [ - "heck 0.5.0", - "itertools 0.14.0", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "pulldown-cmark", - "pulldown-cmark-to-cmark", - "regex", - "syn 2.0.119", - "tempfile", -] - [[package]] name = "prost-derive" version = "0.14.4" @@ -5286,15 +5191,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "prost-types" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" -dependencies = [ - "prost", -] - [[package]] name = "protobuf" version = "2.18.2" @@ -5348,26 +5244,6 @@ dependencies = [ "tempdir", ] -[[package]] -name = "pulldown-cmark" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" -dependencies = [ - "bitflags 2.13.1", - "memchr", - "unicase", -] - -[[package]] -name = "pulldown-cmark-to-cmark" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" -dependencies = [ - "pulldown-cmark", -] - [[package]] name = "pwd-grp" version = "1.0.2" @@ -5790,15 +5666,6 @@ dependencies = [ "bitflags 2.13.1", ] -[[package]] -name = "redox_syscall" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759" -dependencies = [ - "bitflags 2.13.1", -] - [[package]] name = "redox_users" version = "0.5.2" @@ -5889,7 +5756,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", - "hyper-tls 0.5.0", + "hyper-tls", "ipnet", "js-sys", "log", @@ -5903,7 +5770,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration 0.5.1", + "system-configuration", "tokio 1.53.1", "tokio-native-tls", "tower-service", @@ -5922,20 +5789,15 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes 1.12.1", - "encoding_rs", "futures-core", - "h2 0.4.15", "http 1.4.2", "http-body 1.1.0", "http-body-util", "hyper 1.11.0", "hyper-rustls", - "hyper-tls 0.6.0", "hyper-util", "js-sys", "log", - "mime", - "native-tls", "percent-encoding", "pin-project-lite 0.2.17", "quinn", @@ -5946,7 +5808,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio 1.53.1", - "tokio-native-tls", "tokio-rustls", "tower", "tower-http", @@ -6123,7 +5984,6 @@ dependencies = [ "tokio-util", "tonic", "tonic-prost", - "tonic-prost-build", "tor-rtcompat", "tower", "tracing", @@ -6974,8 +6834,6 @@ checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", "sqlx-sqlite", ] @@ -7003,7 +6861,6 @@ dependencies = [ "once_cell", "percent-encoding", "serde", - "serde_json", "sha2 0.10.9", "smallvec", "thiserror 2.0.19", @@ -7043,93 +6900,12 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", "sqlx-sqlite", "syn 2.0.119", "tokio 1.53.1", "url", ] -[[package]] -name = "sqlx-mysql" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" -dependencies = [ - "atoi", - "base64 0.22.1", - "bitflags 2.13.1", - "byteorder", - "bytes 1.12.1", - "crc", - "digest 0.10.7", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac 0.12.1", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "percent-encoding", - "rand 0.8.7", - "rsa", - "serde", - "sha1", - "sha2 0.10.9", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 2.0.19", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-postgres" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" -dependencies = [ - "atoi", - "base64 0.22.1", - "bitflags 2.13.1", - "byteorder", - "crc", - "dotenvy", - "etcetera", - "futures-channel", - "futures-core", - "futures-util", - "hex", - "hkdf", - "hmac 0.12.1", - "home", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "rand 0.8.7", - "serde", - "serde_json", - "sha2 0.10.9", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 2.0.19", - "tracing", - "whoami", -] - [[package]] name = "sqlx-sqlite" version = "0.8.6" @@ -7207,17 +6983,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", -] - [[package]] name = "strsim" version = "0.10.0" @@ -7324,18 +7089,7 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys 0.5.0", -] - -[[package]] -name = "system-configuration" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" -dependencies = [ - "bitflags 2.13.1", - "core-foundation 0.9.4", - "system-configuration-sys 0.6.0", + "system-configuration-sys", ] [[package]] @@ -7348,16 +7102,6 @@ dependencies = [ "libc", ] -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" @@ -7566,7 +7310,6 @@ dependencies = [ "bytes 1.12.1", "libc", "mio 1.2.2", - "parking_lot", "pin-project-lite 0.2.17", "signal-hook-registry", "socket2 0.6.5", @@ -7766,18 +7509,6 @@ dependencies = [ "webpki-roots 1.0.9", ] -[[package]] -name = "tonic-build" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" -dependencies = [ - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "tonic-prost" version = "0.14.6" @@ -7789,22 +7520,6 @@ dependencies = [ "tonic", ] -[[package]] -name = "tonic-prost-build" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "prost-types", - "quote", - "syn 2.0.119", - "tempfile", - "tonic-build", -] - [[package]] name = "tor-async-utils" version = "0.31.0" @@ -8983,12 +8698,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.24" @@ -9004,12 +8713,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-properties" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" - [[package]] name = "unicode-segmentation" version = "1.13.3" @@ -9221,12 +8924,6 @@ dependencies = [ "wit-bindgen", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasix" version = "0.13.2" @@ -9344,16 +9041,6 @@ dependencies = [ "rustix 0.38.44", ] -[[package]] -name = "whoami" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", -] - [[package]] name = "widestring" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 2ff7c2da8..777c0ae1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,18 @@ members = [ ] resolver = "2" +[profile.dev] +debug = 1 + +[profile.dev.package."*"] +debug = 0 + +[profile.test] +debug = 1 + +[profile.test.package."*"] +debug = 0 + [patch.crates-io] # -- ZSA support branches -- orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "4cf06bc19e52d1e8e43438cdbdd703ac2565bff6" } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 53b026cd6..4795fec64 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -4,6 +4,7 @@ import FlutterMacOS import Foundation + import device_info_plus import file_picker import file_selector_macos @@ -20,15 +21,12 @@ import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - DeviceInfoPlusMacosPlugin.register( - with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterContactsPlugin.register(with: registry.registrar(forPlugin: "FlutterContactsPlugin")) - InAppWebViewFlutterPlugin.register( - with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) - FlutterPasskeyServicePlugin.register( - with: registry.registrar(forPlugin: "FlutterPasskeyServicePlugin")) + InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + FlutterPasskeyServicePlugin.register(with: registry.registrar(forPlugin: "FlutterPasskeyServicePlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) diff --git a/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved index 100cf7b26..3352df210 100644 --- a/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/app-check.git", "state" : { - "revision" : "61b85103a1aeed8218f17c794687781505fbbef5", - "version" : "11.2.0" + "revision" : "3e33dd27dd4c69bd81c7c81fe61d8ccf58846902", + "version" : "11.3.1" } }, { @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleUtilities.git", "state" : { - "revision" : "60da361632d0de02786f709bdc0c4df340f7613e", - "version" : "8.1.0" + "revision" : "9f183ae842be978784f2963a343682e0c46d8fb3", + "version" : "8.1.2" } }, { @@ -54,13 +54,22 @@ "version" : "4.1.1" } }, + { + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", + "version" : "101.0.0" + } + }, { "identity" : "promises", "kind" : "remoteSourceControl", "location" : "https://github.com/google/promises.git", "state" : { - "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", - "version" : "2.4.0" + "revision" : "f4a19a3c313dc2616c70bb49d29a799fb16be837", + "version" : "2.4.1" } } ], diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 479fdcca4..a9a639064 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -36,8 +36,8 @@ futures = "0.3" serde = "1.0" serde_json = "1.0" serde_with = {version = "3.17", features = ["hex"]} -sqlx = {version = "0.8", features = ["runtime-tokio", "sqlite", "macros", "migrate"]} -tokio = {version = "1", features = ["full"]} +sqlx = {version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"]} +tokio = {version = "1", features = ["io-util", "macros", "net", "rt-multi-thread", "sync", "time"]} tokio-rustls = "0.26" tokio-stream = "0.1" tokio-util = "0.7" @@ -47,7 +47,7 @@ arti-client = {version = "0.31", features = ["tokio", "native-tls", "onion-servi httparse = "1.10.1" hyper-util = {version = "0.1", features = ["tokio"]} rayon = "1.10" -reqwest = {version = "0.12", features = ["json", "rustls-tls", "socks"]} +reqwest = {version = "0.12", default-features = false, features = ["json", "rustls-tls", "socks"]} rhai = {version = "1.25", features = ["sync", "serde"]} zip = {version = "2", default-features = false, features = ["deflate"]} tokio-socks = "0.5.2" @@ -143,9 +143,6 @@ unexpected_cfgs = {level = "warn", check-cfg = ['cfg(frb_expand)']} chrono = "0.4" rand = "0.6" -[build-dependencies] -tonic-prost-build = "0.14" - [features] default = ["flutter"] flutter = ["flutter_rust_bridge"] From 85d17a1118f84c834839a6867f4130d0f30608b6 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 20:48:00 +0200 Subject: [PATCH 049/189] fix: add error log printer utility --- lib/error_log_printer.dart | 26 ++++++++++++++++++++++++ lib/main.dart | 3 ++- test/error_log_printer_test.dart | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 lib/error_log_printer.dart create mode 100644 test/error_log_printer_test.dart diff --git a/lib/error_log_printer.dart b/lib/error_log_printer.dart new file mode 100644 index 000000000..e48d387f4 --- /dev/null +++ b/lib/error_log_printer.dart @@ -0,0 +1,26 @@ +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:logger/logger.dart'; + +final _unknownRustFrame = RegExp(r'^[ \t]*\d+:[ \t]+[ \t]*$'); + +String omitUnknownRustFrames(String message) { + return message.split('\n').where((line) => !_unknownRustFrame.hasMatch(line)).join('\n'); +} + +class ErrorLogPrinter extends PrettyPrinter { + @override + List log(LogEvent event) { + final error = event.error; + if (error is! AnyhowException) return super.log(event); + + return super.log( + LogEvent( + event.level, + event.message, + time: event.time, + error: AnyhowException(omitUnknownRustFrames(error.message)), + stackTrace: event.stackTrace, + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 46db5cf04..869d8eaa6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:toastification/toastification.dart'; +import 'package:zkool/error_log_printer.dart'; import 'package:zkool/router.dart'; import 'package:zkool/src/rust/api/network.dart'; import 'package:zkool/src/rust/api/plugin.dart'; @@ -13,7 +14,7 @@ import 'package:zkool/src/rust/frb_generated.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; -final logger = Logger(filter: ProductionFilter()); +final logger = Logger(filter: ProductionFilter(), printer: ErrorLogPrinter()); const String appName = "zkool"; diff --git a/test/error_log_printer_test.dart b/test/error_log_printer_test.dart new file mode 100644 index 000000000..345b89182 --- /dev/null +++ b/test/error_log_printer_test.dart @@ -0,0 +1,34 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/error_log_printer.dart'; + +void main() { + test('omits unresolved Rust frames and preserves useful error details', () { + const error = ''' +transport error + +Caused by: + 0: connection error + 1: peer closed connection + +Stack backtrace: + 0: + 1: + 12: resolved_function + 13: +'''; + + expect( + omitUnknownRustFrames(error), + ''' +transport error + +Caused by: + 0: connection error + 1: peer closed connection + +Stack backtrace: + 12: resolved_function +''', + ); + }); +} From b28998e7ee91cfa435bf99b70e7f90762877022c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 30 Jul 2026 22:56:24 +0200 Subject: [PATCH 050/189] feat: identify migration txs in history --- lib/utils.dart | 2 ++ rust/src/memo.rs | 87 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/lib/utils.dart b/lib/utils.dart index 26c9cf38b..65602367e 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -198,6 +198,8 @@ String compactBetween(DateTime from, DateTime to) { return (Colors.blue, Icons.shield, "Shield"); case 12: return (Colors.grey, Icons.drag_handle, "T. Self Transfer"); + case 16: + return (Colors.teal, Icons.sync_alt, "Migration"); default: return (Colors.grey, Icons.question_mark, "Unknown"); } diff --git a/rust/src/memo.rs b/rust/src/memo.rs index 7f67fd68b..c9c623fe3 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -21,6 +21,8 @@ use crate::{ Client, }; +const TX_TYPE_MIGRATION: u8 = 16; + pub async fn fetch_tx_details( network: &Network, connection: &mut SqliteConnection, @@ -105,21 +107,47 @@ async fn summarize_tx( Ok((2, value, asset_id, zsa_value)) } else { // self transfer - let has_tspend = sqlx::query("SELECT 1 FROM spends WHERE tx = ? AND pool = 0") - .bind(tx) - .fetch_optional(&mut *connection) - .await? - .is_some(); - let has_tnote = sqlx::query("SELECT 1 FROM notes WHERE tx = ? AND pool = 0") - .bind(tx) - .fetch_optional(&mut *connection) - .await? - .is_some(); - let tpe: u8 = (if has_tspend { 8 } else { 0 }) | (if has_tnote { 4 } else { 0 }); + let (has_tspend, has_tnote, has_ospend, has_inote) = sqlx::query( + "SELECT + EXISTS(SELECT 1 FROM spends WHERE tx = ? AND pool = 0), + EXISTS(SELECT 1 FROM notes WHERE tx = ? AND pool = 0), + EXISTS(SELECT 1 FROM spends WHERE tx = ? AND pool = 2), + EXISTS(SELECT 1 FROM notes WHERE tx = ? AND pool = 3)", + ) + .bind(tx) + .bind(tx) + .bind(tx) + .bind(tx) + .map(|row: SqliteRow| { + ( + row.get::(0), + row.get::(1), + row.get::(2), + row.get::(3), + ) + }) + .fetch_one(&mut *connection) + .await?; + let tpe = self_transfer_type(value, fee, has_tspend, has_tnote, has_ospend, has_inote); Ok((tpe, value, asset_id, zsa_value)) } } +fn self_transfer_type( + value: i64, + fee: i64, + has_tspend: bool, + has_tnote: bool, + has_ospend: bool, + has_inote: bool, +) -> u8 { + if has_ospend && has_inote && value == -fee { + TX_TYPE_MIGRATION + } else { + (if has_tspend { 8 } else { 0 }) | (if has_tnote { 4 } else { 0 }) + } +} + /// Try ZSA decryption using the raw 612-byte enc_ciphertext with OrchardZSADomain. /// Called when vanilla OrchardDomain decryption fails and raw ZSA ciphertext is available. fn try_zsa_decrypt( @@ -555,3 +583,40 @@ async fn store_output( Ok(id_output) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn orchard_to_ironwood_fee_only_transfer_is_migration() { + assert_eq!( + self_transfer_type(-10_000, 10_000, false, false, true, true), + TX_TYPE_MIGRATION + ); + } + + #[test] + fn migration_requires_exact_fee_value_and_both_pools() { + assert_eq!( + self_transfer_type(-9_999, 10_000, false, false, true, true), + 0 + ); + assert_eq!( + self_transfer_type(-10_000, 10_000, false, false, true, false), + 0 + ); + assert_eq!( + self_transfer_type(-10_000, 10_000, false, false, false, true), + 0 + ); + } + + #[test] + fn existing_transparent_self_transfer_types_are_preserved() { + assert_eq!( + self_transfer_type(-10_000, 10_000, true, true, false, false), + 12 + ); + } +} From 995dd4d424c95d4b8248125e815b72bd45728f00 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Fri, 31 Jul 2026 09:25:37 +0200 Subject: [PATCH 051/189] chore: format generated Rust bindings --- lib/src/rust/api/account.dart | 238 +- lib/src/rust/api/account.freezed.dart | 827 ++- lib/src/rust/api/coin.dart | 25 +- lib/src/rust/api/coin.freezed.dart | 69 +- lib/src/rust/api/contacts.dart | 40 +- lib/src/rust/api/contacts.freezed.dart | 65 +- lib/src/rust/api/db.dart | 39 +- lib/src/rust/api/frost.dart | 108 +- lib/src/rust/api/frost.freezed.dart | 324 +- lib/src/rust/api/init.dart | 6 +- lib/src/rust/api/init.freezed.dart | 17 +- lib/src/rust/api/issuance.dart | 8 +- lib/src/rust/api/key.dart | 22 +- lib/src/rust/api/mempool.dart | 19 +- lib/src/rust/api/mempool.freezed.dart | 43 +- lib/src/rust/api/migrate.dart | 9 +- lib/src/rust/api/migrate.freezed.dart | 69 +- lib/src/rust/api/network.dart | 32 +- lib/src/rust/api/network.freezed.dart | 149 +- lib/src/rust/api/openalias.dart | 29 +- lib/src/rust/api/pay.dart | 82 +- lib/src/rust/api/pay.freezed.dart | 174 +- lib/src/rust/api/plugin.dart | 21 +- lib/src/rust/api/plugin.freezed.dart | 200 +- lib/src/rust/api/raptor.dart | 16 +- lib/src/rust/api/sapling.dart | 11 +- lib/src/rust/api/sweep.dart | 6 +- lib/src/rust/api/sync.dart | 30 +- lib/src/rust/api/transaction.dart | 44 +- lib/src/rust/api/vault.dart | 29 +- lib/src/rust/api/zsa.dart | 14 +- lib/src/rust/api/zsa.freezed.dart | 122 +- lib/src/rust/frb_generated.dart | 7892 +++++++++++++----------- lib/src/rust/frb_generated.io.dart | 465 +- lib/src/rust/frb_generated.web.dart | 534 +- lib/src/rust/io.dart | 7 +- lib/src/rust/pay.dart | 26 +- lib/src/rust/pay/error.freezed.dart | 54 +- 38 files changed, 7208 insertions(+), 4657 deletions(-) diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index 79a6fefa1..d13212c6a 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -14,107 +14,171 @@ part 'account.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `get_ledger` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt` -Future getAccountPools({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountPools(account: account, c: c); +Future getAccountPools({required int account, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountPools(account: account, c: c); -Future getAccountUfvk({required int account, required int pools, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountUfvk(account: account, pools: pools, c: c); +Future getAccountUfvk( + {required int account, required int pools, required Coin c}) => + RustLib.instance.api + .crateApiAccountGetAccountUfvk(account: account, pools: pools, c: c); -Future getAccountSeed({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountSeed(account: account, c: c); +Future getAccountSeed({required int account, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountSeed(account: account, c: c); -Future getAccountFingerprint({required int account, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountFingerprint(account: account, c: c); +Future getAccountFingerprint( + {required int account, required Coin c}) => + RustLib.instance.api + .crateApiAccountGetAccountFingerprint(account: account, c: c); -String uaFromUfvk({required String ufvk, int? di, required Coin c}) => RustLib.instance.api.crateApiAccountUaFromUfvk(ufvk: ufvk, di: di, c: c); +String uaFromUfvk({required String ufvk, int? di, required Coin c}) => + RustLib.instance.api.crateApiAccountUaFromUfvk(ufvk: ufvk, di: di, c: c); -Receivers receiversFromUa({required String ua, required Coin c}) => RustLib.instance.api.crateApiAccountReceiversFromUa(ua: ua, c: c); +Receivers receiversFromUa({required String ua, required Coin c}) => + RustLib.instance.api.crateApiAccountReceiversFromUa(ua: ua, c: c); -Future> listAccounts({required Coin c}) => RustLib.instance.api.crateApiAccountListAccounts(c: c); +Future> listAccounts({required Coin c}) => + RustLib.instance.api.crateApiAccountListAccounts(c: c); -Future updateAccount({required AccountUpdate update, required Coin c}) => RustLib.instance.api.crateApiAccountUpdateAccount(update: update, c: c); +Future updateAccount({required AccountUpdate update, required Coin c}) => + RustLib.instance.api.crateApiAccountUpdateAccount(update: update, c: c); -Future deleteAccount({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteAccount(account: account, c: c); +Future deleteAccount({required int account, required Coin c}) => + RustLib.instance.api.crateApiAccountDeleteAccount(account: account, c: c); -Future reorderAccount({required int oldPosition, required int newPosition, required Coin c}) => - RustLib.instance.api.crateApiAccountReorderAccount(oldPosition: oldPosition, newPosition: newPosition, c: c); +Future reorderAccount( + {required int oldPosition, + required int newPosition, + required Coin c}) => + RustLib.instance.api.crateApiAccountReorderAccount( + oldPosition: oldPosition, newPosition: newPosition, c: c); -Future newAccount({required NewAccount na, required Coin c}) => RustLib.instance.api.crateApiAccountNewAccount(na: na, c: c); +Future newAccount({required NewAccount na, required Coin c}) => + RustLib.instance.api.crateApiAccountNewAccount(na: na, c: c); -Future hasTransparentPubKey({required Coin c}) => RustLib.instance.api.crateApiAccountHasTransparentPubKey(c: c); +Future hasTransparentPubKey({required Coin c}) => + RustLib.instance.api.crateApiAccountHasTransparentPubKey(c: c); -Future generateNextDindex({required Coin c}) => RustLib.instance.api.crateApiAccountGenerateNextDindex(c: c); +Future generateNextDindex({required Coin c}) => + RustLib.instance.api.crateApiAccountGenerateNextDindex(c: c); -Future generateNextChangeAddress({required Coin c}) => RustLib.instance.api.crateApiAccountGenerateNextChangeAddress(c: c); +Future generateNextChangeAddress({required Coin c}) => + RustLib.instance.api.crateApiAccountGenerateNextChangeAddress(c: c); -Future resetSync({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountResetSync(id: id, c: c); +Future resetSync({required int id, required Coin c}) => + RustLib.instance.api.crateApiAccountResetSync(id: id, c: c); -Future removeAccount({required int accountId, required Coin c}) => RustLib.instance.api.crateApiAccountRemoveAccount(accountId: accountId, c: c); +Future removeAccount({required int accountId, required Coin c}) => + RustLib.instance.api + .crateApiAccountRemoveAccount(accountId: accountId, c: c); -Future> listTxHistory({required Coin c}) => RustLib.instance.api.crateApiAccountListTxHistory(c: c); +Future> listTxHistory({required Coin c}) => + RustLib.instance.api.crateApiAccountListTxHistory(c: c); -Future> listMemos({required Coin c}) => RustLib.instance.api.crateApiAccountListMemos(c: c); +Future> listMemos({required Coin c}) => + RustLib.instance.api.crateApiAccountListMemos(c: c); -Future getAddresses({required int uaPools, required Coin c}) => RustLib.instance.api.crateApiAccountGetAddresses(uaPools: uaPools, c: c); +Future getAddresses({required int uaPools, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAddresses(uaPools: uaPools, c: c); -Future getAccountAddresses({required int account, required int uaPools, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountAddresses(account: account, uaPools: uaPools, c: c); +Future getAccountAddresses( + {required int account, required int uaPools, required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountAddresses( + account: account, uaPools: uaPools, c: c); -Future getTxDetails({required int idTx, required Coin c}) => RustLib.instance.api.crateApiAccountGetTxDetails(idTx: idTx, c: c); +Future getTxDetails({required int idTx, required Coin c}) => + RustLib.instance.api.crateApiAccountGetTxDetails(idTx: idTx, c: c); -Future> listNotes({required Coin c}) => RustLib.instance.api.crateApiAccountListNotes(c: c); +Future> listNotes({required Coin c}) => + RustLib.instance.api.crateApiAccountListNotes(c: c); -Future lockNote({required int id, required bool locked, required Coin c}) => RustLib.instance.api.crateApiAccountLockNote(id: id, locked: locked, c: c); +Future lockNote( + {required int id, required bool locked, required Coin c}) => + RustLib.instance.api.crateApiAccountLockNote(id: id, locked: locked, c: c); -Future> fetchTransparentAddressTxCount({required Coin c}) => RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); +Future> fetchTransparentAddressTxCount( + {required Coin c}) => + RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); -Future> fetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}) => - RustLib.instance.api.crateApiAccountFetchAddressTxCount(c: c, aggregate: aggregate, poolFilter: poolFilter); +Future> fetchAddressTxCount( + {required Coin c, required bool aggregate, required int poolFilter}) => + RustLib.instance.api.crateApiAccountFetchAddressTxCount( + c: c, aggregate: aggregate, poolFilter: poolFilter); -Future exportAccount({required int id, required String passphrase, required Coin c}) => - RustLib.instance.api.crateApiAccountExportAccount(id: id, passphrase: passphrase, c: c); +Future exportAccount( + {required int id, required String passphrase, required Coin c}) => + RustLib.instance.api + .crateApiAccountExportAccount(id: id, passphrase: passphrase, c: c); -Future importAccount({required String passphrase, required List data, required Coin c}) => - RustLib.instance.api.crateApiAccountImportAccount(passphrase: passphrase, data: data, c: c); +Future importAccount( + {required String passphrase, + required List data, + required Coin c}) => + RustLib.instance.api + .crateApiAccountImportAccount(passphrase: passphrase, data: data, c: c); -Future printKeys({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountPrintKeys(id: id, c: c); +Future printKeys({required int id, required Coin c}) => + RustLib.instance.api.crateApiAccountPrintKeys(id: id, c: c); -Future getAccountFrostParams({required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountFrostParams(c: c); +Future getAccountFrostParams({required Coin c}) => + RustLib.instance.api.crateApiAccountGetAccountFrostParams(c: c); -Future> listFolders({required Coin c}) => RustLib.instance.api.crateApiAccountListFolders(c: c); +Future> listFolders({required Coin c}) => + RustLib.instance.api.crateApiAccountListFolders(c: c); -Future createNewFolder({required String name, required Coin c}) => RustLib.instance.api.crateApiAccountCreateNewFolder(name: name, c: c); +Future createNewFolder({required String name, required Coin c}) => + RustLib.instance.api.crateApiAccountCreateNewFolder(name: name, c: c); -Future renameFolder({required int id, required String name, required Coin c}) => +Future renameFolder( + {required int id, required String name, required Coin c}) => RustLib.instance.api.crateApiAccountRenameFolder(id: id, name: name, c: c); -Future deleteFolders({required List ids, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteFolders(ids: ids, c: c); +Future deleteFolders({required List ids, required Coin c}) => + RustLib.instance.api.crateApiAccountDeleteFolders(ids: ids, c: c); -Future> listCategories({required Coin c}) => RustLib.instance.api.crateApiAccountListCategories(c: c); +Future> listCategories({required Coin c}) => + RustLib.instance.api.crateApiAccountListCategories(c: c); -Future createNewCategory({required Category category, required Coin c}) => RustLib.instance.api.crateApiAccountCreateNewCategory(category: category, c: c); +Future createNewCategory({required Category category, required Coin c}) => + RustLib.instance.api + .crateApiAccountCreateNewCategory(category: category, c: c); -Future renameCategory({required Category category, required Coin c}) => RustLib.instance.api.crateApiAccountRenameCategory(category: category, c: c); +Future renameCategory({required Category category, required Coin c}) => + RustLib.instance.api + .crateApiAccountRenameCategory(category: category, c: c); -Future deleteCategories({required List ids, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteCategories(ids: ids, c: c); +Future deleteCategories({required List ids, required Coin c}) => + RustLib.instance.api.crateApiAccountDeleteCategories(ids: ids, c: c); -Future getExportedData({required int type, required Coin c}) => RustLib.instance.api.crateApiAccountGetExportedData(type: type, c: c); +Future getExportedData({required int type, required Coin c}) => + RustLib.instance.api.crateApiAccountGetExportedData(type: type, c: c); -Future lockRecentNotes({required int height, required int threshold, required Coin c}) => - RustLib.instance.api.crateApiAccountLockRecentNotes(height: height, threshold: threshold, c: c); +Future lockRecentNotes( + {required int height, required int threshold, required Coin c}) => + RustLib.instance.api.crateApiAccountLockRecentNotes( + height: height, threshold: threshold, c: c); -Future unlockAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); +Future unlockAllNotes({required Coin c}) => + RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); -Future toggleAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountToggleAllNotes(c: c); +Future toggleAllNotes({required Coin c}) => + RustLib.instance.api.crateApiAccountToggleAllNotes(c: c); -Future maxSpendable({required Coin c}) => RustLib.instance.api.crateApiAccountMaxSpendable(c: c); +Future maxSpendable({required Coin c}) => + RustLib.instance.api.crateApiAccountMaxSpendable(c: c); -Future showLedgerSaplingAddress({required Coin c}) => RustLib.instance.api.crateApiAccountShowLedgerSaplingAddress(c: c); +Future showLedgerSaplingAddress({required Coin c}) => + RustLib.instance.api.crateApiAccountShowLedgerSaplingAddress(c: c); -Future showLedgerTransparentAddress({required Coin c}) => RustLib.instance.api.crateApiAccountShowLedgerTransparentAddress(c: c); +Future showLedgerTransparentAddress({required Coin c}) => + RustLib.instance.api.crateApiAccountShowLedgerTransparentAddress(c: c); -Stream signLedgerTransaction({required PcztPackage package, required Coin c}) => - RustLib.instance.api.crateApiAccountSignLedgerTransaction(package: package, c: c); +Stream signLedgerTransaction( + {required PcztPackage package, required Coin c}) => + RustLib.instance.api + .crateApiAccountSignLedgerTransaction(package: package, c: c); -Future dummyExport({required SigningEvent a}) => RustLib.instance.api.crateApiAccountDummyExport(a: a); +Future dummyExport({required SigningEvent a}) => + RustLib.instance.api.crateApiAccountDummyExport(a: a); @freezed sealed class Account with _$Account { @@ -172,7 +236,12 @@ class Addresses { }); @override - int get hashCode => taddr.hashCode ^ saddr.hashCode ^ oaddr.hashCode ^ ua.hashCode ^ diversifierIndex.hashCode; + int get hashCode => + taddr.hashCode ^ + saddr.hashCode ^ + oaddr.hashCode ^ + ua.hashCode ^ + diversifierIndex.hashCode; @override bool operator ==(Object other) => @@ -258,14 +327,20 @@ class Receivers { this.oaddr, }); - static Future default_() => RustLib.instance.api.crateApiAccountReceiversDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountReceiversDefault(); @override int get hashCode => taddr.hashCode ^ saddr.hashCode ^ oaddr.hashCode; @override bool operator ==(Object other) => - identical(this, other) || other is Receivers && runtimeType == other.runtimeType && taddr == other.taddr && saddr == other.saddr && oaddr == other.oaddr; + identical(this, other) || + other is Receivers && + runtimeType == other.runtimeType && + taddr == other.taddr && + saddr == other.saddr && + oaddr == other.oaddr; } @freezed @@ -297,7 +372,14 @@ class TAddressTxCount { }); @override - int get hashCode => pool.hashCode ^ address.hashCode ^ scope.hashCode ^ dindex.hashCode ^ amount.hashCode ^ txCount.hashCode ^ time.hashCode; + int get hashCode => + pool.hashCode ^ + address.hashCode ^ + scope.hashCode ^ + dindex.hashCode ^ + amount.hashCode ^ + txCount.hashCode ^ + time.hashCode; @override bool operator ==(Object other) => @@ -362,7 +444,8 @@ class TxAccount { this.userMemo, }); - static Future default_() => RustLib.instance.api.crateApiAccountTxAccountDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountTxAccountDefault(); @override int get hashCode => @@ -413,10 +496,16 @@ class TxMemo { required this.memoBytes, }); - static Future default_() => RustLib.instance.api.crateApiAccountTxMemoDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountTxMemoDefault(); @override - int get hashCode => note.hashCode ^ output.hashCode ^ pool.hashCode ^ memo.hashCode ^ memoBytes.hashCode; + int get hashCode => + note.hashCode ^ + output.hashCode ^ + pool.hashCode ^ + memo.hashCode ^ + memoBytes.hashCode; @override bool operator ==(Object other) => @@ -459,7 +548,8 @@ class TxNote { required this.assetDisplay, }); - static Future default_() => RustLib.instance.api.crateApiAccountTxNoteDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountTxNoteDefault(); @override int get hashCode => @@ -512,10 +602,17 @@ class TxOutput { this.contactName, }); - static Future default_() => RustLib.instance.api.crateApiAccountTxOutputDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountTxOutputDefault(); @override - int get hashCode => id.hashCode ^ pool.hashCode ^ height.hashCode ^ value.hashCode ^ address.hashCode ^ contactName.hashCode; + int get hashCode => + id.hashCode ^ + pool.hashCode ^ + height.hashCode ^ + value.hashCode ^ + address.hashCode ^ + contactName.hashCode; @override bool operator ==(Object other) => @@ -547,10 +644,17 @@ class TxSpend { required this.assetDisplay, }); - static Future default_() => RustLib.instance.api.crateApiAccountTxSpendDefault(); + static Future default_() => + RustLib.instance.api.crateApiAccountTxSpendDefault(); @override - int get hashCode => id.hashCode ^ pool.hashCode ^ height.hashCode ^ value.hashCode ^ idAsset.hashCode ^ assetDisplay.hashCode; + int get hashCode => + id.hashCode ^ + pool.hashCode ^ + height.hashCode ^ + value.hashCode ^ + idAsset.hashCode ^ + assetDisplay.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/account.freezed.dart b/lib/src/rust/api/account.freezed.dart index 1a4003e5f..20e59b151 100644 --- a/lib/src/rust/api/account.freezed.dart +++ b/lib/src/rust/api/account.freezed.dart @@ -39,7 +39,8 @@ mixin _$Account { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountCopyWith get copyWith => _$AccountCopyWithImpl(this as Account, _$identity); + $AccountCopyWith get copyWith => + _$AccountCopyWithImpl(this as Account, _$identity); @override bool operator ==(Object other) { @@ -50,18 +51,22 @@ mixin _$Account { (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && (identical(other.seed, seed) || other.seed == seed) && - (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && + (identical(other.passphrase, passphrase) || + other.passphrase == passphrase) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.dindex, dindex) || other.dindex == dindex) && const DeepCollectionEquality().equals(other.icon, icon) && - (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && + (identical(other.useInternal, useInternal) || + other.useInternal == useInternal) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && - (identical(other.position, position) || other.position == position) && + (identical(other.position, position) || + other.position == position) && (identical(other.hidden, hidden) || other.hidden == hidden) && (identical(other.saved, saved) || other.saved == saved) && (identical(other.enabled, enabled) || other.enabled == enabled) && - (identical(other.internal, internal) || other.internal == internal) && + (identical(other.internal, internal) || + other.internal == internal) && (identical(other.hw, hw) || other.hw == hw) && (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && @@ -101,7 +106,8 @@ mixin _$Account { /// @nodoc abstract mixin class $AccountCopyWith<$Res> { - factory $AccountCopyWith(Account value, $Res Function(Account) _then) = _$AccountCopyWithImpl; + factory $AccountCopyWith(Account value, $Res Function(Account) _then) = + _$AccountCopyWithImpl; @useResult $Res call( {int coin, @@ -347,16 +353,54 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult maybeWhen( - TResult Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, - Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance)? + TResult Function( + int coin, + int id, + String name, + String? seed, + String? passphrase, + int aindex, + int dindex, + Uint8List? icon, + bool useInternal, + int birth, + Folder folder, + int position, + bool hidden, + bool saved, + bool enabled, + bool internal, + int hw, + int height, + int time, + BigInt balance)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Account() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, - _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); + return $default( + _that.coin, + _that.id, + _that.name, + _that.seed, + _that.passphrase, + _that.aindex, + _that.dindex, + _that.icon, + _that.useInternal, + _that.birth, + _that.folder, + _that.position, + _that.hidden, + _that.saved, + _that.enabled, + _that.internal, + _that.hw, + _that.height, + _that.time, + _that.balance); case _: return orElse(); } @@ -377,15 +421,53 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult when( - TResult Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, - Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance) + TResult Function( + int coin, + int id, + String name, + String? seed, + String? passphrase, + int aindex, + int dindex, + Uint8List? icon, + bool useInternal, + int birth, + Folder folder, + int position, + bool hidden, + bool saved, + bool enabled, + bool internal, + int hw, + int height, + int time, + BigInt balance) $default, ) { final _that = this; switch (_that) { case _Account(): - return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, - _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); + return $default( + _that.coin, + _that.id, + _that.name, + _that.seed, + _that.passphrase, + _that.aindex, + _that.dindex, + _that.icon, + _that.useInternal, + _that.birth, + _that.folder, + _that.position, + _that.hidden, + _that.saved, + _that.enabled, + _that.internal, + _that.hw, + _that.height, + _that.time, + _that.balance); } } @@ -403,15 +485,53 @@ extension AccountPatterns on Account { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int coin, int id, String name, String? seed, String? passphrase, int aindex, int dindex, Uint8List? icon, bool useInternal, int birth, - Folder folder, int position, bool hidden, bool saved, bool enabled, bool internal, int hw, int height, int time, BigInt balance)? + TResult? Function( + int coin, + int id, + String name, + String? seed, + String? passphrase, + int aindex, + int dindex, + Uint8List? icon, + bool useInternal, + int birth, + Folder folder, + int position, + bool hidden, + bool saved, + bool enabled, + bool internal, + int hw, + int height, + int time, + BigInt balance)? $default, ) { final _that = this; switch (_that) { case _Account() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.seed, _that.passphrase, _that.aindex, _that.dindex, _that.icon, _that.useInternal, _that.birth, - _that.folder, _that.position, _that.hidden, _that.saved, _that.enabled, _that.internal, _that.hw, _that.height, _that.time, _that.balance); + return $default( + _that.coin, + _that.id, + _that.name, + _that.seed, + _that.passphrase, + _that.aindex, + _that.dindex, + _that.icon, + _that.useInternal, + _that.birth, + _that.folder, + _that.position, + _that.hidden, + _that.saved, + _that.enabled, + _that.internal, + _that.hw, + _that.height, + _that.time, + _that.balance); case _: return null; } @@ -489,7 +609,8 @@ class _Account implements Account { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountCopyWith<_Account> get copyWith => __$AccountCopyWithImpl<_Account>(this, _$identity); + _$AccountCopyWith<_Account> get copyWith => + __$AccountCopyWithImpl<_Account>(this, _$identity); @override bool operator ==(Object other) { @@ -500,18 +621,22 @@ class _Account implements Account { (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && (identical(other.seed, seed) || other.seed == seed) && - (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && + (identical(other.passphrase, passphrase) || + other.passphrase == passphrase) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.dindex, dindex) || other.dindex == dindex) && const DeepCollectionEquality().equals(other.icon, icon) && - (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && + (identical(other.useInternal, useInternal) || + other.useInternal == useInternal) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && - (identical(other.position, position) || other.position == position) && + (identical(other.position, position) || + other.position == position) && (identical(other.hidden, hidden) || other.hidden == hidden) && (identical(other.saved, saved) || other.saved == saved) && (identical(other.enabled, enabled) || other.enabled == enabled) && - (identical(other.internal, internal) || other.internal == internal) && + (identical(other.internal, internal) || + other.internal == internal) && (identical(other.hw, hw) || other.hw == hw) && (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && @@ -551,7 +676,8 @@ class _Account implements Account { /// @nodoc abstract mixin class _$AccountCopyWith<$Res> implements $AccountCopyWith<$Res> { - factory _$AccountCopyWith(_Account value, $Res Function(_Account) _then) = __$AccountCopyWithImpl; + factory _$AccountCopyWith(_Account value, $Res Function(_Account) _then) = + __$AccountCopyWithImpl; @override @useResult $Res call( @@ -723,7 +849,9 @@ mixin _$AccountUpdate { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountUpdateCopyWith get copyWith => _$AccountUpdateCopyWithImpl(this as AccountUpdate, _$identity); + $AccountUpdateCopyWith get copyWith => + _$AccountUpdateCopyWithImpl( + this as AccountUpdate, _$identity); @override bool operator ==(Object other) { @@ -741,7 +869,16 @@ mixin _$AccountUpdate { } @override - int get hashCode => Object.hash(runtimeType, coin, id, name, const DeepCollectionEquality().hash(icon), birth, folder, hidden, enabled); + int get hashCode => Object.hash( + runtimeType, + coin, + id, + name, + const DeepCollectionEquality().hash(icon), + birth, + folder, + hidden, + enabled); @override String toString() { @@ -751,13 +888,24 @@ mixin _$AccountUpdate { /// @nodoc abstract mixin class $AccountUpdateCopyWith<$Res> { - factory $AccountUpdateCopyWith(AccountUpdate value, $Res Function(AccountUpdate) _then) = _$AccountUpdateCopyWithImpl; + factory $AccountUpdateCopyWith( + AccountUpdate value, $Res Function(AccountUpdate) _then) = + _$AccountUpdateCopyWithImpl; @useResult - $Res call({int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled}); + $Res call( + {int coin, + int id, + String? name, + Uint8List? icon, + int? birth, + int folder, + bool? hidden, + bool? enabled}); } /// @nodoc -class _$AccountUpdateCopyWithImpl<$Res> implements $AccountUpdateCopyWith<$Res> { +class _$AccountUpdateCopyWithImpl<$Res> + implements $AccountUpdateCopyWith<$Res> { _$AccountUpdateCopyWithImpl(this._self, this._then); final AccountUpdate _self; @@ -905,13 +1053,16 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult maybeWhen( - TResult Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled)? $default, { + TResult Function(int coin, int id, String? name, Uint8List? icon, + int? birth, int folder, bool? hidden, bool? enabled)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountUpdate() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, + _that.birth, _that.folder, _that.hidden, _that.enabled); case _: return orElse(); } @@ -932,12 +1083,15 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult when( - TResult Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled) $default, + TResult Function(int coin, int id, String? name, Uint8List? icon, + int? birth, int folder, bool? hidden, bool? enabled) + $default, ) { final _that = this; switch (_that) { case _AccountUpdate(): - return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, + _that.birth, _that.folder, _that.hidden, _that.enabled); } } @@ -955,12 +1109,15 @@ extension AccountUpdatePatterns on AccountUpdate { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled)? $default, + TResult? Function(int coin, int id, String? name, Uint8List? icon, + int? birth, int folder, bool? hidden, bool? enabled)? + $default, ) { final _that = this; switch (_that) { case _AccountUpdate() when $default != null: - return $default(_that.coin, _that.id, _that.name, _that.icon, _that.birth, _that.folder, _that.hidden, _that.enabled); + return $default(_that.coin, _that.id, _that.name, _that.icon, + _that.birth, _that.folder, _that.hidden, _that.enabled); case _: return null; } @@ -970,7 +1127,15 @@ extension AccountUpdatePatterns on AccountUpdate { /// @nodoc class _AccountUpdate implements AccountUpdate { - const _AccountUpdate({required this.coin, required this.id, this.name, this.icon, this.birth, required this.folder, this.hidden, this.enabled}); + const _AccountUpdate( + {required this.coin, + required this.id, + this.name, + this.icon, + this.birth, + required this.folder, + this.hidden, + this.enabled}); @override final int coin; @@ -994,7 +1159,8 @@ class _AccountUpdate implements AccountUpdate { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountUpdateCopyWith<_AccountUpdate> get copyWith => __$AccountUpdateCopyWithImpl<_AccountUpdate>(this, _$identity); + _$AccountUpdateCopyWith<_AccountUpdate> get copyWith => + __$AccountUpdateCopyWithImpl<_AccountUpdate>(this, _$identity); @override bool operator ==(Object other) { @@ -1012,7 +1178,16 @@ class _AccountUpdate implements AccountUpdate { } @override - int get hashCode => Object.hash(runtimeType, coin, id, name, const DeepCollectionEquality().hash(icon), birth, folder, hidden, enabled); + int get hashCode => Object.hash( + runtimeType, + coin, + id, + name, + const DeepCollectionEquality().hash(icon), + birth, + folder, + hidden, + enabled); @override String toString() { @@ -1021,15 +1196,27 @@ class _AccountUpdate implements AccountUpdate { } /// @nodoc -abstract mixin class _$AccountUpdateCopyWith<$Res> implements $AccountUpdateCopyWith<$Res> { - factory _$AccountUpdateCopyWith(_AccountUpdate value, $Res Function(_AccountUpdate) _then) = __$AccountUpdateCopyWithImpl; +abstract mixin class _$AccountUpdateCopyWith<$Res> + implements $AccountUpdateCopyWith<$Res> { + factory _$AccountUpdateCopyWith( + _AccountUpdate value, $Res Function(_AccountUpdate) _then) = + __$AccountUpdateCopyWithImpl; @override @useResult - $Res call({int coin, int id, String? name, Uint8List? icon, int? birth, int folder, bool? hidden, bool? enabled}); + $Res call( + {int coin, + int id, + String? name, + Uint8List? icon, + int? birth, + int folder, + bool? hidden, + bool? enabled}); } /// @nodoc -class __$AccountUpdateCopyWithImpl<$Res> implements _$AccountUpdateCopyWith<$Res> { +class __$AccountUpdateCopyWithImpl<$Res> + implements _$AccountUpdateCopyWith<$Res> { __$AccountUpdateCopyWithImpl(this._self, this._then); final _AccountUpdate _self; @@ -1096,7 +1283,8 @@ mixin _$Category { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $CategoryCopyWith get copyWith => _$CategoryCopyWithImpl(this as Category, _$identity); + $CategoryCopyWith get copyWith => + _$CategoryCopyWithImpl(this as Category, _$identity); @override bool operator ==(Object other) { @@ -1105,7 +1293,8 @@ mixin _$Category { other is Category && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - (identical(other.isIncome, isIncome) || other.isIncome == isIncome)); + (identical(other.isIncome, isIncome) || + other.isIncome == isIncome)); } @override @@ -1119,7 +1308,8 @@ mixin _$Category { /// @nodoc abstract mixin class $CategoryCopyWith<$Res> { - factory $CategoryCopyWith(Category value, $Res Function(Category) _then) = _$CategoryCopyWithImpl; + factory $CategoryCopyWith(Category value, $Res Function(Category) _then) = + _$CategoryCopyWithImpl; @useResult $Res call({int id, String name, bool isIncome}); } @@ -1313,7 +1503,8 @@ extension CategoryPatterns on Category { /// @nodoc class _Category implements Category { - const _Category({required this.id, required this.name, required this.isIncome}); + const _Category( + {required this.id, required this.name, required this.isIncome}); @override final int id; @@ -1327,7 +1518,8 @@ class _Category implements Category { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$CategoryCopyWith<_Category> get copyWith => __$CategoryCopyWithImpl<_Category>(this, _$identity); + _$CategoryCopyWith<_Category> get copyWith => + __$CategoryCopyWithImpl<_Category>(this, _$identity); @override bool operator ==(Object other) { @@ -1336,7 +1528,8 @@ class _Category implements Category { other is _Category && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - (identical(other.isIncome, isIncome) || other.isIncome == isIncome)); + (identical(other.isIncome, isIncome) || + other.isIncome == isIncome)); } @override @@ -1349,8 +1542,10 @@ class _Category implements Category { } /// @nodoc -abstract mixin class _$CategoryCopyWith<$Res> implements $CategoryCopyWith<$Res> { - factory _$CategoryCopyWith(_Category value, $Res Function(_Category) _then) = __$CategoryCopyWithImpl; +abstract mixin class _$CategoryCopyWith<$Res> + implements $CategoryCopyWith<$Res> { + factory _$CategoryCopyWith(_Category value, $Res Function(_Category) _then) = + __$CategoryCopyWithImpl; @override @useResult $Res call({int id, String name, bool isIncome}); @@ -1398,7 +1593,8 @@ mixin _$Folder { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FolderCopyWith get copyWith => _$FolderCopyWithImpl(this as Folder, _$identity); + $FolderCopyWith get copyWith => + _$FolderCopyWithImpl(this as Folder, _$identity); @override bool operator ==(Object other) { @@ -1420,7 +1616,8 @@ mixin _$Folder { /// @nodoc abstract mixin class $FolderCopyWith<$Res> { - factory $FolderCopyWith(Folder value, $Res Function(Folder) _then) = _$FolderCopyWithImpl; + factory $FolderCopyWith(Folder value, $Res Function(Folder) _then) = + _$FolderCopyWithImpl; @useResult $Res call({int id, String name}); } @@ -1621,7 +1818,8 @@ class _Folder implements Folder { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FolderCopyWith<_Folder> get copyWith => __$FolderCopyWithImpl<_Folder>(this, _$identity); + _$FolderCopyWith<_Folder> get copyWith => + __$FolderCopyWithImpl<_Folder>(this, _$identity); @override bool operator ==(Object other) { @@ -1643,7 +1841,8 @@ class _Folder implements Folder { /// @nodoc abstract mixin class _$FolderCopyWith<$Res> implements $FolderCopyWith<$Res> { - factory _$FolderCopyWith(_Folder value, $Res Function(_Folder) _then) = __$FolderCopyWithImpl; + factory _$FolderCopyWith(_Folder value, $Res Function(_Folder) _then) = + __$FolderCopyWithImpl; @override @useResult $Res call({int id, String name}); @@ -1687,7 +1886,8 @@ mixin _$FrostParams { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FrostParamsCopyWith get copyWith => _$FrostParamsCopyWithImpl(this as FrostParams, _$identity); + $FrostParamsCopyWith get copyWith => + _$FrostParamsCopyWithImpl(this as FrostParams, _$identity); @override bool operator ==(Object other) { @@ -1710,7 +1910,9 @@ mixin _$FrostParams { /// @nodoc abstract mixin class $FrostParamsCopyWith<$Res> { - factory $FrostParamsCopyWith(FrostParams value, $Res Function(FrostParams) _then) = _$FrostParamsCopyWithImpl; + factory $FrostParamsCopyWith( + FrostParams value, $Res Function(FrostParams) _then) = + _$FrostParamsCopyWithImpl; @useResult $Res call({int id, int n, int t}); } @@ -1918,7 +2120,8 @@ class _FrostParams implements FrostParams { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FrostParamsCopyWith<_FrostParams> get copyWith => __$FrostParamsCopyWithImpl<_FrostParams>(this, _$identity); + _$FrostParamsCopyWith<_FrostParams> get copyWith => + __$FrostParamsCopyWithImpl<_FrostParams>(this, _$identity); @override bool operator ==(Object other) { @@ -1940,8 +2143,11 @@ class _FrostParams implements FrostParams { } /// @nodoc -abstract mixin class _$FrostParamsCopyWith<$Res> implements $FrostParamsCopyWith<$Res> { - factory _$FrostParamsCopyWith(_FrostParams value, $Res Function(_FrostParams) _then) = __$FrostParamsCopyWithImpl; +abstract mixin class _$FrostParamsCopyWith<$Res> + implements $FrostParamsCopyWith<$Res> { + factory _$FrostParamsCopyWith( + _FrostParams value, $Res Function(_FrostParams) _then) = + __$FrostParamsCopyWithImpl; @override @useResult $Res call({int id, int n, int t}); @@ -1997,7 +2203,8 @@ mixin _$Memo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoCopyWith get copyWith => _$MemoCopyWithImpl(this as Memo, _$identity); + $MemoCopyWith get copyWith => + _$MemoCopyWithImpl(this as Memo, _$identity); @override bool operator ==(Object other) { @@ -2013,11 +2220,23 @@ mixin _$Memo { (identical(other.time, time) || other.time == time) && const DeepCollectionEquality().equals(other.memoBytes, memoBytes) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo)); + (identical(other.isUserMemo, isUserMemo) || + other.isUserMemo == isUserMemo)); } @override - int get hashCode => Object.hash(runtimeType, id, idTx, idNote, pool, height, vout, time, const DeepCollectionEquality().hash(memoBytes), memo, isUserMemo); + int get hashCode => Object.hash( + runtimeType, + id, + idTx, + idNote, + pool, + height, + vout, + time, + const DeepCollectionEquality().hash(memoBytes), + memo, + isUserMemo); @override String toString() { @@ -2027,9 +2246,20 @@ mixin _$Memo { /// @nodoc abstract mixin class $MemoCopyWith<$Res> { - factory $MemoCopyWith(Memo value, $Res Function(Memo) _then) = _$MemoCopyWithImpl; + factory $MemoCopyWith(Memo value, $Res Function(Memo) _then) = + _$MemoCopyWithImpl; @useResult - $Res call({int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo}); + $Res call( + {int id, + int idTx, + int? idNote, + int pool, + int height, + int vout, + int time, + Uint8List memoBytes, + String? memo, + bool isUserMemo}); } /// @nodoc @@ -2191,13 +2421,34 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult maybeWhen( - TResult Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo)? $default, { + TResult Function( + int id, + int idTx, + int? idNote, + int pool, + int height, + int vout, + int time, + Uint8List memoBytes, + String? memo, + bool isUserMemo)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Memo() when $default != null: - return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); + return $default( + _that.id, + _that.idTx, + _that.idNote, + _that.pool, + _that.height, + _that.vout, + _that.time, + _that.memoBytes, + _that.memo, + _that.isUserMemo); case _: return orElse(); } @@ -2218,12 +2469,33 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult when( - TResult Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo) $default, + TResult Function( + int id, + int idTx, + int? idNote, + int pool, + int height, + int vout, + int time, + Uint8List memoBytes, + String? memo, + bool isUserMemo) + $default, ) { final _that = this; switch (_that) { case _Memo(): - return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); + return $default( + _that.id, + _that.idTx, + _that.idNote, + _that.pool, + _that.height, + _that.vout, + _that.time, + _that.memoBytes, + _that.memo, + _that.isUserMemo); } } @@ -2241,12 +2513,33 @@ extension MemoPatterns on Memo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo)? $default, + TResult? Function( + int id, + int idTx, + int? idNote, + int pool, + int height, + int vout, + int time, + Uint8List memoBytes, + String? memo, + bool isUserMemo)? + $default, ) { final _that = this; switch (_that) { case _Memo() when $default != null: - return $default(_that.id, _that.idTx, _that.idNote, _that.pool, _that.height, _that.vout, _that.time, _that.memoBytes, _that.memo, _that.isUserMemo); + return $default( + _that.id, + _that.idTx, + _that.idNote, + _that.pool, + _that.height, + _that.vout, + _that.time, + _that.memoBytes, + _that.memo, + _that.isUserMemo); case _: return null; } @@ -2294,7 +2587,8 @@ class _Memo implements Memo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoCopyWith<_Memo> get copyWith => __$MemoCopyWithImpl<_Memo>(this, _$identity); + _$MemoCopyWith<_Memo> get copyWith => + __$MemoCopyWithImpl<_Memo>(this, _$identity); @override bool operator ==(Object other) { @@ -2310,11 +2604,23 @@ class _Memo implements Memo { (identical(other.time, time) || other.time == time) && const DeepCollectionEquality().equals(other.memoBytes, memoBytes) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo)); + (identical(other.isUserMemo, isUserMemo) || + other.isUserMemo == isUserMemo)); } @override - int get hashCode => Object.hash(runtimeType, id, idTx, idNote, pool, height, vout, time, const DeepCollectionEquality().hash(memoBytes), memo, isUserMemo); + int get hashCode => Object.hash( + runtimeType, + id, + idTx, + idNote, + pool, + height, + vout, + time, + const DeepCollectionEquality().hash(memoBytes), + memo, + isUserMemo); @override String toString() { @@ -2324,10 +2630,21 @@ class _Memo implements Memo { /// @nodoc abstract mixin class _$MemoCopyWith<$Res> implements $MemoCopyWith<$Res> { - factory _$MemoCopyWith(_Memo value, $Res Function(_Memo) _then) = __$MemoCopyWithImpl; + factory _$MemoCopyWith(_Memo value, $Res Function(_Memo) _then) = + __$MemoCopyWithImpl; @override @useResult - $Res call({int id, int idTx, int? idNote, int pool, int height, int vout, int time, Uint8List memoBytes, String? memo, bool isUserMemo}); + $Res call( + {int id, + int idTx, + int? idNote, + int pool, + int height, + int vout, + int time, + Uint8List memoBytes, + String? memo, + bool isUserMemo}); } /// @nodoc @@ -2418,7 +2735,8 @@ mixin _$NewAccount { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $NewAccountCopyWith get copyWith => _$NewAccountCopyWithImpl(this as NewAccount, _$identity); + $NewAccountCopyWith get copyWith => + _$NewAccountCopyWithImpl(this as NewAccount, _$identity); @override bool operator ==(Object other) { @@ -2429,20 +2747,37 @@ mixin _$NewAccount { (identical(other.name, name) || other.name == name) && (identical(other.restore, restore) || other.restore == restore) && (identical(other.key, key) || other.key == key) && - (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && - const DeepCollectionEquality().equals(other.fingerprint, fingerprint) && + (identical(other.passphrase, passphrase) || + other.passphrase == passphrase) && + const DeepCollectionEquality() + .equals(other.fingerprint, fingerprint) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && (identical(other.pools, pools) || other.pools == pools) && - (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && - (identical(other.internal, internal) || other.internal == internal) && + (identical(other.useInternal, useInternal) || + other.useInternal == useInternal) && + (identical(other.internal, internal) || + other.internal == internal) && (identical(other.ledger, ledger) || other.ledger == ledger)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(icon), name, restore, key, passphrase, - const DeepCollectionEquality().hash(fingerprint), aindex, birth, folder, pools, useInternal, internal, ledger); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(icon), + name, + restore, + key, + passphrase, + const DeepCollectionEquality().hash(fingerprint), + aindex, + birth, + folder, + pools, + useInternal, + internal, + ledger); @override String toString() { @@ -2452,7 +2787,9 @@ mixin _$NewAccount { /// @nodoc abstract mixin class $NewAccountCopyWith<$Res> { - factory $NewAccountCopyWith(NewAccount value, $Res Function(NewAccount) _then) = _$NewAccountCopyWithImpl; + factory $NewAccountCopyWith( + NewAccount value, $Res Function(NewAccount) _then) = + _$NewAccountCopyWithImpl; @useResult $Res call( {Uint8List? icon, @@ -2644,16 +2981,40 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult maybeWhen( - TResult Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, - int? pools, bool useInternal, bool internal, bool ledger)? + TResult Function( + Uint8List? icon, + String name, + bool restore, + String key, + String? passphrase, + Uint8List? fingerprint, + int aindex, + int? birth, + String folder, + int? pools, + bool useInternal, + bool internal, + bool ledger)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _NewAccount() when $default != null: - return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, - _that.pools, _that.useInternal, _that.internal, _that.ledger); + return $default( + _that.icon, + _that.name, + _that.restore, + _that.key, + _that.passphrase, + _that.fingerprint, + _that.aindex, + _that.birth, + _that.folder, + _that.pools, + _that.useInternal, + _that.internal, + _that.ledger); case _: return orElse(); } @@ -2674,15 +3035,39 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult when( - TResult Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, - int? pools, bool useInternal, bool internal, bool ledger) + TResult Function( + Uint8List? icon, + String name, + bool restore, + String key, + String? passphrase, + Uint8List? fingerprint, + int aindex, + int? birth, + String folder, + int? pools, + bool useInternal, + bool internal, + bool ledger) $default, ) { final _that = this; switch (_that) { case _NewAccount(): - return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, - _that.pools, _that.useInternal, _that.internal, _that.ledger); + return $default( + _that.icon, + _that.name, + _that.restore, + _that.key, + _that.passphrase, + _that.fingerprint, + _that.aindex, + _that.birth, + _that.folder, + _that.pools, + _that.useInternal, + _that.internal, + _that.ledger); } } @@ -2700,15 +3085,39 @@ extension NewAccountPatterns on NewAccount { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Uint8List? icon, String name, bool restore, String key, String? passphrase, Uint8List? fingerprint, int aindex, int? birth, String folder, - int? pools, bool useInternal, bool internal, bool ledger)? + TResult? Function( + Uint8List? icon, + String name, + bool restore, + String key, + String? passphrase, + Uint8List? fingerprint, + int aindex, + int? birth, + String folder, + int? pools, + bool useInternal, + bool internal, + bool ledger)? $default, ) { final _that = this; switch (_that) { case _NewAccount() when $default != null: - return $default(_that.icon, _that.name, _that.restore, _that.key, _that.passphrase, _that.fingerprint, _that.aindex, _that.birth, _that.folder, - _that.pools, _that.useInternal, _that.internal, _that.ledger); + return $default( + _that.icon, + _that.name, + _that.restore, + _that.key, + _that.passphrase, + _that.fingerprint, + _that.aindex, + _that.birth, + _that.folder, + _that.pools, + _that.useInternal, + _that.internal, + _that.ledger); case _: return null; } @@ -2765,7 +3174,8 @@ class _NewAccount implements NewAccount { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$NewAccountCopyWith<_NewAccount> get copyWith => __$NewAccountCopyWithImpl<_NewAccount>(this, _$identity); + _$NewAccountCopyWith<_NewAccount> get copyWith => + __$NewAccountCopyWithImpl<_NewAccount>(this, _$identity); @override bool operator ==(Object other) { @@ -2776,20 +3186,37 @@ class _NewAccount implements NewAccount { (identical(other.name, name) || other.name == name) && (identical(other.restore, restore) || other.restore == restore) && (identical(other.key, key) || other.key == key) && - (identical(other.passphrase, passphrase) || other.passphrase == passphrase) && - const DeepCollectionEquality().equals(other.fingerprint, fingerprint) && + (identical(other.passphrase, passphrase) || + other.passphrase == passphrase) && + const DeepCollectionEquality() + .equals(other.fingerprint, fingerprint) && (identical(other.aindex, aindex) || other.aindex == aindex) && (identical(other.birth, birth) || other.birth == birth) && (identical(other.folder, folder) || other.folder == folder) && (identical(other.pools, pools) || other.pools == pools) && - (identical(other.useInternal, useInternal) || other.useInternal == useInternal) && - (identical(other.internal, internal) || other.internal == internal) && + (identical(other.useInternal, useInternal) || + other.useInternal == useInternal) && + (identical(other.internal, internal) || + other.internal == internal) && (identical(other.ledger, ledger) || other.ledger == ledger)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(icon), name, restore, key, passphrase, - const DeepCollectionEquality().hash(fingerprint), aindex, birth, folder, pools, useInternal, internal, ledger); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(icon), + name, + restore, + key, + passphrase, + const DeepCollectionEquality().hash(fingerprint), + aindex, + birth, + folder, + pools, + useInternal, + internal, + ledger); @override String toString() { @@ -2798,8 +3225,11 @@ class _NewAccount implements NewAccount { } /// @nodoc -abstract mixin class _$NewAccountCopyWith<$Res> implements $NewAccountCopyWith<$Res> { - factory _$NewAccountCopyWith(_NewAccount value, $Res Function(_NewAccount) _then) = __$NewAccountCopyWithImpl; +abstract mixin class _$NewAccountCopyWith<$Res> + implements $NewAccountCopyWith<$Res> { + factory _$NewAccountCopyWith( + _NewAccount value, $Res Function(_NewAccount) _then) = + __$NewAccountCopyWithImpl; @override @useResult $Res call( @@ -2911,14 +3341,16 @@ mixin _$Seed { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SeedCopyWith get copyWith => _$SeedCopyWithImpl(this as Seed, _$identity); + $SeedCopyWith get copyWith => + _$SeedCopyWithImpl(this as Seed, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is Seed && - (identical(other.mnemonic, mnemonic) || other.mnemonic == mnemonic) && + (identical(other.mnemonic, mnemonic) || + other.mnemonic == mnemonic) && (identical(other.phrase, phrase) || other.phrase == phrase) && (identical(other.aindex, aindex) || other.aindex == aindex)); } @@ -2934,7 +3366,8 @@ mixin _$Seed { /// @nodoc abstract mixin class $SeedCopyWith<$Res> { - factory $SeedCopyWith(Seed value, $Res Function(Seed) _then) = _$SeedCopyWithImpl; + factory $SeedCopyWith(Seed value, $Res Function(Seed) _then) = + _$SeedCopyWithImpl; @useResult $Res call({String mnemonic, String phrase, int aindex}); } @@ -3128,7 +3561,8 @@ extension SeedPatterns on Seed { /// @nodoc class _Seed implements Seed { - const _Seed({required this.mnemonic, required this.phrase, required this.aindex}); + const _Seed( + {required this.mnemonic, required this.phrase, required this.aindex}); @override final String mnemonic; @@ -3142,14 +3576,16 @@ class _Seed implements Seed { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SeedCopyWith<_Seed> get copyWith => __$SeedCopyWithImpl<_Seed>(this, _$identity); + _$SeedCopyWith<_Seed> get copyWith => + __$SeedCopyWithImpl<_Seed>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _Seed && - (identical(other.mnemonic, mnemonic) || other.mnemonic == mnemonic) && + (identical(other.mnemonic, mnemonic) || + other.mnemonic == mnemonic) && (identical(other.phrase, phrase) || other.phrase == phrase) && (identical(other.aindex, aindex) || other.aindex == aindex)); } @@ -3165,7 +3601,8 @@ class _Seed implements Seed { /// @nodoc abstract mixin class _$SeedCopyWith<$Res> implements $SeedCopyWith<$Res> { - factory _$SeedCopyWith(_Seed value, $Res Function(_Seed) _then) = __$SeedCopyWithImpl; + factory _$SeedCopyWith(_Seed value, $Res Function(_Seed) _then) = + __$SeedCopyWithImpl; @override @useResult $Res call({String mnemonic, String phrase, int aindex}); @@ -3238,19 +3675,38 @@ mixin _$Tx { (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && (identical(other.tpe, tpe) || other.tpe == tpe) && - (identical(other.category, category) || other.category == category) && - (identical(other.zsaValue, zsaValue) || other.zsaValue == zsaValue) && + (identical(other.category, category) || + other.category == category) && + (identical(other.zsaValue, zsaValue) || + other.zsaValue == zsaValue) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetDisplay, assetDisplay) || other.assetDisplay == assetDisplay) && + (identical(other.assetDisplay, assetDisplay) || + other.assetDisplay == assetDisplay) && (identical(other.price, price) || other.price == price) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo) && - (identical(other.contactName, contactName) || other.contactName == contactName)); + (identical(other.isUserMemo, isUserMemo) || + other.isUserMemo == isUserMemo) && + (identical(other.contactName, contactName) || + other.contactName == contactName)); } @override - int get hashCode => Object.hash(runtimeType, id, const DeepCollectionEquality().hash(txid), height, time, value, tpe, category, zsaValue, assetId, - assetDisplay, price, memo, isUserMemo, contactName); + int get hashCode => Object.hash( + runtimeType, + id, + const DeepCollectionEquality().hash(txid), + height, + time, + value, + tpe, + category, + zsaValue, + assetId, + assetDisplay, + price, + memo, + isUserMemo, + contactName); @override String toString() { @@ -3458,16 +3914,42 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult maybeWhen( - TResult Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, - String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName)? + TResult Function( + int id, + Uint8List txid, + int height, + int time, + PlatformInt64 value, + int? tpe, + String? category, + PlatformInt64 zsaValue, + int? assetId, + String assetDisplay, + double? price, + String? memo, + bool isUserMemo, + String? contactName)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _Tx() when $default != null: - return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, - _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); + return $default( + _that.id, + _that.txid, + _that.height, + _that.time, + _that.value, + _that.tpe, + _that.category, + _that.zsaValue, + _that.assetId, + _that.assetDisplay, + _that.price, + _that.memo, + _that.isUserMemo, + _that.contactName); case _: return orElse(); } @@ -3488,15 +3970,41 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult when( - TResult Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, - String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName) + TResult Function( + int id, + Uint8List txid, + int height, + int time, + PlatformInt64 value, + int? tpe, + String? category, + PlatformInt64 zsaValue, + int? assetId, + String assetDisplay, + double? price, + String? memo, + bool isUserMemo, + String? contactName) $default, ) { final _that = this; switch (_that) { case _Tx(): - return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, - _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); + return $default( + _that.id, + _that.txid, + _that.height, + _that.time, + _that.value, + _that.tpe, + _that.category, + _that.zsaValue, + _that.assetId, + _that.assetDisplay, + _that.price, + _that.memo, + _that.isUserMemo, + _that.contactName); } } @@ -3514,15 +4022,41 @@ extension TxPatterns on Tx { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int id, Uint8List txid, int height, int time, PlatformInt64 value, int? tpe, String? category, PlatformInt64 zsaValue, int? assetId, - String assetDisplay, double? price, String? memo, bool isUserMemo, String? contactName)? + TResult? Function( + int id, + Uint8List txid, + int height, + int time, + PlatformInt64 value, + int? tpe, + String? category, + PlatformInt64 zsaValue, + int? assetId, + String assetDisplay, + double? price, + String? memo, + bool isUserMemo, + String? contactName)? $default, ) { final _that = this; switch (_that) { case _Tx() when $default != null: - return $default(_that.id, _that.txid, _that.height, _that.time, _that.value, _that.tpe, _that.category, _that.zsaValue, _that.assetId, - _that.assetDisplay, _that.price, _that.memo, _that.isUserMemo, _that.contactName); + return $default( + _that.id, + _that.txid, + _that.height, + _that.time, + _that.value, + _that.tpe, + _that.category, + _that.zsaValue, + _that.assetId, + _that.assetDisplay, + _that.price, + _that.memo, + _that.isUserMemo, + _that.contactName); case _: return null; } @@ -3595,19 +4129,38 @@ class _Tx implements Tx { (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && (identical(other.tpe, tpe) || other.tpe == tpe) && - (identical(other.category, category) || other.category == category) && - (identical(other.zsaValue, zsaValue) || other.zsaValue == zsaValue) && + (identical(other.category, category) || + other.category == category) && + (identical(other.zsaValue, zsaValue) || + other.zsaValue == zsaValue) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetDisplay, assetDisplay) || other.assetDisplay == assetDisplay) && + (identical(other.assetDisplay, assetDisplay) || + other.assetDisplay == assetDisplay) && (identical(other.price, price) || other.price == price) && (identical(other.memo, memo) || other.memo == memo) && - (identical(other.isUserMemo, isUserMemo) || other.isUserMemo == isUserMemo) && - (identical(other.contactName, contactName) || other.contactName == contactName)); + (identical(other.isUserMemo, isUserMemo) || + other.isUserMemo == isUserMemo) && + (identical(other.contactName, contactName) || + other.contactName == contactName)); } @override - int get hashCode => Object.hash(runtimeType, id, const DeepCollectionEquality().hash(txid), height, time, value, tpe, category, zsaValue, assetId, - assetDisplay, price, memo, isUserMemo, contactName); + int get hashCode => Object.hash( + runtimeType, + id, + const DeepCollectionEquality().hash(txid), + height, + time, + value, + tpe, + category, + zsaValue, + assetId, + assetDisplay, + price, + memo, + isUserMemo, + contactName); @override String toString() { diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index 18109a36e..2bffde001 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -11,11 +11,13 @@ part 'coin.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `network`, `open_proxied_stream`, `try_open` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` -Future initDatadir({required String directory}) => RustLib.instance.api.crateApiCoinInitDatadir(directory: directory); +Future initDatadir({required String directory}) => + RustLib.instance.api.crateApiCoinInitDatadir(directory: directory); Future getTorClient() => RustLib.instance.api.crateApiCoinGetTorClient(); -Future closePool({required String dbFilepath}) => RustLib.instance.api.crateApiCoinClosePool(dbFilepath: dbFilepath); +Future closePool({required String dbFilepath}) => + RustLib.instance.api.crateApiCoinClosePool(dbFilepath: dbFilepath); @freezed sealed class Coin with _$Coin { @@ -33,16 +35,23 @@ sealed class Coin with _$Coin { that: this, ); - factory Coin({int? defaultCoin}) => RustLib.instance.api.crateApiCoinCoinNew(defaultCoin: defaultCoin); + factory Coin({int? defaultCoin}) => + RustLib.instance.api.crateApiCoinCoinNew(defaultCoin: defaultCoin); Future openDatabase({required String dbFilepath, String? password}) => - RustLib.instance.api.crateApiCoinCoinOpenDatabase(that: this, dbFilepath: dbFilepath, password: password); + RustLib.instance.api.crateApiCoinCoinOpenDatabase( + that: this, dbFilepath: dbFilepath, password: password); - Future setAccount({required int account}) => RustLib.instance.api.crateApiCoinCoinSetAccount(that: this, account: account); + Future setAccount({required int account}) => RustLib.instance.api + .crateApiCoinCoinSetAccount(that: this, account: account); - Coin setLwd({required int serverType, required String url}) => RustLib.instance.api.crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); + Coin setLwd({required int serverType, required String url}) => + RustLib.instance.api + .crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); - Coin setProxy({required String proxy}) => RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); + Coin setProxy({required String proxy}) => + RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); - Future setUseTor({required bool useTor}) => RustLib.instance.api.crateApiCoinCoinSetUseTor(that: this, useTor: useTor); + Future setUseTor({required bool useTor}) => RustLib.instance.api + .crateApiCoinCoinSetUseTor(that: this, useTor: useTor); } diff --git a/lib/src/rust/api/coin.freezed.dart b/lib/src/rust/api/coin.freezed.dart index b00fd0d2d..a6b9a8d97 100644 --- a/lib/src/rust/api/coin.freezed.dart +++ b/lib/src/rust/api/coin.freezed.dart @@ -26,7 +26,8 @@ mixin _$Coin { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $CoinCopyWith get copyWith => _$CoinCopyWithImpl(this as Coin, _$identity); + $CoinCopyWith get copyWith => + _$CoinCopyWithImpl(this as Coin, _$identity); @override bool operator ==(Object other) { @@ -35,15 +36,18 @@ mixin _$Coin { other is Coin && (identical(other.coin, coin) || other.coin == coin) && (identical(other.account, account) || other.account == account) && - (identical(other.dbFilepath, dbFilepath) || other.dbFilepath == dbFilepath) && + (identical(other.dbFilepath, dbFilepath) || + other.dbFilepath == dbFilepath) && (identical(other.url, url) || other.url == url) && - (identical(other.serverType, serverType) || other.serverType == serverType) && + (identical(other.serverType, serverType) || + other.serverType == serverType) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash( + runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); @override String toString() { @@ -53,9 +57,17 @@ mixin _$Coin { /// @nodoc abstract mixin class $CoinCopyWith<$Res> { - factory $CoinCopyWith(Coin value, $Res Function(Coin) _then) = _$CoinCopyWithImpl; + factory $CoinCopyWith(Coin value, $Res Function(Coin) _then) = + _$CoinCopyWithImpl; @useResult - $Res call({int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy}); + $Res call( + {int coin, + int account, + String dbFilepath, + String url, + int serverType, + bool useTor, + String proxy}); } /// @nodoc @@ -202,13 +214,16 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult maybeWhen({ - TResult Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy)? raw, + TResult Function(int coin, int account, String dbFilepath, String url, + int serverType, bool useTor, String proxy)? + raw, required TResult orElse(), }) { final _that = this; switch (_that) { case _Coin() when raw != null: - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, + _that.serverType, _that.useTor, _that.proxy); case _: return orElse(); } @@ -229,12 +244,15 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult when({ - required TResult Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy) raw, + required TResult Function(int coin, int account, String dbFilepath, + String url, int serverType, bool useTor, String proxy) + raw, }) { final _that = this; switch (_that) { case _Coin(): - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, + _that.serverType, _that.useTor, _that.proxy); } } @@ -252,12 +270,15 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy)? raw, + TResult? Function(int coin, int account, String dbFilepath, String url, + int serverType, bool useTor, String proxy)? + raw, }) { final _that = this; switch (_that) { case _Coin() when raw != null: - return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, _that.serverType, _that.useTor, _that.proxy); + return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, + _that.serverType, _that.useTor, _that.proxy); case _: return null; } @@ -297,7 +318,8 @@ class _Coin extends Coin { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$CoinCopyWith<_Coin> get copyWith => __$CoinCopyWithImpl<_Coin>(this, _$identity); + _$CoinCopyWith<_Coin> get copyWith => + __$CoinCopyWithImpl<_Coin>(this, _$identity); @override bool operator ==(Object other) { @@ -306,15 +328,18 @@ class _Coin extends Coin { other is _Coin && (identical(other.coin, coin) || other.coin == coin) && (identical(other.account, account) || other.account == account) && - (identical(other.dbFilepath, dbFilepath) || other.dbFilepath == dbFilepath) && + (identical(other.dbFilepath, dbFilepath) || + other.dbFilepath == dbFilepath) && (identical(other.url, url) || other.url == url) && - (identical(other.serverType, serverType) || other.serverType == serverType) && + (identical(other.serverType, serverType) || + other.serverType == serverType) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash( + runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); @override String toString() { @@ -324,10 +349,18 @@ class _Coin extends Coin { /// @nodoc abstract mixin class _$CoinCopyWith<$Res> implements $CoinCopyWith<$Res> { - factory _$CoinCopyWith(_Coin value, $Res Function(_Coin) _then) = __$CoinCopyWithImpl; + factory _$CoinCopyWith(_Coin value, $Res Function(_Coin) _then) = + __$CoinCopyWithImpl; @override @useResult - $Res call({int coin, int account, String dbFilepath, String url, int serverType, bool useTor, String proxy}); + $Res call( + {int coin, + int account, + String dbFilepath, + String url, + int serverType, + bool useTor, + String proxy}); } /// @nodoc diff --git a/lib/src/rust/api/contacts.dart b/lib/src/rust/api/contacts.dart index 1ae2222ad..97c03c9dc 100644 --- a/lib/src/rust/api/contacts.dart +++ b/lib/src/rust/api/contacts.dart @@ -11,28 +11,46 @@ part 'contacts.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `from` -Future> listContacts({required Coin c}) => RustLib.instance.api.crateApiContactsListContacts(c: c); +Future> listContacts({required Coin c}) => + RustLib.instance.api.crateApiContactsListContacts(c: c); -Future createContact({required String name, required List addresses, required String notes, required Coin c}) => - RustLib.instance.api.crateApiContactsCreateContact(name: name, addresses: addresses, notes: notes, c: c); +Future createContact( + {required String name, + required List addresses, + required String notes, + required Coin c}) => + RustLib.instance.api.crateApiContactsCreateContact( + name: name, addresses: addresses, notes: notes, c: c); -Future updateContact({required int id, String? name, List? addresses, String? notes, required Coin c}) => - RustLib.instance.api.crateApiContactsUpdateContact(id: id, name: name, addresses: addresses, notes: notes, c: c); +Future updateContact( + {required int id, + String? name, + List? addresses, + String? notes, + required Coin c}) => + RustLib.instance.api.crateApiContactsUpdateContact( + id: id, name: name, addresses: addresses, notes: notes, c: c); -Future deleteContacts({required List ids, required Coin c}) => RustLib.instance.api.crateApiContactsDeleteContacts(ids: ids, c: c); +Future deleteContacts({required List ids, required Coin c}) => + RustLib.instance.api.crateApiContactsDeleteContacts(ids: ids, c: c); /// Find contacts whose stored addresses match the given address. /// /// The input address can be either a unified address (which will be expanded /// to its constituent receivers) or a single-pool receiver address. /// Returns matching contacts with the original address that produced the match. -Future> findContactsForAddress({required String address, required Coin c}) => - RustLib.instance.api.crateApiContactsFindContactsForAddress(address: address, c: c); +Future> findContactsForAddress( + {required String address, required Coin c}) => + RustLib.instance.api + .crateApiContactsFindContactsForAddress(address: address, c: c); -Future exportContactsVcard({required Coin c}) => RustLib.instance.api.crateApiContactsExportContactsVcard(c: c); +Future exportContactsVcard({required Coin c}) => + RustLib.instance.api.crateApiContactsExportContactsVcard(c: c); -Future> importContactsVcard({required String vcardData, required Coin c}) => - RustLib.instance.api.crateApiContactsImportContactsVcard(vcardData: vcardData, c: c); +Future> importContactsVcard( + {required String vcardData, required Coin c}) => + RustLib.instance.api + .crateApiContactsImportContactsVcard(vcardData: vcardData, c: c); @freezed sealed class Contact with _$Contact { diff --git a/lib/src/rust/api/contacts.freezed.dart b/lib/src/rust/api/contacts.freezed.dart index 0c4a60023..757611b2d 100644 --- a/lib/src/rust/api/contacts.freezed.dart +++ b/lib/src/rust/api/contacts.freezed.dart @@ -23,7 +23,8 @@ mixin _$Contact { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ContactCopyWith get copyWith => _$ContactCopyWithImpl(this as Contact, _$identity); + $ContactCopyWith get copyWith => + _$ContactCopyWithImpl(this as Contact, _$identity); @override bool operator ==(Object other) { @@ -37,7 +38,8 @@ mixin _$Contact { } @override - int get hashCode => Object.hash(runtimeType, id, name, const DeepCollectionEquality().hash(addresses), notes); + int get hashCode => Object.hash(runtimeType, id, name, + const DeepCollectionEquality().hash(addresses), notes); @override String toString() { @@ -47,7 +49,8 @@ mixin _$Contact { /// @nodoc abstract mixin class $ContactCopyWith<$Res> { - factory $ContactCopyWith(Contact value, $Res Function(Contact) _then) = _$ContactCopyWithImpl; + factory $ContactCopyWith(Contact value, $Res Function(Contact) _then) = + _$ContactCopyWithImpl; @useResult $Res call({int id, String name, List addresses, String notes}); } @@ -181,7 +184,8 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult maybeWhen( - TResult Function(int id, String name, List addresses, String notes)? $default, { + TResult Function(int id, String name, List addresses, String notes)? + $default, { required TResult orElse(), }) { final _that = this; @@ -208,7 +212,8 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult when( - TResult Function(int id, String name, List addresses, String notes) $default, + TResult Function(int id, String name, List addresses, String notes) + $default, ) { final _that = this; switch (_that) { @@ -231,7 +236,9 @@ extension ContactPatterns on Contact { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int id, String name, List addresses, String notes)? $default, + TResult? Function( + int id, String name, List addresses, String notes)? + $default, ) { final _that = this; switch (_that) { @@ -246,7 +253,12 @@ extension ContactPatterns on Contact { /// @nodoc class _Contact implements Contact { - const _Contact({required this.id, required this.name, required final List addresses, required this.notes}) : _addresses = addresses; + const _Contact( + {required this.id, + required this.name, + required final List addresses, + required this.notes}) + : _addresses = addresses; @override final int id; @@ -268,7 +280,8 @@ class _Contact implements Contact { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ContactCopyWith<_Contact> get copyWith => __$ContactCopyWithImpl<_Contact>(this, _$identity); + _$ContactCopyWith<_Contact> get copyWith => + __$ContactCopyWithImpl<_Contact>(this, _$identity); @override bool operator ==(Object other) { @@ -277,12 +290,14 @@ class _Contact implements Contact { other is _Contact && (identical(other.id, id) || other.id == id) && (identical(other.name, name) || other.name == name) && - const DeepCollectionEquality().equals(other._addresses, _addresses) && + const DeepCollectionEquality() + .equals(other._addresses, _addresses) && (identical(other.notes, notes) || other.notes == notes)); } @override - int get hashCode => Object.hash(runtimeType, id, name, const DeepCollectionEquality().hash(_addresses), notes); + int get hashCode => Object.hash(runtimeType, id, name, + const DeepCollectionEquality().hash(_addresses), notes); @override String toString() { @@ -292,7 +307,8 @@ class _Contact implements Contact { /// @nodoc abstract mixin class _$ContactCopyWith<$Res> implements $ContactCopyWith<$Res> { - factory _$ContactCopyWith(_Contact value, $Res Function(_Contact) _then) = __$ContactCopyWithImpl; + factory _$ContactCopyWith(_Contact value, $Res Function(_Contact) _then) = + __$ContactCopyWithImpl; @override @useResult $Res call({int id, String name, List addresses, String notes}); @@ -345,7 +361,9 @@ mixin _$ContactMatch { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ContactMatchCopyWith get copyWith => _$ContactMatchCopyWithImpl(this as ContactMatch, _$identity); + $ContactMatchCopyWith get copyWith => + _$ContactMatchCopyWithImpl( + this as ContactMatch, _$identity); @override bool operator ==(Object other) { @@ -353,7 +371,8 @@ mixin _$ContactMatch { (other.runtimeType == runtimeType && other is ContactMatch && (identical(other.contact, contact) || other.contact == contact) && - (identical(other.matchedAddress, matchedAddress) || other.matchedAddress == matchedAddress)); + (identical(other.matchedAddress, matchedAddress) || + other.matchedAddress == matchedAddress)); } @override @@ -367,7 +386,9 @@ mixin _$ContactMatch { /// @nodoc abstract mixin class $ContactMatchCopyWith<$Res> { - factory $ContactMatchCopyWith(ContactMatch value, $Res Function(ContactMatch) _then) = _$ContactMatchCopyWithImpl; + factory $ContactMatchCopyWith( + ContactMatch value, $Res Function(ContactMatch) _then) = + _$ContactMatchCopyWithImpl; @useResult $Res call({Contact contact, String matchedAddress}); @@ -580,7 +601,8 @@ class _ContactMatch implements ContactMatch { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ContactMatchCopyWith<_ContactMatch> get copyWith => __$ContactMatchCopyWithImpl<_ContactMatch>(this, _$identity); + _$ContactMatchCopyWith<_ContactMatch> get copyWith => + __$ContactMatchCopyWithImpl<_ContactMatch>(this, _$identity); @override bool operator ==(Object other) { @@ -588,7 +610,8 @@ class _ContactMatch implements ContactMatch { (other.runtimeType == runtimeType && other is _ContactMatch && (identical(other.contact, contact) || other.contact == contact) && - (identical(other.matchedAddress, matchedAddress) || other.matchedAddress == matchedAddress)); + (identical(other.matchedAddress, matchedAddress) || + other.matchedAddress == matchedAddress)); } @override @@ -601,8 +624,11 @@ class _ContactMatch implements ContactMatch { } /// @nodoc -abstract mixin class _$ContactMatchCopyWith<$Res> implements $ContactMatchCopyWith<$Res> { - factory _$ContactMatchCopyWith(_ContactMatch value, $Res Function(_ContactMatch) _then) = __$ContactMatchCopyWithImpl; +abstract mixin class _$ContactMatchCopyWith<$Res> + implements $ContactMatchCopyWith<$Res> { + factory _$ContactMatchCopyWith( + _ContactMatch value, $Res Function(_ContactMatch) _then) = + __$ContactMatchCopyWithImpl; @override @useResult $Res call({Contact contact, String matchedAddress}); @@ -612,7 +638,8 @@ abstract mixin class _$ContactMatchCopyWith<$Res> implements $ContactMatchCopyWi } /// @nodoc -class __$ContactMatchCopyWithImpl<$Res> implements _$ContactMatchCopyWith<$Res> { +class __$ContactMatchCopyWithImpl<$Res> + implements _$ContactMatchCopyWith<$Res> { __$ContactMatchCopyWithImpl(this._self, this._then); final _ContactMatch _self; diff --git a/lib/src/rust/api/db.dart b/lib/src/rust/api/db.dart index 64cef0cfe..77746c5fd 100644 --- a/lib/src/rust/api/db.dart +++ b/lib/src/rust/api/db.dart @@ -7,16 +7,29 @@ import '../frb_generated.dart'; import 'coin.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -Future> listDbAccounts({required String dbFilepath}) => RustLib.instance.api.crateApiDbListDbAccounts(dbFilepath: dbFilepath); - -Future changeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}) => - RustLib.instance.api.crateApiDbChangeDbPassword(dbFilepath: dbFilepath, tmpDir: tmpDir, oldPassword: oldPassword, newPassword: newPassword); - -Future getProp({required String key, required Coin c}) => RustLib.instance.api.crateApiDbGetProp(key: key, c: c); - -Future putProp({required String key, required String value, required Coin c}) => RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); - -Future> listDbNames({required String dir}) => RustLib.instance.api.crateApiDbListDbNames(dir: dir); +Future> listDbAccounts({required String dbFilepath}) => + RustLib.instance.api.crateApiDbListDbAccounts(dbFilepath: dbFilepath); + +Future changeDbPassword( + {required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword}) => + RustLib.instance.api.crateApiDbChangeDbPassword( + dbFilepath: dbFilepath, + tmpDir: tmpDir, + oldPassword: oldPassword, + newPassword: newPassword); + +Future getProp({required String key, required Coin c}) => + RustLib.instance.api.crateApiDbGetProp(key: key, c: c); + +Future putProp( + {required String key, required String value, required Coin c}) => + RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); + +Future> listDbNames({required String dir}) => + RustLib.instance.api.crateApiDbListDbNames(dir: dir); class DbAccountPreview { final int id; @@ -32,5 +45,9 @@ class DbAccountPreview { @override bool operator ==(Object other) => - identical(this, other) || other is DbAccountPreview && runtimeType == other.runtimeType && id == other.id && name == other.name; + identical(this, other) || + other is DbAccountPreview && + runtimeType == other.runtimeType && + id == other.id && + name == other.name; } diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index c863adb20..a4ed66a81 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -15,32 +15,58 @@ part 'frost.freezed.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DKGParams` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt` -Future setDkgParams({required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}) => - RustLib.instance.api.crateApiFrostSetDkgParams(name: name, id: id, n: n, t: t, fundingAccount: fundingAccount, c: c); - -Future hasDkgParams({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgParams(c: c); - -Future initDkg({required Coin c}) => RustLib.instance.api.crateApiFrostInitDkg(c: c); - -Future hasDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgAddresses(c: c); - -Stream doDkg({required Coin c}) => RustLib.instance.api.crateApiFrostDoDkg(c: c); - -Future> getDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostGetDkgAddresses(c: c); - -Future setDkgAddress({required int id, required String address, required Coin c}) => - RustLib.instance.api.crateApiFrostSetDkgAddress(id: id, address: address, c: c); - -Future cancelDkg({required Coin c}) => RustLib.instance.api.crateApiFrostCancelDkg(c: c); - -Future resetSign({required Coin c}) => RustLib.instance.api.crateApiFrostResetSign(c: c); - -Future initSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}) => - RustLib.instance.api.crateApiFrostInitSign(coordinator: coordinator, fundingAccount: fundingAccount, pczt: pczt, c: c); - -Future isSigningInProgress({required Coin c}) => RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); - -Stream doSign({required Coin c}) => RustLib.instance.api.crateApiFrostDoSign(c: c); +Future setDkgParams( + {required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c}) => + RustLib.instance.api.crateApiFrostSetDkgParams( + name: name, id: id, n: n, t: t, fundingAccount: fundingAccount, c: c); + +Future hasDkgParams({required Coin c}) => + RustLib.instance.api.crateApiFrostHasDkgParams(c: c); + +Future initDkg({required Coin c}) => + RustLib.instance.api.crateApiFrostInitDkg(c: c); + +Future hasDkgAddresses({required Coin c}) => + RustLib.instance.api.crateApiFrostHasDkgAddresses(c: c); + +Stream doDkg({required Coin c}) => + RustLib.instance.api.crateApiFrostDoDkg(c: c); + +Future> getDkgAddresses({required Coin c}) => + RustLib.instance.api.crateApiFrostGetDkgAddresses(c: c); + +Future setDkgAddress( + {required int id, required String address, required Coin c}) => + RustLib.instance.api + .crateApiFrostSetDkgAddress(id: id, address: address, c: c); + +Future cancelDkg({required Coin c}) => + RustLib.instance.api.crateApiFrostCancelDkg(c: c); + +Future resetSign({required Coin c}) => + RustLib.instance.api.crateApiFrostResetSign(c: c); + +Future initSign( + {required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c}) => + RustLib.instance.api.crateApiFrostInitSign( + coordinator: coordinator, + fundingAccount: fundingAccount, + pczt: pczt, + c: c); + +Future isSigningInProgress({required Coin c}) => + RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); + +Stream doSign({required Coin c}) => + RustLib.instance.api.crateApiFrostDoSign(c: c); @freezed sealed class DKGStatus with _$DKGStatus { @@ -68,22 +94,32 @@ sealed class FrostSignParams with _$FrostSignParams { required int coordinator, required int fundingAccount, }) = _FrostSignParams; - static Future default_() => RustLib.instance.api.crateApiFrostFrostSignParamsDefault(); + static Future default_() => + RustLib.instance.api.crateApiFrostFrostSignParamsDefault(); } @freezed sealed class SigningStatus with _$SigningStatus { const SigningStatus._(); - const factory SigningStatus.sendingCommitment() = SigningStatus_SendingCommitment; - const factory SigningStatus.waitingForCommitments() = SigningStatus_WaitingForCommitments; - const factory SigningStatus.sendingSigningPackage() = SigningStatus_SendingSigningPackage; - const factory SigningStatus.waitingForSigningPackage() = SigningStatus_WaitingForSigningPackage; - const factory SigningStatus.sendingSignatureShare() = SigningStatus_SendingSignatureShare; - const factory SigningStatus.signingCompleted() = SigningStatus_SigningCompleted; - const factory SigningStatus.waitingForSignatureShares() = SigningStatus_WaitingForSignatureShares; - const factory SigningStatus.preparingTransaction() = SigningStatus_PreparingTransaction; - const factory SigningStatus.sendingTransaction() = SigningStatus_SendingTransaction; + const factory SigningStatus.sendingCommitment() = + SigningStatus_SendingCommitment; + const factory SigningStatus.waitingForCommitments() = + SigningStatus_WaitingForCommitments; + const factory SigningStatus.sendingSigningPackage() = + SigningStatus_SendingSigningPackage; + const factory SigningStatus.waitingForSigningPackage() = + SigningStatus_WaitingForSigningPackage; + const factory SigningStatus.sendingSignatureShare() = + SigningStatus_SendingSignatureShare; + const factory SigningStatus.signingCompleted() = + SigningStatus_SigningCompleted; + const factory SigningStatus.waitingForSignatureShares() = + SigningStatus_WaitingForSignatureShares; + const factory SigningStatus.preparingTransaction() = + SigningStatus_PreparingTransaction; + const factory SigningStatus.sendingTransaction() = + SigningStatus_SendingTransaction; const factory SigningStatus.transactionSent( String field0, ) = SigningStatus_TransactionSent; diff --git a/lib/src/rust/api/frost.freezed.dart b/lib/src/rust/api/frost.freezed.dart index 2e3c255ad..9a9a2e016 100644 --- a/lib/src/rust/api/frost.freezed.dart +++ b/lib/src/rust/api/frost.freezed.dart @@ -16,7 +16,8 @@ T _$identity(T value) => value; mixin _$DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus); + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus); } @override @@ -99,9 +100,11 @@ extension DKGStatusPatterns on DKGStatus { TResult map({ required TResult Function(DKGStatus_WaitParams value) waitParams, required TResult Function(DKGStatus_WaitAddresses value) waitAddresses, - required TResult Function(DKGStatus_PublishRound1Pkg value) publishRound1Pkg, + required TResult Function(DKGStatus_PublishRound1Pkg value) + publishRound1Pkg, required TResult Function(DKGStatus_WaitRound1Pkg value) waitRound1Pkg, - required TResult Function(DKGStatus_PublishRound2Pkg value) publishRound2Pkg, + required TResult Function(DKGStatus_PublishRound2Pkg value) + publishRound2Pkg, required TResult Function(DKGStatus_WaitRound2Pkg value) waitRound2Pkg, required TResult Function(DKGStatus_Finalize value) finalize, required TResult Function(DKGStatus_SharedAddress value) sharedAddress, @@ -319,7 +322,8 @@ class DKGStatus_WaitParams extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitParams); + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus_WaitParams); } @override @@ -349,16 +353,21 @@ class DKGStatus_WaitAddresses extends DKGStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $DKGStatus_WaitAddressesCopyWith get copyWith => _$DKGStatus_WaitAddressesCopyWithImpl(this, _$identity); + $DKGStatus_WaitAddressesCopyWith get copyWith => + _$DKGStatus_WaitAddressesCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_WaitAddresses && const DeepCollectionEquality().equals(other._field0, _field0)); + (other.runtimeType == runtimeType && + other is DKGStatus_WaitAddresses && + const DeepCollectionEquality().equals(other._field0, _field0)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_field0)); @override String toString() { @@ -367,14 +376,18 @@ class DKGStatus_WaitAddresses extends DKGStatus { } /// @nodoc -abstract mixin class $DKGStatus_WaitAddressesCopyWith<$Res> implements $DKGStatusCopyWith<$Res> { - factory $DKGStatus_WaitAddressesCopyWith(DKGStatus_WaitAddresses value, $Res Function(DKGStatus_WaitAddresses) _then) = _$DKGStatus_WaitAddressesCopyWithImpl; +abstract mixin class $DKGStatus_WaitAddressesCopyWith<$Res> + implements $DKGStatusCopyWith<$Res> { + factory $DKGStatus_WaitAddressesCopyWith(DKGStatus_WaitAddresses value, + $Res Function(DKGStatus_WaitAddresses) _then) = + _$DKGStatus_WaitAddressesCopyWithImpl; @useResult $Res call({List field0}); } /// @nodoc -class _$DKGStatus_WaitAddressesCopyWithImpl<$Res> implements $DKGStatus_WaitAddressesCopyWith<$Res> { +class _$DKGStatus_WaitAddressesCopyWithImpl<$Res> + implements $DKGStatus_WaitAddressesCopyWith<$Res> { _$DKGStatus_WaitAddressesCopyWithImpl(this._self, this._then); final DKGStatus_WaitAddresses _self; @@ -402,7 +415,9 @@ class DKGStatus_PublishRound1Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_PublishRound1Pkg); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is DKGStatus_PublishRound1Pkg); } @override @@ -421,7 +436,8 @@ class DKGStatus_WaitRound1Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitRound1Pkg); + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus_WaitRound1Pkg); } @override @@ -440,7 +456,9 @@ class DKGStatus_PublishRound2Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_PublishRound2Pkg); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is DKGStatus_PublishRound2Pkg); } @override @@ -459,7 +477,8 @@ class DKGStatus_WaitRound2Pkg extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_WaitRound2Pkg); + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus_WaitRound2Pkg); } @override @@ -478,7 +497,8 @@ class DKGStatus_Finalize extends DKGStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is DKGStatus_Finalize); + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus_Finalize); } @override @@ -501,12 +521,16 @@ class DKGStatus_SharedAddress extends DKGStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $DKGStatus_SharedAddressCopyWith get copyWith => _$DKGStatus_SharedAddressCopyWithImpl(this, _$identity); + $DKGStatus_SharedAddressCopyWith get copyWith => + _$DKGStatus_SharedAddressCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is DKGStatus_SharedAddress && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is DKGStatus_SharedAddress && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -519,14 +543,18 @@ class DKGStatus_SharedAddress extends DKGStatus { } /// @nodoc -abstract mixin class $DKGStatus_SharedAddressCopyWith<$Res> implements $DKGStatusCopyWith<$Res> { - factory $DKGStatus_SharedAddressCopyWith(DKGStatus_SharedAddress value, $Res Function(DKGStatus_SharedAddress) _then) = _$DKGStatus_SharedAddressCopyWithImpl; +abstract mixin class $DKGStatus_SharedAddressCopyWith<$Res> + implements $DKGStatusCopyWith<$Res> { + factory $DKGStatus_SharedAddressCopyWith(DKGStatus_SharedAddress value, + $Res Function(DKGStatus_SharedAddress) _then) = + _$DKGStatus_SharedAddressCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$DKGStatus_SharedAddressCopyWithImpl<$Res> implements $DKGStatus_SharedAddressCopyWith<$Res> { +class _$DKGStatus_SharedAddressCopyWithImpl<$Res> + implements $DKGStatus_SharedAddressCopyWith<$Res> { _$DKGStatus_SharedAddressCopyWithImpl(this._self, this._then); final DKGStatus_SharedAddress _self; @@ -557,7 +585,9 @@ mixin _$FrostSignParams { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $FrostSignParamsCopyWith get copyWith => _$FrostSignParamsCopyWithImpl(this as FrostSignParams, _$identity); + $FrostSignParamsCopyWith get copyWith => + _$FrostSignParamsCopyWithImpl( + this as FrostSignParams, _$identity); @override bool operator ==(Object other) { @@ -565,12 +595,15 @@ mixin _$FrostSignParams { (other.runtimeType == runtimeType && other is FrostSignParams && (identical(other.account, account) || other.account == account) && - (identical(other.coordinator, coordinator) || other.coordinator == coordinator) && - (identical(other.fundingAccount, fundingAccount) || other.fundingAccount == fundingAccount)); + (identical(other.coordinator, coordinator) || + other.coordinator == coordinator) && + (identical(other.fundingAccount, fundingAccount) || + other.fundingAccount == fundingAccount)); } @override - int get hashCode => Object.hash(runtimeType, account, coordinator, fundingAccount); + int get hashCode => + Object.hash(runtimeType, account, coordinator, fundingAccount); @override String toString() { @@ -580,13 +613,16 @@ mixin _$FrostSignParams { /// @nodoc abstract mixin class $FrostSignParamsCopyWith<$Res> { - factory $FrostSignParamsCopyWith(FrostSignParams value, $Res Function(FrostSignParams) _then) = _$FrostSignParamsCopyWithImpl; + factory $FrostSignParamsCopyWith( + FrostSignParams value, $Res Function(FrostSignParams) _then) = + _$FrostSignParamsCopyWithImpl; @useResult $Res call({int account, int coordinator, int fundingAccount}); } /// @nodoc -class _$FrostSignParamsCopyWithImpl<$Res> implements $FrostSignParamsCopyWith<$Res> { +class _$FrostSignParamsCopyWithImpl<$Res> + implements $FrostSignParamsCopyWith<$Res> { _$FrostSignParamsCopyWithImpl(this._self, this._then); final FrostSignParams _self; @@ -709,7 +745,8 @@ extension FrostSignParamsPatterns on FrostSignParams { @optionalTypeArgs TResult maybeWhen( - TResult Function(int account, int coordinator, int fundingAccount)? $default, { + TResult Function(int account, int coordinator, int fundingAccount)? + $default, { required TResult orElse(), }) { final _that = this; @@ -759,7 +796,8 @@ extension FrostSignParamsPatterns on FrostSignParams { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int account, int coordinator, int fundingAccount)? $default, + TResult? Function(int account, int coordinator, int fundingAccount)? + $default, ) { final _that = this; switch (_that) { @@ -774,7 +812,11 @@ extension FrostSignParamsPatterns on FrostSignParams { /// @nodoc class _FrostSignParams extends FrostSignParams { - const _FrostSignParams({required this.account, required this.coordinator, required this.fundingAccount}) : super._(); + const _FrostSignParams( + {required this.account, + required this.coordinator, + required this.fundingAccount}) + : super._(); @override final int account; @@ -788,7 +830,8 @@ class _FrostSignParams extends FrostSignParams { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FrostSignParamsCopyWith<_FrostSignParams> get copyWith => __$FrostSignParamsCopyWithImpl<_FrostSignParams>(this, _$identity); + _$FrostSignParamsCopyWith<_FrostSignParams> get copyWith => + __$FrostSignParamsCopyWithImpl<_FrostSignParams>(this, _$identity); @override bool operator ==(Object other) { @@ -796,12 +839,15 @@ class _FrostSignParams extends FrostSignParams { (other.runtimeType == runtimeType && other is _FrostSignParams && (identical(other.account, account) || other.account == account) && - (identical(other.coordinator, coordinator) || other.coordinator == coordinator) && - (identical(other.fundingAccount, fundingAccount) || other.fundingAccount == fundingAccount)); + (identical(other.coordinator, coordinator) || + other.coordinator == coordinator) && + (identical(other.fundingAccount, fundingAccount) || + other.fundingAccount == fundingAccount)); } @override - int get hashCode => Object.hash(runtimeType, account, coordinator, fundingAccount); + int get hashCode => + Object.hash(runtimeType, account, coordinator, fundingAccount); @override String toString() { @@ -810,15 +856,19 @@ class _FrostSignParams extends FrostSignParams { } /// @nodoc -abstract mixin class _$FrostSignParamsCopyWith<$Res> implements $FrostSignParamsCopyWith<$Res> { - factory _$FrostSignParamsCopyWith(_FrostSignParams value, $Res Function(_FrostSignParams) _then) = __$FrostSignParamsCopyWithImpl; +abstract mixin class _$FrostSignParamsCopyWith<$Res> + implements $FrostSignParamsCopyWith<$Res> { + factory _$FrostSignParamsCopyWith( + _FrostSignParams value, $Res Function(_FrostSignParams) _then) = + __$FrostSignParamsCopyWithImpl; @override @useResult $Res call({int account, int coordinator, int fundingAccount}); } /// @nodoc -class __$FrostSignParamsCopyWithImpl<$Res> implements _$FrostSignParamsCopyWith<$Res> { +class __$FrostSignParamsCopyWithImpl<$Res> + implements _$FrostSignParamsCopyWith<$Res> { __$FrostSignParamsCopyWithImpl(this._self, this._then); final _FrostSignParams _self; @@ -854,7 +904,8 @@ class __$FrostSignParamsCopyWithImpl<$Res> implements _$FrostSignParamsCopyWith< mixin _$SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus); + return identical(this, other) || + (other.runtimeType == runtimeType && other is SigningStatus); } @override @@ -888,14 +939,21 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult maybeMap({ TResult Function(SigningStatus_SendingCommitment value)? sendingCommitment, - TResult Function(SigningStatus_WaitingForCommitments value)? waitingForCommitments, - TResult Function(SigningStatus_SendingSigningPackage value)? sendingSigningPackage, - TResult Function(SigningStatus_WaitingForSigningPackage value)? waitingForSigningPackage, - TResult Function(SigningStatus_SendingSignatureShare value)? sendingSignatureShare, + TResult Function(SigningStatus_WaitingForCommitments value)? + waitingForCommitments, + TResult Function(SigningStatus_SendingSigningPackage value)? + sendingSigningPackage, + TResult Function(SigningStatus_WaitingForSigningPackage value)? + waitingForSigningPackage, + TResult Function(SigningStatus_SendingSignatureShare value)? + sendingSignatureShare, TResult Function(SigningStatus_SigningCompleted value)? signingCompleted, - TResult Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, - TResult Function(SigningStatus_PreparingTransaction value)? preparingTransaction, - TResult Function(SigningStatus_SendingTransaction value)? sendingTransaction, + TResult Function(SigningStatus_WaitingForSignatureShares value)? + waitingForSignatureShares, + TResult Function(SigningStatus_PreparingTransaction value)? + preparingTransaction, + TResult Function(SigningStatus_SendingTransaction value)? + sendingTransaction, TResult Function(SigningStatus_TransactionSent value)? transactionSent, required TResult orElse(), }) { @@ -903,19 +961,25 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(_that); - case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() + when waitingForCommitments != null: return waitingForCommitments(_that); - case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() + when sendingSigningPackage != null: return sendingSigningPackage(_that); - case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() + when waitingForSigningPackage != null: return waitingForSigningPackage(_that); - case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() + when sendingSignatureShare != null: return sendingSignatureShare(_that); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(_that); - case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() + when waitingForSignatureShares != null: return waitingForSignatureShares(_that); - case SigningStatus_PreparingTransaction() when preparingTransaction != null: + case SigningStatus_PreparingTransaction() + when preparingTransaction != null: return preparingTransaction(_that); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(_that); @@ -941,16 +1005,26 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult map({ - required TResult Function(SigningStatus_SendingCommitment value) sendingCommitment, - required TResult Function(SigningStatus_WaitingForCommitments value) waitingForCommitments, - required TResult Function(SigningStatus_SendingSigningPackage value) sendingSigningPackage, - required TResult Function(SigningStatus_WaitingForSigningPackage value) waitingForSigningPackage, - required TResult Function(SigningStatus_SendingSignatureShare value) sendingSignatureShare, - required TResult Function(SigningStatus_SigningCompleted value) signingCompleted, - required TResult Function(SigningStatus_WaitingForSignatureShares value) waitingForSignatureShares, - required TResult Function(SigningStatus_PreparingTransaction value) preparingTransaction, - required TResult Function(SigningStatus_SendingTransaction value) sendingTransaction, - required TResult Function(SigningStatus_TransactionSent value) transactionSent, + required TResult Function(SigningStatus_SendingCommitment value) + sendingCommitment, + required TResult Function(SigningStatus_WaitingForCommitments value) + waitingForCommitments, + required TResult Function(SigningStatus_SendingSigningPackage value) + sendingSigningPackage, + required TResult Function(SigningStatus_WaitingForSigningPackage value) + waitingForSigningPackage, + required TResult Function(SigningStatus_SendingSignatureShare value) + sendingSignatureShare, + required TResult Function(SigningStatus_SigningCompleted value) + signingCompleted, + required TResult Function(SigningStatus_WaitingForSignatureShares value) + waitingForSignatureShares, + required TResult Function(SigningStatus_PreparingTransaction value) + preparingTransaction, + required TResult Function(SigningStatus_SendingTransaction value) + sendingTransaction, + required TResult Function(SigningStatus_TransactionSent value) + transactionSent, }) { final _that = this; switch (_that) { @@ -992,33 +1066,46 @@ extension SigningStatusPatterns on SigningStatus { @optionalTypeArgs TResult? mapOrNull({ TResult? Function(SigningStatus_SendingCommitment value)? sendingCommitment, - TResult? Function(SigningStatus_WaitingForCommitments value)? waitingForCommitments, - TResult? Function(SigningStatus_SendingSigningPackage value)? sendingSigningPackage, - TResult? Function(SigningStatus_WaitingForSigningPackage value)? waitingForSigningPackage, - TResult? Function(SigningStatus_SendingSignatureShare value)? sendingSignatureShare, + TResult? Function(SigningStatus_WaitingForCommitments value)? + waitingForCommitments, + TResult? Function(SigningStatus_SendingSigningPackage value)? + sendingSigningPackage, + TResult? Function(SigningStatus_WaitingForSigningPackage value)? + waitingForSigningPackage, + TResult? Function(SigningStatus_SendingSignatureShare value)? + sendingSignatureShare, TResult? Function(SigningStatus_SigningCompleted value)? signingCompleted, - TResult? Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, - TResult? Function(SigningStatus_PreparingTransaction value)? preparingTransaction, - TResult? Function(SigningStatus_SendingTransaction value)? sendingTransaction, + TResult? Function(SigningStatus_WaitingForSignatureShares value)? + waitingForSignatureShares, + TResult? Function(SigningStatus_PreparingTransaction value)? + preparingTransaction, + TResult? Function(SigningStatus_SendingTransaction value)? + sendingTransaction, TResult? Function(SigningStatus_TransactionSent value)? transactionSent, }) { final _that = this; switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(_that); - case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() + when waitingForCommitments != null: return waitingForCommitments(_that); - case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() + when sendingSigningPackage != null: return sendingSigningPackage(_that); - case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() + when waitingForSigningPackage != null: return waitingForSigningPackage(_that); - case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() + when sendingSignatureShare != null: return sendingSignatureShare(_that); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(_that); - case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() + when waitingForSignatureShares != null: return waitingForSignatureShares(_that); - case SigningStatus_PreparingTransaction() when preparingTransaction != null: + case SigningStatus_PreparingTransaction() + when preparingTransaction != null: return preparingTransaction(_that); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(_that); @@ -1059,19 +1146,25 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(); - case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() + when waitingForCommitments != null: return waitingForCommitments(); - case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() + when sendingSigningPackage != null: return sendingSigningPackage(); - case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() + when waitingForSigningPackage != null: return waitingForSigningPackage(); - case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() + when sendingSignatureShare != null: return sendingSignatureShare(); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(); - case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() + when waitingForSignatureShares != null: return waitingForSignatureShares(); - case SigningStatus_PreparingTransaction() when preparingTransaction != null: + case SigningStatus_PreparingTransaction() + when preparingTransaction != null: return preparingTransaction(); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(); @@ -1162,19 +1255,25 @@ extension SigningStatusPatterns on SigningStatus { switch (_that) { case SigningStatus_SendingCommitment() when sendingCommitment != null: return sendingCommitment(); - case SigningStatus_WaitingForCommitments() when waitingForCommitments != null: + case SigningStatus_WaitingForCommitments() + when waitingForCommitments != null: return waitingForCommitments(); - case SigningStatus_SendingSigningPackage() when sendingSigningPackage != null: + case SigningStatus_SendingSigningPackage() + when sendingSigningPackage != null: return sendingSigningPackage(); - case SigningStatus_WaitingForSigningPackage() when waitingForSigningPackage != null: + case SigningStatus_WaitingForSigningPackage() + when waitingForSigningPackage != null: return waitingForSigningPackage(); - case SigningStatus_SendingSignatureShare() when sendingSignatureShare != null: + case SigningStatus_SendingSignatureShare() + when sendingSignatureShare != null: return sendingSignatureShare(); case SigningStatus_SigningCompleted() when signingCompleted != null: return signingCompleted(); - case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: + case SigningStatus_WaitingForSignatureShares() + when waitingForSignatureShares != null: return waitingForSignatureShares(); - case SigningStatus_PreparingTransaction() when preparingTransaction != null: + case SigningStatus_PreparingTransaction() + when preparingTransaction != null: return preparingTransaction(); case SigningStatus_SendingTransaction() when sendingTransaction != null: return sendingTransaction(); @@ -1193,7 +1292,9 @@ class SigningStatus_SendingCommitment extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingCommitment); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_SendingCommitment); } @override @@ -1212,7 +1313,9 @@ class SigningStatus_WaitingForCommitments extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForCommitments); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_WaitingForCommitments); } @override @@ -1231,7 +1334,9 @@ class SigningStatus_SendingSigningPackage extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingSigningPackage); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_SendingSigningPackage); } @override @@ -1250,7 +1355,9 @@ class SigningStatus_WaitingForSigningPackage extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForSigningPackage); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_WaitingForSigningPackage); } @override @@ -1269,7 +1376,9 @@ class SigningStatus_SendingSignatureShare extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingSignatureShare); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_SendingSignatureShare); } @override @@ -1288,7 +1397,9 @@ class SigningStatus_SigningCompleted extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SigningCompleted); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_SigningCompleted); } @override @@ -1307,7 +1418,9 @@ class SigningStatus_WaitingForSignatureShares extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_WaitingForSignatureShares); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_WaitingForSignatureShares); } @override @@ -1326,7 +1439,9 @@ class SigningStatus_PreparingTransaction extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_PreparingTransaction); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_PreparingTransaction); } @override @@ -1345,7 +1460,9 @@ class SigningStatus_SendingTransaction extends SigningStatus { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningStatus_SendingTransaction); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_SendingTransaction); } @override @@ -1368,13 +1485,16 @@ class SigningStatus_TransactionSent extends SigningStatus { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningStatus_TransactionSentCopyWith get copyWith => - _$SigningStatus_TransactionSentCopyWithImpl(this, _$identity); + $SigningStatus_TransactionSentCopyWith + get copyWith => _$SigningStatus_TransactionSentCopyWithImpl< + SigningStatus_TransactionSent>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is SigningStatus_TransactionSent && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is SigningStatus_TransactionSent && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -1387,15 +1507,19 @@ class SigningStatus_TransactionSent extends SigningStatus { } /// @nodoc -abstract mixin class $SigningStatus_TransactionSentCopyWith<$Res> implements $SigningStatusCopyWith<$Res> { - factory $SigningStatus_TransactionSentCopyWith(SigningStatus_TransactionSent value, $Res Function(SigningStatus_TransactionSent) _then) = +abstract mixin class $SigningStatus_TransactionSentCopyWith<$Res> + implements $SigningStatusCopyWith<$Res> { + factory $SigningStatus_TransactionSentCopyWith( + SigningStatus_TransactionSent value, + $Res Function(SigningStatus_TransactionSent) _then) = _$SigningStatus_TransactionSentCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$SigningStatus_TransactionSentCopyWithImpl<$Res> implements $SigningStatus_TransactionSentCopyWith<$Res> { +class _$SigningStatus_TransactionSentCopyWithImpl<$Res> + implements $SigningStatus_TransactionSentCopyWith<$Res> { _$SigningStatus_TransactionSentCopyWithImpl(this._self, this._then); final SigningStatus_TransactionSent _self; diff --git a/lib/src/rust/api/init.dart b/lib/src/rust/api/init.dart index 013be7f73..bbc587bcb 100644 --- a/lib/src/rust/api/init.dart +++ b/lib/src/rust/api/init.dart @@ -16,9 +16,11 @@ part 'init.freezed.dart'; /// Enable expert mode, which lowers the log filter to allow /// sync, mempool, and memo target debug messages /// while keeping everything else at `info`. -void setExpertMode({required bool enabled}) => RustLib.instance.api.crateApiInitSetExpertMode(enabled: enabled); +void setExpertMode({required bool enabled}) => + RustLib.instance.api.crateApiInitSetExpertMode(enabled: enabled); -Stream setLogStream() => RustLib.instance.api.crateApiInitSetLogStream(); +Stream setLogStream() => + RustLib.instance.api.crateApiInitSetLogStream(); @freezed sealed class LogMessage with _$LogMessage { diff --git a/lib/src/rust/api/init.freezed.dart b/lib/src/rust/api/init.freezed.dart index ca8fb8a8b..9b794dc69 100644 --- a/lib/src/rust/api/init.freezed.dart +++ b/lib/src/rust/api/init.freezed.dart @@ -22,7 +22,8 @@ mixin _$LogMessage { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $LogMessageCopyWith get copyWith => _$LogMessageCopyWithImpl(this as LogMessage, _$identity); + $LogMessageCopyWith get copyWith => + _$LogMessageCopyWithImpl(this as LogMessage, _$identity); @override bool operator ==(Object other) { @@ -45,7 +46,9 @@ mixin _$LogMessage { /// @nodoc abstract mixin class $LogMessageCopyWith<$Res> { - factory $LogMessageCopyWith(LogMessage value, $Res Function(LogMessage) _then) = _$LogMessageCopyWithImpl; + factory $LogMessageCopyWith( + LogMessage value, $Res Function(LogMessage) _then) = + _$LogMessageCopyWithImpl; @useResult $Res call({int level, String message, String? span}); } @@ -253,7 +256,8 @@ class _LogMessage implements LogMessage { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$LogMessageCopyWith<_LogMessage> get copyWith => __$LogMessageCopyWithImpl<_LogMessage>(this, _$identity); + _$LogMessageCopyWith<_LogMessage> get copyWith => + __$LogMessageCopyWithImpl<_LogMessage>(this, _$identity); @override bool operator ==(Object other) { @@ -275,8 +279,11 @@ class _LogMessage implements LogMessage { } /// @nodoc -abstract mixin class _$LogMessageCopyWith<$Res> implements $LogMessageCopyWith<$Res> { - factory _$LogMessageCopyWith(_LogMessage value, $Res Function(_LogMessage) _then) = __$LogMessageCopyWithImpl; +abstract mixin class _$LogMessageCopyWith<$Res> + implements $LogMessageCopyWith<$Res> { + factory _$LogMessageCopyWith( + _LogMessage value, $Res Function(_LogMessage) _then) = + __$LogMessageCopyWithImpl; @override @useResult $Res call({int level, String message, String? span}); diff --git a/lib/src/rust/api/issuance.dart b/lib/src/rust/api/issuance.dart index 20240f0b7..baa7321b7 100644 --- a/lib/src/rust/api/issuance.dart +++ b/lib/src/rust/api/issuance.dart @@ -36,4 +36,10 @@ Future issueAsset( required int idAccount, required Coin c}) => RustLib.instance.api.crateApiIssuanceIssueAsset( - assetName: assetName, amount: amount, firstIssuance: firstIssuance, finalize: finalize, descHash: descHash, idAccount: idAccount, c: c); + assetName: assetName, + amount: amount, + firstIssuance: firstIssuance, + finalize: finalize, + descHash: descHash, + idAccount: idAccount, + c: c); diff --git a/lib/src/rust/api/key.dart b/lib/src/rust/api/key.dart index 05287a57d..65992f57e 100644 --- a/lib/src/rust/api/key.dart +++ b/lib/src/rust/api/key.dart @@ -9,16 +9,24 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; String generateSeed() => RustLib.instance.api.crateApiKeyGenerateSeed(); -bool isValidPhrase({required String phrase}) => RustLib.instance.api.crateApiKeyIsValidPhrase(phrase: phrase); +bool isValidPhrase({required String phrase}) => + RustLib.instance.api.crateApiKeyIsValidPhrase(phrase: phrase); -bool isValidFvk({required String fvk, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidFvk(fvk: fvk, c: c); +bool isValidFvk({required String fvk, required Coin c}) => + RustLib.instance.api.crateApiKeyIsValidFvk(fvk: fvk, c: c); -bool isValidKey({required String key, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidKey(key: key, c: c); +bool isValidKey({required String key, required Coin c}) => + RustLib.instance.api.crateApiKeyIsValidKey(key: key, c: c); -bool isValidAddress({required String address}) => RustLib.instance.api.crateApiKeyIsValidAddress(address: address); +bool isValidAddress({required String address}) => + RustLib.instance.api.crateApiKeyIsValidAddress(address: address); -bool isValidTransparentAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiKeyIsValidTransparentAddress(address: address, c: c); +bool isValidTransparentAddress({required String address, required Coin c}) => + RustLib.instance.api + .crateApiKeyIsValidTransparentAddress(address: address, c: c); -bool isTexAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiKeyIsTexAddress(address: address, c: c); +bool isTexAddress({required String address, required Coin c}) => + RustLib.instance.api.crateApiKeyIsTexAddress(address: address, c: c); -int getKeyPools({required String key, required Coin c}) => RustLib.instance.api.crateApiKeyGetKeyPools(key: key, c: c); +int getKeyPools({required String key, required Coin c}) => + RustLib.instance.api.crateApiKeyGetKeyPools(key: key, c: c); diff --git a/lib/src/rust/api/mempool.dart b/lib/src/rust/api/mempool.dart index 290ee8ce1..847ca3ee0 100644 --- a/lib/src/rust/api/mempool.dart +++ b/lib/src/rust/api/mempool.dart @@ -12,7 +12,8 @@ part 'mempool.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `run_mempool` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt` -Future getMempoolTx({required String txId, required Coin c}) => RustLib.instance.api.crateApiMempoolGetMempoolTx(txId: txId, c: c); +Future getMempoolTx({required String txId, required Coin c}) => + RustLib.instance.api.crateApiMempoolGetMempoolTx(txId: txId, c: c); // Rust type: RustOpaqueMoi> abstract class Mempool implements RustOpaqueInterface { @@ -40,7 +41,11 @@ class MempoolAmount { @override bool operator ==(Object other) => identical(this, other) || - other is MempoolAmount && runtimeType == other.runtimeType && account == other.account && name == other.name && value == other.value; + other is MempoolAmount && + runtimeType == other.runtimeType && + account == other.account && + name == other.name && + value == other.value; } @freezed @@ -120,10 +125,16 @@ class MempoolTx { }); @override - int get hashCode => txid.hashCode ^ amounts.hashCode ^ notes.hashCode ^ size.hashCode; + int get hashCode => + txid.hashCode ^ amounts.hashCode ^ notes.hashCode ^ size.hashCode; @override bool operator ==(Object other) => identical(this, other) || - other is MempoolTx && runtimeType == other.runtimeType && txid == other.txid && amounts == other.amounts && notes == other.notes && size == other.size; + other is MempoolTx && + runtimeType == other.runtimeType && + txid == other.txid && + amounts == other.amounts && + notes == other.notes && + size == other.size; } diff --git a/lib/src/rust/api/mempool.freezed.dart b/lib/src/rust/api/mempool.freezed.dart index e409be207..98fd47a0a 100644 --- a/lib/src/rust/api/mempool.freezed.dart +++ b/lib/src/rust/api/mempool.freezed.dart @@ -18,11 +18,15 @@ mixin _$MempoolMsg { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is MempoolMsg && const DeepCollectionEquality().equals(other.field0, field0)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is MempoolMsg && + const DeepCollectionEquality().equals(other.field0, field0)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); @override String toString() { @@ -218,12 +222,16 @@ class MempoolMsg_BlockHeight extends MempoolMsg { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolMsg_BlockHeightCopyWith get copyWith => _$MempoolMsg_BlockHeightCopyWithImpl(this, _$identity); + $MempoolMsg_BlockHeightCopyWith get copyWith => + _$MempoolMsg_BlockHeightCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is MempoolMsg_BlockHeight && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is MempoolMsg_BlockHeight && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -236,14 +244,18 @@ class MempoolMsg_BlockHeight extends MempoolMsg { } /// @nodoc -abstract mixin class $MempoolMsg_BlockHeightCopyWith<$Res> implements $MempoolMsgCopyWith<$Res> { - factory $MempoolMsg_BlockHeightCopyWith(MempoolMsg_BlockHeight value, $Res Function(MempoolMsg_BlockHeight) _then) = _$MempoolMsg_BlockHeightCopyWithImpl; +abstract mixin class $MempoolMsg_BlockHeightCopyWith<$Res> + implements $MempoolMsgCopyWith<$Res> { + factory $MempoolMsg_BlockHeightCopyWith(MempoolMsg_BlockHeight value, + $Res Function(MempoolMsg_BlockHeight) _then) = + _$MempoolMsg_BlockHeightCopyWithImpl; @useResult $Res call({int field0}); } /// @nodoc -class _$MempoolMsg_BlockHeightCopyWithImpl<$Res> implements $MempoolMsg_BlockHeightCopyWith<$Res> { +class _$MempoolMsg_BlockHeightCopyWithImpl<$Res> + implements $MempoolMsg_BlockHeightCopyWith<$Res> { _$MempoolMsg_BlockHeightCopyWithImpl(this._self, this._then); final MempoolMsg_BlockHeight _self; @@ -276,12 +288,15 @@ class MempoolMsg_TxId extends MempoolMsg { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolMsg_TxIdCopyWith get copyWith => _$MempoolMsg_TxIdCopyWithImpl(this, _$identity); + $MempoolMsg_TxIdCopyWith get copyWith => + _$MempoolMsg_TxIdCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is MempoolMsg_TxId && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is MempoolMsg_TxId && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -294,14 +309,18 @@ class MempoolMsg_TxId extends MempoolMsg { } /// @nodoc -abstract mixin class $MempoolMsg_TxIdCopyWith<$Res> implements $MempoolMsgCopyWith<$Res> { - factory $MempoolMsg_TxIdCopyWith(MempoolMsg_TxId value, $Res Function(MempoolMsg_TxId) _then) = _$MempoolMsg_TxIdCopyWithImpl; +abstract mixin class $MempoolMsg_TxIdCopyWith<$Res> + implements $MempoolMsgCopyWith<$Res> { + factory $MempoolMsg_TxIdCopyWith( + MempoolMsg_TxId value, $Res Function(MempoolMsg_TxId) _then) = + _$MempoolMsg_TxIdCopyWithImpl; @useResult $Res call({MempoolTx field0}); } /// @nodoc -class _$MempoolMsg_TxIdCopyWithImpl<$Res> implements $MempoolMsg_TxIdCopyWith<$Res> { +class _$MempoolMsg_TxIdCopyWithImpl<$Res> + implements $MempoolMsg_TxIdCopyWith<$Res> { _$MempoolMsg_TxIdCopyWithImpl(this._self, this._then); final MempoolMsg_TxId _self; diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index 291ed0519..dd7ee381a 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -13,16 +13,19 @@ part 'migrate.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). -Future stepMigration({required Coin c}) => RustLib.instance.api.crateApiMigrateStepMigration(c: c); +Future stepMigration({required Coin c}) => + RustLib.instance.api.crateApiMigrateStepMigration(c: c); /// Stub kept for FRB generated-code compatibility. -Future getMigrationStatus({required Coin c}) => RustLib.instance.api.crateApiMigrateGetMigrationStatus(c: c); +Future getMigrationStatus({required Coin c}) => + RustLib.instance.api.crateApiMigrateGetMigrationStatus(c: c); // Rust type: RustOpaqueMoi> abstract class NoteMigration implements RustOpaqueInterface { Future cancel(); - factory NoteMigration() => RustLib.instance.api.crateApiMigrateNoteMigrationNew(); + factory NoteMigration() => + RustLib.instance.api.crateApiMigrateNoteMigrationNew(); Stream run({required Coin c, required BigInt meanDelayMs}); diff --git a/lib/src/rust/api/migrate.freezed.dart b/lib/src/rust/api/migrate.freezed.dart index c5184cc96..09e367646 100644 --- a/lib/src/rust/api/migrate.freezed.dart +++ b/lib/src/rust/api/migrate.freezed.dart @@ -16,7 +16,8 @@ T _$identity(T value) => value; mixin _$MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent); + return identical(this, other) || + (other.runtimeType == runtimeType && other is MigrationEvent); } @override @@ -89,7 +90,8 @@ extension MigrationEventPatterns on MigrationEvent { @optionalTypeArgs TResult map({ required TResult Function(MigrationEvent_SplitComplete value) splitComplete, - required TResult Function(MigrationEvent_MigrateComplete value) migrateComplete, + required TResult Function(MigrationEvent_MigrateComplete value) + migrateComplete, required TResult Function(MigrationEvent_Complete value) complete, required TResult Function(MigrationEvent_NothingToDo value) nothingToDo, required TResult Function(MigrationEvent_Error value) error, @@ -269,13 +271,16 @@ class MigrationEvent_SplitComplete extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_SplitCompleteCopyWith get copyWith => - _$MigrationEvent_SplitCompleteCopyWithImpl(this, _$identity); + $MigrationEvent_SplitCompleteCopyWith + get copyWith => _$MigrationEvent_SplitCompleteCopyWithImpl< + MigrationEvent_SplitComplete>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is MigrationEvent_SplitComplete && (identical(other.fee, fee) || other.fee == fee)); + (other.runtimeType == runtimeType && + other is MigrationEvent_SplitComplete && + (identical(other.fee, fee) || other.fee == fee)); } @override @@ -288,15 +293,19 @@ class MigrationEvent_SplitComplete extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_SplitCompleteCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_SplitCompleteCopyWith(MigrationEvent_SplitComplete value, $Res Function(MigrationEvent_SplitComplete) _then) = +abstract mixin class $MigrationEvent_SplitCompleteCopyWith<$Res> + implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_SplitCompleteCopyWith( + MigrationEvent_SplitComplete value, + $Res Function(MigrationEvent_SplitComplete) _then) = _$MigrationEvent_SplitCompleteCopyWithImpl; @useResult $Res call({BigInt fee}); } /// @nodoc -class _$MigrationEvent_SplitCompleteCopyWithImpl<$Res> implements $MigrationEvent_SplitCompleteCopyWith<$Res> { +class _$MigrationEvent_SplitCompleteCopyWithImpl<$Res> + implements $MigrationEvent_SplitCompleteCopyWith<$Res> { _$MigrationEvent_SplitCompleteCopyWithImpl(this._self, this._then); final MigrationEvent_SplitComplete _self; @@ -328,13 +337,16 @@ class MigrationEvent_MigrateComplete extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_MigrateCompleteCopyWith get copyWith => - _$MigrationEvent_MigrateCompleteCopyWithImpl(this, _$identity); + $MigrationEvent_MigrateCompleteCopyWith + get copyWith => _$MigrationEvent_MigrateCompleteCopyWithImpl< + MigrationEvent_MigrateComplete>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is MigrationEvent_MigrateComplete && (identical(other.fee, fee) || other.fee == fee)); + (other.runtimeType == runtimeType && + other is MigrationEvent_MigrateComplete && + (identical(other.fee, fee) || other.fee == fee)); } @override @@ -347,15 +359,19 @@ class MigrationEvent_MigrateComplete extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_MigrateCompleteCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_MigrateCompleteCopyWith(MigrationEvent_MigrateComplete value, $Res Function(MigrationEvent_MigrateComplete) _then) = +abstract mixin class $MigrationEvent_MigrateCompleteCopyWith<$Res> + implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_MigrateCompleteCopyWith( + MigrationEvent_MigrateComplete value, + $Res Function(MigrationEvent_MigrateComplete) _then) = _$MigrationEvent_MigrateCompleteCopyWithImpl; @useResult $Res call({BigInt fee}); } /// @nodoc -class _$MigrationEvent_MigrateCompleteCopyWithImpl<$Res> implements $MigrationEvent_MigrateCompleteCopyWith<$Res> { +class _$MigrationEvent_MigrateCompleteCopyWithImpl<$Res> + implements $MigrationEvent_MigrateCompleteCopyWith<$Res> { _$MigrationEvent_MigrateCompleteCopyWithImpl(this._self, this._then); final MigrationEvent_MigrateComplete _self; @@ -383,7 +399,8 @@ class MigrationEvent_Complete extends MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent_Complete); + return identical(this, other) || + (other.runtimeType == runtimeType && other is MigrationEvent_Complete); } @override @@ -402,7 +419,9 @@ class MigrationEvent_NothingToDo extends MigrationEvent { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is MigrationEvent_NothingToDo); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is MigrationEvent_NothingToDo); } @override @@ -425,12 +444,16 @@ class MigrationEvent_Error extends MigrationEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MigrationEvent_ErrorCopyWith get copyWith => _$MigrationEvent_ErrorCopyWithImpl(this, _$identity); + $MigrationEvent_ErrorCopyWith get copyWith => + _$MigrationEvent_ErrorCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is MigrationEvent_Error && (identical(other.message, message) || other.message == message)); + (other.runtimeType == runtimeType && + other is MigrationEvent_Error && + (identical(other.message, message) || other.message == message)); } @override @@ -443,14 +466,18 @@ class MigrationEvent_Error extends MigrationEvent { } /// @nodoc -abstract mixin class $MigrationEvent_ErrorCopyWith<$Res> implements $MigrationEventCopyWith<$Res> { - factory $MigrationEvent_ErrorCopyWith(MigrationEvent_Error value, $Res Function(MigrationEvent_Error) _then) = _$MigrationEvent_ErrorCopyWithImpl; +abstract mixin class $MigrationEvent_ErrorCopyWith<$Res> + implements $MigrationEventCopyWith<$Res> { + factory $MigrationEvent_ErrorCopyWith(MigrationEvent_Error value, + $Res Function(MigrationEvent_Error) _then) = + _$MigrationEvent_ErrorCopyWithImpl; @useResult $Res call({String message}); } /// @nodoc -class _$MigrationEvent_ErrorCopyWithImpl<$Res> implements $MigrationEvent_ErrorCopyWith<$Res> { +class _$MigrationEvent_ErrorCopyWithImpl<$Res> + implements $MigrationEvent_ErrorCopyWith<$Res> { _$MigrationEvent_ErrorCopyWithImpl(this._self, this._then); final MigrationEvent_Error _self; diff --git a/lib/src/rust/api/network.dart b/lib/src/rust/api/network.dart index 434c4f910..05afff178 100644 --- a/lib/src/rust/api/network.dart +++ b/lib/src/rust/api/network.dart @@ -12,26 +12,38 @@ part 'network.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `coingecko_client` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt` -Future initDatadir({required String directory}) => RustLib.instance.api.crateApiNetworkInitDatadir(directory: directory); +Future initDatadir({required String directory}) => + RustLib.instance.api.crateApiNetworkInitDatadir(directory: directory); -Future isIronwoodActive({required Coin c}) => RustLib.instance.api.crateApiNetworkIsIronwoodActive(c: c); +Future isIronwoodActive({required Coin c}) => + RustLib.instance.api.crateApiNetworkIsIronwoodActive(c: c); -Future getCurrentHeight({required Coin c}) => RustLib.instance.api.crateApiNetworkGetCurrentHeight(c: c); +Future getCurrentHeight({required Coin c}) => + RustLib.instance.api.crateApiNetworkGetCurrentHeight(c: c); -Future getCoingeckoPrice({required String api, required String currency}) => - RustLib.instance.api.crateApiNetworkGetCoingeckoPrice(api: api, currency: currency); +Future getCoingeckoPrice( + {required String api, required String currency}) => + RustLib.instance.api + .crateApiNetworkGetCoingeckoPrice(api: api, currency: currency); -Future> getSupportedVsCurrencies({required String api}) => RustLib.instance.api.crateApiNetworkGetSupportedVsCurrencies(api: api); +Future> getSupportedVsCurrencies({required String api}) => + RustLib.instance.api.crateApiNetworkGetSupportedVsCurrencies(api: api); /// Returns the ZEC price in both `from_currency` and `to_currency`. /// The exchange rate from `from_currency` to `to_currency` can be computed as /// `to_price / from_price`. -Future getExchangeRate({required String api, required String fromCurrency, required String toCurrency}) => - RustLib.instance.api.crateApiNetworkGetExchangeRate(api: api, fromCurrency: fromCurrency, toCurrency: toCurrency); +Future getExchangeRate( + {required String api, + required String fromCurrency, + required String toCurrency}) => + RustLib.instance.api.crateApiNetworkGetExchangeRate( + api: api, fromCurrency: fromCurrency, toCurrency: toCurrency); -Future getNetworkName({required Coin c}) => RustLib.instance.api.crateApiNetworkGetNetworkName(c: c); +Future getNetworkName({required Coin c}) => + RustLib.instance.api.crateApiNetworkGetNetworkName(c: c); -Future> queryLwdList({required int coin}) => RustLib.instance.api.crateApiNetworkQueryLwdList(coin: coin); +Future> queryLwdList({required int coin}) => + RustLib.instance.api.crateApiNetworkQueryLwdList(coin: coin); @freezed sealed class ExchangeRate with _$ExchangeRate { diff --git a/lib/src/rust/api/network.freezed.dart b/lib/src/rust/api/network.freezed.dart index 94697f15e..7ed5a4bb3 100644 --- a/lib/src/rust/api/network.freezed.dart +++ b/lib/src/rust/api/network.freezed.dart @@ -23,21 +23,27 @@ mixin _$ExchangeRate { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ExchangeRateCopyWith get copyWith => _$ExchangeRateCopyWithImpl(this as ExchangeRate, _$identity); + $ExchangeRateCopyWith get copyWith => + _$ExchangeRateCopyWithImpl( + this as ExchangeRate, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is ExchangeRate && - (identical(other.fromPrice, fromPrice) || other.fromPrice == fromPrice) && + (identical(other.fromPrice, fromPrice) || + other.fromPrice == fromPrice) && (identical(other.toPrice, toPrice) || other.toPrice == toPrice) && - (identical(other.fromCurrency, fromCurrency) || other.fromCurrency == fromCurrency) && - (identical(other.toCurrency, toCurrency) || other.toCurrency == toCurrency)); + (identical(other.fromCurrency, fromCurrency) || + other.fromCurrency == fromCurrency) && + (identical(other.toCurrency, toCurrency) || + other.toCurrency == toCurrency)); } @override - int get hashCode => Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); + int get hashCode => + Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); @override String toString() { @@ -47,9 +53,15 @@ mixin _$ExchangeRate { /// @nodoc abstract mixin class $ExchangeRateCopyWith<$Res> { - factory $ExchangeRateCopyWith(ExchangeRate value, $Res Function(ExchangeRate) _then) = _$ExchangeRateCopyWithImpl; + factory $ExchangeRateCopyWith( + ExchangeRate value, $Res Function(ExchangeRate) _then) = + _$ExchangeRateCopyWithImpl; @useResult - $Res call({double fromPrice, double toPrice, String fromCurrency, String toCurrency}); + $Res call( + {double fromPrice, + double toPrice, + String fromCurrency, + String toCurrency}); } /// @nodoc @@ -181,13 +193,16 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult maybeWhen( - TResult Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency)? $default, { + TResult Function(double fromPrice, double toPrice, String fromCurrency, + String toCurrency)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _ExchangeRate() when $default != null: - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, + _that.toCurrency); case _: return orElse(); } @@ -208,12 +223,15 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult when( - TResult Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency) $default, + TResult Function(double fromPrice, double toPrice, String fromCurrency, + String toCurrency) + $default, ) { final _that = this; switch (_that) { case _ExchangeRate(): - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, + _that.toCurrency); } } @@ -231,12 +249,15 @@ extension ExchangeRatePatterns on ExchangeRate { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(double fromPrice, double toPrice, String fromCurrency, String toCurrency)? $default, + TResult? Function(double fromPrice, double toPrice, String fromCurrency, + String toCurrency)? + $default, ) { final _that = this; switch (_that) { case _ExchangeRate() when $default != null: - return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, _that.toCurrency); + return $default(_that.fromPrice, _that.toPrice, _that.fromCurrency, + _that.toCurrency); case _: return null; } @@ -246,7 +267,11 @@ extension ExchangeRatePatterns on ExchangeRate { /// @nodoc class _ExchangeRate implements ExchangeRate { - const _ExchangeRate({required this.fromPrice, required this.toPrice, required this.fromCurrency, required this.toCurrency}); + const _ExchangeRate( + {required this.fromPrice, + required this.toPrice, + required this.fromCurrency, + required this.toCurrency}); @override final double fromPrice; @@ -262,21 +287,26 @@ class _ExchangeRate implements ExchangeRate { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ExchangeRateCopyWith<_ExchangeRate> get copyWith => __$ExchangeRateCopyWithImpl<_ExchangeRate>(this, _$identity); + _$ExchangeRateCopyWith<_ExchangeRate> get copyWith => + __$ExchangeRateCopyWithImpl<_ExchangeRate>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _ExchangeRate && - (identical(other.fromPrice, fromPrice) || other.fromPrice == fromPrice) && + (identical(other.fromPrice, fromPrice) || + other.fromPrice == fromPrice) && (identical(other.toPrice, toPrice) || other.toPrice == toPrice) && - (identical(other.fromCurrency, fromCurrency) || other.fromCurrency == fromCurrency) && - (identical(other.toCurrency, toCurrency) || other.toCurrency == toCurrency)); + (identical(other.fromCurrency, fromCurrency) || + other.fromCurrency == fromCurrency) && + (identical(other.toCurrency, toCurrency) || + other.toCurrency == toCurrency)); } @override - int get hashCode => Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); + int get hashCode => + Object.hash(runtimeType, fromPrice, toPrice, fromCurrency, toCurrency); @override String toString() { @@ -285,15 +315,23 @@ class _ExchangeRate implements ExchangeRate { } /// @nodoc -abstract mixin class _$ExchangeRateCopyWith<$Res> implements $ExchangeRateCopyWith<$Res> { - factory _$ExchangeRateCopyWith(_ExchangeRate value, $Res Function(_ExchangeRate) _then) = __$ExchangeRateCopyWithImpl; +abstract mixin class _$ExchangeRateCopyWith<$Res> + implements $ExchangeRateCopyWith<$Res> { + factory _$ExchangeRateCopyWith( + _ExchangeRate value, $Res Function(_ExchangeRate) _then) = + __$ExchangeRateCopyWithImpl; @override @useResult - $Res call({double fromPrice, double toPrice, String fromCurrency, String toCurrency}); + $Res call( + {double fromPrice, + double toPrice, + String fromCurrency, + String toCurrency}); } /// @nodoc -class __$ExchangeRateCopyWithImpl<$Res> implements _$ExchangeRateCopyWith<$Res> { +class __$ExchangeRateCopyWithImpl<$Res> + implements _$ExchangeRateCopyWith<$Res> { __$ExchangeRateCopyWithImpl(this._self, this._then); final _ExchangeRate _self; @@ -344,7 +382,8 @@ mixin _$LWDInfo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $LWDInfoCopyWith get copyWith => _$LWDInfoCopyWithImpl(this as LWDInfo, _$identity); + $LWDInfoCopyWith get copyWith => + _$LWDInfoCopyWithImpl(this as LWDInfo, _$identity); @override bool operator ==(Object other) { @@ -361,7 +400,8 @@ mixin _$LWDInfo { } @override - int get hashCode => Object.hash(runtimeType, url, isTor, height, status, uptime, version, ping); + int get hashCode => Object.hash( + runtimeType, url, isTor, height, status, uptime, version, ping); @override String toString() { @@ -371,9 +411,17 @@ mixin _$LWDInfo { /// @nodoc abstract mixin class $LWDInfoCopyWith<$Res> { - factory $LWDInfoCopyWith(LWDInfo value, $Res Function(LWDInfo) _then) = _$LWDInfoCopyWithImpl; + factory $LWDInfoCopyWith(LWDInfo value, $Res Function(LWDInfo) _then) = + _$LWDInfoCopyWithImpl; @useResult - $Res call({String url, bool isTor, int height, String status, int uptime, String version, int ping}); + $Res call( + {String url, + bool isTor, + int height, + String status, + int uptime, + String version, + int ping}); } /// @nodoc @@ -520,13 +568,16 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult maybeWhen( - TResult Function(String url, bool isTor, int height, String status, int uptime, String version, int ping)? $default, { + TResult Function(String url, bool isTor, int height, String status, + int uptime, String version, int ping)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _LWDInfo() when $default != null: - return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, + _that.uptime, _that.version, _that.ping); case _: return orElse(); } @@ -547,12 +598,15 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult when( - TResult Function(String url, bool isTor, int height, String status, int uptime, String version, int ping) $default, + TResult Function(String url, bool isTor, int height, String status, + int uptime, String version, int ping) + $default, ) { final _that = this; switch (_that) { case _LWDInfo(): - return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, + _that.uptime, _that.version, _that.ping); } } @@ -570,12 +624,15 @@ extension LWDInfoPatterns on LWDInfo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String url, bool isTor, int height, String status, int uptime, String version, int ping)? $default, + TResult? Function(String url, bool isTor, int height, String status, + int uptime, String version, int ping)? + $default, ) { final _that = this; switch (_that) { case _LWDInfo() when $default != null: - return $default(_that.url, _that.isTor, _that.height, _that.status, _that.uptime, _that.version, _that.ping); + return $default(_that.url, _that.isTor, _that.height, _that.status, + _that.uptime, _that.version, _that.ping); case _: return null; } @@ -586,7 +643,13 @@ extension LWDInfoPatterns on LWDInfo { class _LWDInfo implements LWDInfo { const _LWDInfo( - {required this.url, required this.isTor, required this.height, required this.status, required this.uptime, required this.version, required this.ping}); + {required this.url, + required this.isTor, + required this.height, + required this.status, + required this.uptime, + required this.version, + required this.ping}); @override final String url; @@ -608,7 +671,8 @@ class _LWDInfo implements LWDInfo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$LWDInfoCopyWith<_LWDInfo> get copyWith => __$LWDInfoCopyWithImpl<_LWDInfo>(this, _$identity); + _$LWDInfoCopyWith<_LWDInfo> get copyWith => + __$LWDInfoCopyWithImpl<_LWDInfo>(this, _$identity); @override bool operator ==(Object other) { @@ -625,7 +689,8 @@ class _LWDInfo implements LWDInfo { } @override - int get hashCode => Object.hash(runtimeType, url, isTor, height, status, uptime, version, ping); + int get hashCode => Object.hash( + runtimeType, url, isTor, height, status, uptime, version, ping); @override String toString() { @@ -635,10 +700,18 @@ class _LWDInfo implements LWDInfo { /// @nodoc abstract mixin class _$LWDInfoCopyWith<$Res> implements $LWDInfoCopyWith<$Res> { - factory _$LWDInfoCopyWith(_LWDInfo value, $Res Function(_LWDInfo) _then) = __$LWDInfoCopyWithImpl; + factory _$LWDInfoCopyWith(_LWDInfo value, $Res Function(_LWDInfo) _then) = + __$LWDInfoCopyWithImpl; @override @useResult - $Res call({String url, bool isTor, int height, String status, int uptime, String version, int ping}); + $Res call( + {String url, + bool isTor, + int height, + String status, + int uptime, + String version, + int ping}); } /// @nodoc diff --git a/lib/src/rust/api/openalias.dart b/lib/src/rust/api/openalias.dart index 5c9507625..7e0e0fb46 100644 --- a/lib/src/rust/api/openalias.dart +++ b/lib/src/rust/api/openalias.dart @@ -15,32 +15,39 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// /// Performs DNS TXT lookup, parses OA1 records, filters for Zcash /// addresses, and validates them against the wallet's network type. -Future resolveOpenalias({required String alias, required Coin c}) => +Future resolveOpenalias( + {required String alias, required Coin c}) => RustLib.instance.api.crateApiOpenaliasResolveOpenalias(alias: alias, c: c); /// Resolve an OpenAlias name and return ALL cryptocurrency addresses /// found (not just Zcash) as [`Recipient`]s. -Future resolveOpenaliasAll({required String alias}) => RustLib.instance.api.crateApiOpenaliasResolveOpenaliasAll(alias: alias); +Future resolveOpenaliasAll({required String alias}) => + RustLib.instance.api.crateApiOpenaliasResolveOpenaliasAll(alias: alias); /// Validate whether a string looks like a valid OpenAlias name format. /// Returns true/false without performing any DNS lookup. -bool validateOpenaliasName({required String alias}) => RustLib.instance.api.crateApiOpenaliasValidateOpenaliasName(alias: alias); +bool validateOpenaliasName({required String alias}) => + RustLib.instance.api.crateApiOpenaliasValidateOpenaliasName(alias: alias); /// Validate that an address string is a syntactically valid Zcash address /// for the wallet's network (convenience wrapper returning bool). /// /// See [`try_validate_zcash_address`] for the `Result`-returning variant /// that provides error details. -bool validateZcashAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiOpenaliasValidateZcashAddress(address: address, c: c); +bool validateZcashAddress({required String address, required Coin c}) => + RustLib.instance.api + .crateApiOpenaliasValidateZcashAddress(address: address, c: c); /// Try to validate that an address string is a syntactically valid Zcash /// address for the wallet's network, returning `Ok(())` or an error with /// details about why validation failed. void tryValidateZcashAddress({required String address, required Coin c}) => - RustLib.instance.api.crateApiOpenaliasTryValidateZcashAddress(address: address, c: c); + RustLib.instance.api + .crateApiOpenaliasTryValidateZcashAddress(address: address, c: c); /// Get the raw OpenAlias TXT record strings for diagnostic purposes. -Future resolveOpenaliasRaw({required String alias}) => RustLib.instance.api.crateApiOpenaliasResolveOpenaliasRaw(alias: alias); +Future resolveOpenaliasRaw({required String alias}) => + RustLib.instance.api.crateApiOpenaliasResolveOpenaliasRaw(alias: alias); /// Result of an OpenAlias resolution, including DNSSEC verification status. class OpenAliasResolution { @@ -60,7 +67,10 @@ class OpenAliasResolution { @override bool operator ==(Object other) => identical(this, other) || - other is OpenAliasResolution && runtimeType == other.runtimeType && recipients == other.recipients && dnssecStatus == other.dnssecStatus; + other is OpenAliasResolution && + runtimeType == other.runtimeType && + recipients == other.recipients && + dnssecStatus == other.dnssecStatus; } /// Result of a raw OpenAlias resolution, including DNSSEC verification status. @@ -81,5 +91,8 @@ class RawOpenAliasResolution { @override bool operator ==(Object other) => identical(this, other) || - other is RawOpenAliasResolution && runtimeType == other.runtimeType && records == other.records && dnssecStatus == other.dnssecStatus; + other is RawOpenAliasResolution && + runtimeType == other.runtimeType && + records == other.records && + dnssecStatus == other.dnssecStatus; } diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index 9da534193..5af48ef4c 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -13,35 +13,61 @@ part 'pay.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `borrow_decode`, `decode`, `encode` -Future buildPuri({required List recipients}) => RustLib.instance.api.crateApiPayBuildPuri(recipients: recipients); +Future buildPuri({required List recipients}) => + RustLib.instance.api.crateApiPayBuildPuri(recipients: recipients); -Future prepare({required List recipients, required PaymentOptions options, required Coin c}) => - RustLib.instance.api.crateApiPayPrepare(recipients: recipients, options: options, c: c); +Future prepare( + {required List recipients, + required PaymentOptions options, + required Coin c}) => + RustLib.instance.api + .crateApiPayPrepare(recipients: recipients, options: options, c: c); /// Prepare a migration transaction (splitting or migrating). /// Uses `migration=true` to allow Orchard outputs when Ironwood is active. -Future prepareMigration({required List recipients, required int srcPools, required Coin c}) => - RustLib.instance.api.crateApiPayPrepareMigration(recipients: recipients, srcPools: srcPools, c: c); - -Future signTransaction({required PcztPackage pczt, required Coin c}) => RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); - -Future extractTransaction({required PcztPackage package}) => RustLib.instance.api.crateApiPayExtractTransaction(package: package); - -Future packTransaction({required PcztPackage pczt}) => RustLib.instance.api.crateApiPayPackTransaction(pczt: pczt); - -Future unpackTransaction({required List bytes}) => RustLib.instance.api.crateApiPayUnpackTransaction(bytes: bytes); - -Future broadcastTransaction({required int height, required List txBytes, required Coin c}) => - RustLib.instance.api.crateApiPayBroadcastTransaction(height: height, txBytes: txBytes, c: c); - -TxPlan toPlan({required PcztPackage package, required Coin c}) => RustLib.instance.api.crateApiPayToPlan(package: package, c: c); - -Future send({required int height, required List data, required Coin c}) => RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); - -Future storePendingTx({required int height, required List txid, double? price, int? category, required Coin c}) => - RustLib.instance.api.crateApiPayStorePendingTx(height: height, txid: txid, price: price, category: category, c: c); - -List? parsePaymentUri({required String uri}) => RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); +Future prepareMigration( + {required List recipients, + required int srcPools, + required Coin c}) => + RustLib.instance.api.crateApiPayPrepareMigration( + recipients: recipients, srcPools: srcPools, c: c); + +Future signTransaction( + {required PcztPackage pczt, required Coin c}) => + RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); + +Future extractTransaction({required PcztPackage package}) => + RustLib.instance.api.crateApiPayExtractTransaction(package: package); + +Future packTransaction({required PcztPackage pczt}) => + RustLib.instance.api.crateApiPayPackTransaction(pczt: pczt); + +Future unpackTransaction({required List bytes}) => + RustLib.instance.api.crateApiPayUnpackTransaction(bytes: bytes); + +Future broadcastTransaction( + {required int height, required List txBytes, required Coin c}) => + RustLib.instance.api.crateApiPayBroadcastTransaction( + height: height, txBytes: txBytes, c: c); + +TxPlan toPlan({required PcztPackage package, required Coin c}) => + RustLib.instance.api.crateApiPayToPlan(package: package, c: c); + +Future send( + {required int height, required List data, required Coin c}) => + RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); + +Future storePendingTx( + {required int height, + required List txid, + double? price, + int? category, + required Coin c}) => + RustLib.instance.api.crateApiPayStorePendingTx( + height: height, txid: txid, price: price, category: category, c: c); + +List? parsePaymentUri({required String uri}) => + RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); class PaymentOptions { final int srcPools; @@ -57,7 +83,11 @@ class PaymentOptions { }); @override - int get hashCode => srcPools.hashCode ^ recipientPaysFee.hashCode ^ smartTransparent.hashCode ^ category.hashCode; + int get hashCode => + srcPools.hashCode ^ + recipientPaysFee.hashCode ^ + smartTransparent.hashCode ^ + category.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/pay.freezed.dart b/lib/src/rust/api/pay.freezed.dart index 10328fae2..489143a29 100644 --- a/lib/src/rust/api/pay.freezed.dart +++ b/lib/src/rust/api/pay.freezed.dart @@ -29,7 +29,8 @@ mixin _$PcztPackage { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $PcztPackageCopyWith get copyWith => _$PcztPackageCopyWithImpl(this as PcztPackage, _$identity); + $PcztPackageCopyWith get copyWith => + _$PcztPackageCopyWithImpl(this as PcztPackage, _$identity); @override bool operator ==(Object other) { @@ -38,14 +39,20 @@ mixin _$PcztPackage { other is PcztPackage && const DeepCollectionEquality().equals(other.pczt, pczt) && const DeepCollectionEquality().equals(other.nSpends, nSpends) && - const DeepCollectionEquality().equals(other.saplingIndices, saplingIndices) && - const DeepCollectionEquality().equals(other.orchardIndices, orchardIndices) && - const DeepCollectionEquality().equals(other.ironwoodIndices, ironwoodIndices) && + const DeepCollectionEquality() + .equals(other.saplingIndices, saplingIndices) && + const DeepCollectionEquality() + .equals(other.orchardIndices, orchardIndices) && + const DeepCollectionEquality() + .equals(other.ironwoodIndices, ironwoodIndices) && (identical(other.canSign, canSign) || other.canSign == canSign) && - (identical(other.canBroadcast, canBroadcast) || other.canBroadcast == canBroadcast) && + (identical(other.canBroadcast, canBroadcast) || + other.canBroadcast == canBroadcast) && (identical(other.price, price) || other.price == price) && - (identical(other.category, category) || other.category == category) && - (identical(other.isIssuance, isIssuance) || other.isIssuance == isIssuance)); + (identical(other.category, category) || + other.category == category) && + (identical(other.isIssuance, isIssuance) || + other.isIssuance == isIssuance)); } @override @@ -70,7 +77,9 @@ mixin _$PcztPackage { /// @nodoc abstract mixin class $PcztPackageCopyWith<$Res> { - factory $PcztPackageCopyWith(PcztPackage value, $Res Function(PcztPackage) _then) = _$PcztPackageCopyWithImpl; + factory $PcztPackageCopyWith( + PcztPackage value, $Res Function(PcztPackage) _then) = + _$PcztPackageCopyWithImpl; @useResult $Res call( {Uint8List pczt, @@ -244,16 +253,34 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult maybeWhen( - TResult Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, - bool canBroadcast, double? price, int? category, bool isIssuance)? + TResult Function( + Uint8List pczt, + UsizeArray4 nSpends, + Uint64List saplingIndices, + Uint64List orchardIndices, + Uint64List ironwoodIndices, + bool canSign, + bool canBroadcast, + double? price, + int? category, + bool isIssuance)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _PcztPackage() when $default != null: - return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, - _that.price, _that.category, _that.isIssuance); + return $default( + _that.pczt, + _that.nSpends, + _that.saplingIndices, + _that.orchardIndices, + _that.ironwoodIndices, + _that.canSign, + _that.canBroadcast, + _that.price, + _that.category, + _that.isIssuance); case _: return orElse(); } @@ -274,15 +301,33 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult when( - TResult Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, - bool canBroadcast, double? price, int? category, bool isIssuance) + TResult Function( + Uint8List pczt, + UsizeArray4 nSpends, + Uint64List saplingIndices, + Uint64List orchardIndices, + Uint64List ironwoodIndices, + bool canSign, + bool canBroadcast, + double? price, + int? category, + bool isIssuance) $default, ) { final _that = this; switch (_that) { case _PcztPackage(): - return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, - _that.price, _that.category, _that.isIssuance); + return $default( + _that.pczt, + _that.nSpends, + _that.saplingIndices, + _that.orchardIndices, + _that.ironwoodIndices, + _that.canSign, + _that.canBroadcast, + _that.price, + _that.category, + _that.isIssuance); } } @@ -300,15 +345,33 @@ extension PcztPackagePatterns on PcztPackage { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Uint8List pczt, UsizeArray4 nSpends, Uint64List saplingIndices, Uint64List orchardIndices, Uint64List ironwoodIndices, bool canSign, - bool canBroadcast, double? price, int? category, bool isIssuance)? + TResult? Function( + Uint8List pczt, + UsizeArray4 nSpends, + Uint64List saplingIndices, + Uint64List orchardIndices, + Uint64List ironwoodIndices, + bool canSign, + bool canBroadcast, + double? price, + int? category, + bool isIssuance)? $default, ) { final _that = this; switch (_that) { case _PcztPackage() when $default != null: - return $default(_that.pczt, _that.nSpends, _that.saplingIndices, _that.orchardIndices, _that.ironwoodIndices, _that.canSign, _that.canBroadcast, - _that.price, _that.category, _that.isIssuance); + return $default( + _that.pczt, + _that.nSpends, + _that.saplingIndices, + _that.orchardIndices, + _that.ironwoodIndices, + _that.canSign, + _that.canBroadcast, + _that.price, + _that.category, + _that.isIssuance); case _: return null; } @@ -356,7 +419,8 @@ class _PcztPackage implements PcztPackage { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$PcztPackageCopyWith<_PcztPackage> get copyWith => __$PcztPackageCopyWithImpl<_PcztPackage>(this, _$identity); + _$PcztPackageCopyWith<_PcztPackage> get copyWith => + __$PcztPackageCopyWithImpl<_PcztPackage>(this, _$identity); @override bool operator ==(Object other) { @@ -365,14 +429,20 @@ class _PcztPackage implements PcztPackage { other is _PcztPackage && const DeepCollectionEquality().equals(other.pczt, pczt) && const DeepCollectionEquality().equals(other.nSpends, nSpends) && - const DeepCollectionEquality().equals(other.saplingIndices, saplingIndices) && - const DeepCollectionEquality().equals(other.orchardIndices, orchardIndices) && - const DeepCollectionEquality().equals(other.ironwoodIndices, ironwoodIndices) && + const DeepCollectionEquality() + .equals(other.saplingIndices, saplingIndices) && + const DeepCollectionEquality() + .equals(other.orchardIndices, orchardIndices) && + const DeepCollectionEquality() + .equals(other.ironwoodIndices, ironwoodIndices) && (identical(other.canSign, canSign) || other.canSign == canSign) && - (identical(other.canBroadcast, canBroadcast) || other.canBroadcast == canBroadcast) && + (identical(other.canBroadcast, canBroadcast) || + other.canBroadcast == canBroadcast) && (identical(other.price, price) || other.price == price) && - (identical(other.category, category) || other.category == category) && - (identical(other.isIssuance, isIssuance) || other.isIssuance == isIssuance)); + (identical(other.category, category) || + other.category == category) && + (identical(other.isIssuance, isIssuance) || + other.isIssuance == isIssuance)); } @override @@ -396,8 +466,11 @@ class _PcztPackage implements PcztPackage { } /// @nodoc -abstract mixin class _$PcztPackageCopyWith<$Res> implements $PcztPackageCopyWith<$Res> { - factory _$PcztPackageCopyWith(_PcztPackage value, $Res Function(_PcztPackage) _then) = __$PcztPackageCopyWithImpl; +abstract mixin class _$PcztPackageCopyWith<$Res> + implements $PcztPackageCopyWith<$Res> { + factory _$PcztPackageCopyWith( + _PcztPackage value, $Res Function(_PcztPackage) _then) = + __$PcztPackageCopyWithImpl; @override @useResult $Res call( @@ -487,11 +560,15 @@ mixin _$SigningEvent { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is SigningEvent && const DeepCollectionEquality().equals(other.field0, field0)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningEvent && + const DeepCollectionEquality().equals(other.field0, field0)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(field0)); @override String toString() { @@ -687,12 +764,16 @@ class SigningEvent_Progress extends SigningEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningEvent_ProgressCopyWith get copyWith => _$SigningEvent_ProgressCopyWithImpl(this, _$identity); + $SigningEvent_ProgressCopyWith get copyWith => + _$SigningEvent_ProgressCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is SigningEvent_Progress && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is SigningEvent_Progress && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -705,14 +786,18 @@ class SigningEvent_Progress extends SigningEvent { } /// @nodoc -abstract mixin class $SigningEvent_ProgressCopyWith<$Res> implements $SigningEventCopyWith<$Res> { - factory $SigningEvent_ProgressCopyWith(SigningEvent_Progress value, $Res Function(SigningEvent_Progress) _then) = _$SigningEvent_ProgressCopyWithImpl; +abstract mixin class $SigningEvent_ProgressCopyWith<$Res> + implements $SigningEventCopyWith<$Res> { + factory $SigningEvent_ProgressCopyWith(SigningEvent_Progress value, + $Res Function(SigningEvent_Progress) _then) = + _$SigningEvent_ProgressCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$SigningEvent_ProgressCopyWithImpl<$Res> implements $SigningEvent_ProgressCopyWith<$Res> { +class _$SigningEvent_ProgressCopyWithImpl<$Res> + implements $SigningEvent_ProgressCopyWith<$Res> { _$SigningEvent_ProgressCopyWithImpl(this._self, this._then); final SigningEvent_Progress _self; @@ -745,12 +830,15 @@ class SigningEvent_Result extends SigningEvent { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SigningEvent_ResultCopyWith get copyWith => _$SigningEvent_ResultCopyWithImpl(this, _$identity); + $SigningEvent_ResultCopyWith get copyWith => + _$SigningEvent_ResultCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is SigningEvent_Result && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is SigningEvent_Result && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -763,8 +851,11 @@ class SigningEvent_Result extends SigningEvent { } /// @nodoc -abstract mixin class $SigningEvent_ResultCopyWith<$Res> implements $SigningEventCopyWith<$Res> { - factory $SigningEvent_ResultCopyWith(SigningEvent_Result value, $Res Function(SigningEvent_Result) _then) = _$SigningEvent_ResultCopyWithImpl; +abstract mixin class $SigningEvent_ResultCopyWith<$Res> + implements $SigningEventCopyWith<$Res> { + factory $SigningEvent_ResultCopyWith( + SigningEvent_Result value, $Res Function(SigningEvent_Result) _then) = + _$SigningEvent_ResultCopyWithImpl; @useResult $Res call({PcztPackage field0}); @@ -772,7 +863,8 @@ abstract mixin class $SigningEvent_ResultCopyWith<$Res> implements $SigningEvent } /// @nodoc -class _$SigningEvent_ResultCopyWithImpl<$Res> implements $SigningEvent_ResultCopyWith<$Res> { +class _$SigningEvent_ResultCopyWithImpl<$Res> + implements $SigningEvent_ResultCopyWith<$Res> { _$SigningEvent_ResultCopyWithImpl(this._self, this._then); final SigningEvent_Result _self; diff --git a/lib/src/rust/api/plugin.dart b/lib/src/rust/api/plugin.dart index 739965a1d..773ec276d 100644 --- a/lib/src/rust/api/plugin.dart +++ b/lib/src/rust/api/plugin.dart @@ -10,23 +10,30 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'plugin.freezed.dart'; /// List all installed plugins. -Future> listPlugins({required Coin c}) => RustLib.instance.api.crateApiPluginListPlugins(c: c); +Future> listPlugins({required Coin c}) => + RustLib.instance.api.crateApiPluginListPlugins(c: c); /// Install a plugin from a URL (downloads a .zip archive). -Future installPlugin({required String url, required Coin c}) => RustLib.instance.api.crateApiPluginInstallPlugin(url: url, c: c); +Future installPlugin({required String url, required Coin c}) => + RustLib.instance.api.crateApiPluginInstallPlugin(url: url, c: c); /// Remove a plugin completely (files + DB). -Future removePlugin({required String id, required Coin c}) => RustLib.instance.api.crateApiPluginRemovePlugin(id: id, c: c); +Future removePlugin({required String id, required Coin c}) => + RustLib.instance.api.crateApiPluginRemovePlugin(id: id, c: c); /// Enable or disable a plugin. -Future setPluginEnabled({required String id, required bool enabled, required Coin c}) => - RustLib.instance.api.crateApiPluginSetPluginEnabled(id: id, enabled: enabled, c: c); +Future setPluginEnabled( + {required String id, required bool enabled, required Coin c}) => + RustLib.instance.api + .crateApiPluginSetPluginEnabled(id: id, enabled: enabled, c: c); /// Parse a memo with all matching plugins. /// `memo_bytes` is the full 512-byte memo (including the 0xFF type byte). /// Returns sections from all plugins whose prefixes match. -Future> parseMemoWithPlugins({required List memoBytes, required Coin c}) => - RustLib.instance.api.crateApiPluginParseMemoWithPlugins(memoBytes: memoBytes, c: c); +Future> parseMemoWithPlugins( + {required List memoBytes, required Coin c}) => + RustLib.instance.api + .crateApiPluginParseMemoWithPlugins(memoBytes: memoBytes, c: c); /// Initialize the plugin system at app startup (creates plugins directory). void initPlugins() => RustLib.instance.api.crateApiPluginInitPlugins(); diff --git a/lib/src/rust/api/plugin.freezed.dart b/lib/src/rust/api/plugin.freezed.dart index 563e395aa..60e74f136 100644 --- a/lib/src/rust/api/plugin.freezed.dart +++ b/lib/src/rust/api/plugin.freezed.dart @@ -21,14 +21,16 @@ mixin _$MemoCell { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoCellCopyWith get copyWith => _$MemoCellCopyWithImpl(this as MemoCell, _$identity); + $MemoCellCopyWith get copyWith => + _$MemoCellCopyWithImpl(this as MemoCell, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is MemoCell && - (identical(other.cellType, cellType) || other.cellType == cellType) && + (identical(other.cellType, cellType) || + other.cellType == cellType) && (identical(other.value, value) || other.value == value)); } @@ -43,7 +45,8 @@ mixin _$MemoCell { /// @nodoc abstract mixin class $MemoCellCopyWith<$Res> { - factory $MemoCellCopyWith(MemoCell value, $Res Function(MemoCell) _then) = _$MemoCellCopyWithImpl; + factory $MemoCellCopyWith(MemoCell value, $Res Function(MemoCell) _then) = + _$MemoCellCopyWithImpl; @useResult $Res call({String cellType, String value}); } @@ -244,14 +247,16 @@ class _MemoCell implements MemoCell { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoCellCopyWith<_MemoCell> get copyWith => __$MemoCellCopyWithImpl<_MemoCell>(this, _$identity); + _$MemoCellCopyWith<_MemoCell> get copyWith => + __$MemoCellCopyWithImpl<_MemoCell>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _MemoCell && - (identical(other.cellType, cellType) || other.cellType == cellType) && + (identical(other.cellType, cellType) || + other.cellType == cellType) && (identical(other.value, value) || other.value == value)); } @@ -265,8 +270,10 @@ class _MemoCell implements MemoCell { } /// @nodoc -abstract mixin class _$MemoCellCopyWith<$Res> implements $MemoCellCopyWith<$Res> { - factory _$MemoCellCopyWith(_MemoCell value, $Res Function(_MemoCell) _then) = __$MemoCellCopyWithImpl; +abstract mixin class _$MemoCellCopyWith<$Res> + implements $MemoCellCopyWith<$Res> { + factory _$MemoCellCopyWith(_MemoCell value, $Res Function(_MemoCell) _then) = + __$MemoCellCopyWithImpl; @override @useResult $Res call({String cellType, String value}); @@ -308,15 +315,20 @@ mixin _$MemoRow { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoRowCopyWith get copyWith => _$MemoRowCopyWithImpl(this as MemoRow, _$identity); + $MemoRowCopyWith get copyWith => + _$MemoRowCopyWithImpl(this as MemoRow, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is MemoRow && const DeepCollectionEquality().equals(other.cells, cells)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is MemoRow && + const DeepCollectionEquality().equals(other.cells, cells)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(cells)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(cells)); @override String toString() { @@ -326,7 +338,8 @@ mixin _$MemoRow { /// @nodoc abstract mixin class $MemoRowCopyWith<$Res> { - factory $MemoRowCopyWith(MemoRow value, $Res Function(MemoRow) _then) = _$MemoRowCopyWithImpl; + factory $MemoRowCopyWith(MemoRow value, $Res Function(MemoRow) _then) = + _$MemoRowCopyWithImpl; @useResult $Res call({List cells}); } @@ -525,15 +538,20 @@ class _MemoRow implements MemoRow { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoRowCopyWith<_MemoRow> get copyWith => __$MemoRowCopyWithImpl<_MemoRow>(this, _$identity); + _$MemoRowCopyWith<_MemoRow> get copyWith => + __$MemoRowCopyWithImpl<_MemoRow>(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is _MemoRow && const DeepCollectionEquality().equals(other._cells, _cells)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _MemoRow && + const DeepCollectionEquality().equals(other._cells, _cells)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_cells)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_cells)); @override String toString() { @@ -543,7 +561,8 @@ class _MemoRow implements MemoRow { /// @nodoc abstract mixin class _$MemoRowCopyWith<$Res> implements $MemoRowCopyWith<$Res> { - factory _$MemoRowCopyWith(_MemoRow value, $Res Function(_MemoRow) _then) = __$MemoRowCopyWithImpl; + factory _$MemoRowCopyWith(_MemoRow value, $Res Function(_MemoRow) _then) = + __$MemoRowCopyWithImpl; @override @useResult $Res call({List cells}); @@ -582,7 +601,8 @@ mixin _$MemoSection { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MemoSectionCopyWith get copyWith => _$MemoSectionCopyWithImpl(this as MemoSection, _$identity); + $MemoSectionCopyWith get copyWith => + _$MemoSectionCopyWithImpl(this as MemoSection, _$identity); @override bool operator ==(Object other) { @@ -595,7 +615,11 @@ mixin _$MemoSection { } @override - int get hashCode => Object.hash(runtimeType, title, const DeepCollectionEquality().hash(headers), const DeepCollectionEquality().hash(rows)); + int get hashCode => Object.hash( + runtimeType, + title, + const DeepCollectionEquality().hash(headers), + const DeepCollectionEquality().hash(rows)); @override String toString() { @@ -605,7 +629,9 @@ mixin _$MemoSection { /// @nodoc abstract mixin class $MemoSectionCopyWith<$Res> { - factory $MemoSectionCopyWith(MemoSection value, $Res Function(MemoSection) _then) = _$MemoSectionCopyWithImpl; + factory $MemoSectionCopyWith( + MemoSection value, $Res Function(MemoSection) _then) = + _$MemoSectionCopyWithImpl; @useResult $Res call({String title, List headers, List rows}); } @@ -734,7 +760,8 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult maybeWhen( - TResult Function(String title, List headers, List rows)? $default, { + TResult Function(String title, List headers, List rows)? + $default, { required TResult orElse(), }) { final _that = this; @@ -761,7 +788,8 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult when( - TResult Function(String title, List headers, List rows) $default, + TResult Function(String title, List headers, List rows) + $default, ) { final _that = this; switch (_that) { @@ -784,7 +812,8 @@ extension MemoSectionPatterns on MemoSection { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String title, List headers, List rows)? $default, + TResult? Function(String title, List headers, List rows)? + $default, ) { final _that = this; switch (_that) { @@ -799,7 +828,10 @@ extension MemoSectionPatterns on MemoSection { /// @nodoc class _MemoSection implements MemoSection { - const _MemoSection({required this.title, required final List headers, required final List rows}) + const _MemoSection( + {required this.title, + required final List headers, + required final List rows}) : _headers = headers, _rows = rows; @@ -826,7 +858,8 @@ class _MemoSection implements MemoSection { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MemoSectionCopyWith<_MemoSection> get copyWith => __$MemoSectionCopyWithImpl<_MemoSection>(this, _$identity); + _$MemoSectionCopyWith<_MemoSection> get copyWith => + __$MemoSectionCopyWithImpl<_MemoSection>(this, _$identity); @override bool operator ==(Object other) { @@ -839,7 +872,11 @@ class _MemoSection implements MemoSection { } @override - int get hashCode => Object.hash(runtimeType, title, const DeepCollectionEquality().hash(_headers), const DeepCollectionEquality().hash(_rows)); + int get hashCode => Object.hash( + runtimeType, + title, + const DeepCollectionEquality().hash(_headers), + const DeepCollectionEquality().hash(_rows)); @override String toString() { @@ -848,8 +885,11 @@ class _MemoSection implements MemoSection { } /// @nodoc -abstract mixin class _$MemoSectionCopyWith<$Res> implements $MemoSectionCopyWith<$Res> { - factory _$MemoSectionCopyWith(_MemoSection value, $Res Function(_MemoSection) _then) = __$MemoSectionCopyWithImpl; +abstract mixin class _$MemoSectionCopyWith<$Res> + implements $MemoSectionCopyWith<$Res> { + factory _$MemoSectionCopyWith( + _MemoSection value, $Res Function(_MemoSection) _then) = + __$MemoSectionCopyWithImpl; @override @useResult $Res call({String title, List headers, List rows}); @@ -903,7 +943,8 @@ mixin _$PluginInfo { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $PluginInfoCopyWith get copyWith => _$PluginInfoCopyWithImpl(this as PluginInfo, _$identity); + $PluginInfoCopyWith get copyWith => + _$PluginInfoCopyWithImpl(this as PluginInfo, _$identity); @override bool operator ==(Object other) { @@ -914,14 +955,24 @@ mixin _$PluginInfo { (identical(other.name, name) || other.name == name) && (identical(other.version, version) || other.version == version) && (identical(other.author, author) || other.author == author) && - (identical(other.description, description) || other.description == description) && + (identical(other.description, description) || + other.description == description) && (identical(other.enabled, enabled) || other.enabled == enabled) && const DeepCollectionEquality().equals(other.types, types) && - const DeepCollectionEquality().equals(other.memoPrefixes, memoPrefixes)); + const DeepCollectionEquality() + .equals(other.memoPrefixes, memoPrefixes)); } @override - int get hashCode => Object.hash(runtimeType, id, name, version, author, description, enabled, const DeepCollectionEquality().hash(types), + int get hashCode => Object.hash( + runtimeType, + id, + name, + version, + author, + description, + enabled, + const DeepCollectionEquality().hash(types), const DeepCollectionEquality().hash(memoPrefixes)); @override @@ -932,9 +983,19 @@ mixin _$PluginInfo { /// @nodoc abstract mixin class $PluginInfoCopyWith<$Res> { - factory $PluginInfoCopyWith(PluginInfo value, $Res Function(PluginInfo) _then) = _$PluginInfoCopyWithImpl; + factory $PluginInfoCopyWith( + PluginInfo value, $Res Function(PluginInfo) _then) = + _$PluginInfoCopyWithImpl; @useResult - $Res call({String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes}); + $Res call( + {String id, + String name, + String version, + String? author, + String? description, + bool enabled, + List types, + List memoPrefixes}); } /// @nodoc @@ -1086,14 +1147,23 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult maybeWhen( - TResult Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes)? + TResult Function( + String id, + String name, + String version, + String? author, + String? description, + bool enabled, + List types, + List memoPrefixes)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _PluginInfo() when $default != null: - return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, + _that.description, _that.enabled, _that.types, _that.memoPrefixes); case _: return orElse(); } @@ -1114,13 +1184,22 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult when( - TResult Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes) + TResult Function( + String id, + String name, + String version, + String? author, + String? description, + bool enabled, + List types, + List memoPrefixes) $default, ) { final _that = this; switch (_that) { case _PluginInfo(): - return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, + _that.description, _that.enabled, _that.types, _that.memoPrefixes); } } @@ -1138,13 +1217,22 @@ extension PluginInfoPatterns on PluginInfo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes)? + TResult? Function( + String id, + String name, + String version, + String? author, + String? description, + bool enabled, + List types, + List memoPrefixes)? $default, ) { final _that = this; switch (_that) { case _PluginInfo() when $default != null: - return $default(_that.id, _that.name, _that.version, _that.author, _that.description, _that.enabled, _that.types, _that.memoPrefixes); + return $default(_that.id, _that.name, _that.version, _that.author, + _that.description, _that.enabled, _that.types, _that.memoPrefixes); case _: return null; } @@ -1199,7 +1287,8 @@ class _PluginInfo implements PluginInfo { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$PluginInfoCopyWith<_PluginInfo> get copyWith => __$PluginInfoCopyWithImpl<_PluginInfo>(this, _$identity); + _$PluginInfoCopyWith<_PluginInfo> get copyWith => + __$PluginInfoCopyWithImpl<_PluginInfo>(this, _$identity); @override bool operator ==(Object other) { @@ -1210,14 +1299,24 @@ class _PluginInfo implements PluginInfo { (identical(other.name, name) || other.name == name) && (identical(other.version, version) || other.version == version) && (identical(other.author, author) || other.author == author) && - (identical(other.description, description) || other.description == description) && + (identical(other.description, description) || + other.description == description) && (identical(other.enabled, enabled) || other.enabled == enabled) && const DeepCollectionEquality().equals(other._types, _types) && - const DeepCollectionEquality().equals(other._memoPrefixes, _memoPrefixes)); + const DeepCollectionEquality() + .equals(other._memoPrefixes, _memoPrefixes)); } @override - int get hashCode => Object.hash(runtimeType, id, name, version, author, description, enabled, const DeepCollectionEquality().hash(_types), + int get hashCode => Object.hash( + runtimeType, + id, + name, + version, + author, + description, + enabled, + const DeepCollectionEquality().hash(_types), const DeepCollectionEquality().hash(_memoPrefixes)); @override @@ -1227,11 +1326,22 @@ class _PluginInfo implements PluginInfo { } /// @nodoc -abstract mixin class _$PluginInfoCopyWith<$Res> implements $PluginInfoCopyWith<$Res> { - factory _$PluginInfoCopyWith(_PluginInfo value, $Res Function(_PluginInfo) _then) = __$PluginInfoCopyWithImpl; +abstract mixin class _$PluginInfoCopyWith<$Res> + implements $PluginInfoCopyWith<$Res> { + factory _$PluginInfoCopyWith( + _PluginInfo value, $Res Function(_PluginInfo) _then) = + __$PluginInfoCopyWithImpl; @override @useResult - $Res call({String id, String name, String version, String? author, String? description, bool enabled, List types, List memoPrefixes}); + $Res call( + {String id, + String name, + String version, + String? author, + String? description, + bool enabled, + List types, + List memoPrefixes}); } /// @nodoc diff --git a/lib/src/rust/api/raptor.dart b/lib/src/rust/api/raptor.dart index 3b63c3c07..584e6f953 100644 --- a/lib/src/rust/api/raptor.dart +++ b/lib/src/rust/api/raptor.dart @@ -8,11 +8,15 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `ec_level_of` -Future> encode({required String path, required RaptorQParams params}) => RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); +Future> encode( + {required String path, required RaptorQParams params}) => + RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); -Uint8List getQrBytes({required List data}) => RustLib.instance.api.crateApiRaptorGetQrBytes(data: data); +Uint8List getQrBytes({required List data}) => + RustLib.instance.api.crateApiRaptorGetQrBytes(data: data); -Future decode({required List packet}) => RustLib.instance.api.crateApiRaptorDecode(packet: packet); +Future decode({required List packet}) => + RustLib.instance.api.crateApiRaptorDecode(packet: packet); Future endDecode() => RustLib.instance.api.crateApiRaptorEndDecode(); @@ -33,5 +37,9 @@ class RaptorQParams { @override bool operator ==(Object other) => identical(this, other) || - other is RaptorQParams && runtimeType == other.runtimeType && version == other.version && ecLevel == other.ecLevel && repair == other.repair; + other is RaptorQParams && + runtimeType == other.runtimeType && + version == other.version && + ecLevel == other.ecLevel && + repair == other.repair; } diff --git a/lib/src/rust/api/sapling.dart b/lib/src/rust/api/sapling.dart index 9a154871b..dfc524efd 100644 --- a/lib/src/rust/api/sapling.dart +++ b/lib/src/rust/api/sapling.dart @@ -9,13 +9,15 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `download_and_verify`, `resolve_params_dir`, `set_sapling_params_dir` /// Check whether Sapling parameters are already on disk. -SaplingParamsStatus checkSaplingParams() => RustLib.instance.api.crateApiSaplingCheckSaplingParams(); +SaplingParamsStatus checkSaplingParams() => + RustLib.instance.api.crateApiSaplingCheckSaplingParams(); /// Download Sapling parameters from the z.cash download server. /// /// Verifies file size and Blake2b hash upon download. /// Safe to call even if they are already downloaded (no-op if valid). -Future downloadSaplingParams() => RustLib.instance.api.crateApiSaplingDownloadSaplingParams(); +Future downloadSaplingParams() => + RustLib.instance.api.crateApiSaplingDownloadSaplingParams(); /// Status of the Sapling proving parameters on disk. class SaplingParamsStatus { @@ -30,5 +32,8 @@ class SaplingParamsStatus { @override bool operator ==(Object other) => - identical(this, other) || other is SaplingParamsStatus && runtimeType == other.runtimeType && downloaded == other.downloaded; + identical(this, other) || + other is SaplingParamsStatus && + runtimeType == other.runtimeType && + downloaded == other.downloaded; } diff --git a/lib/src/rust/api/sweep.dart b/lib/src/rust/api/sweep.dart index 19c7ce2aa..3b11052b8 100644 --- a/lib/src/rust/api/sweep.dart +++ b/lib/src/rust/api/sweep.dart @@ -12,7 +12,9 @@ abstract class TransparentScanner implements RustOpaqueInterface { Future cancel(); // HINT: Make it `#[frb(sync)]` to let it become the default constructor of Dart class. - static Future newInstance() => RustLib.instance.api.crateApiSweepTransparentScannerNew(); + static Future newInstance() => + RustLib.instance.api.crateApiSweepTransparentScannerNew(); - Stream run({required int endHeight, required int gapLimit, required Coin c}); + Stream run( + {required int endHeight, required int gapLimit, required Coin c}); } diff --git a/lib/src/rust/api/sync.dart b/lib/src/rust/api/sync.dart index d9c1cf6db..2e19f76a8 100644 --- a/lib/src/rust/api/sync.dart +++ b/lib/src/rust/api/sync.dart @@ -27,18 +27,24 @@ Stream synchronize( fast: fast, c: c); -Future balance({required Coin c}) => RustLib.instance.api.crateApiSyncBalance(c: c); +Future balance({required Coin c}) => + RustLib.instance.api.crateApiSyncBalance(c: c); Future cancelSync() => RustLib.instance.api.crateApiSyncCancelSync(); -Future rewindSync({required int height, required int account, required Coin c}) => - RustLib.instance.api.crateApiSyncRewindSync(height: height, account: account, c: c); +Future rewindSync( + {required int height, required int account, required Coin c}) => + RustLib.instance.api + .crateApiSyncRewindSync(height: height, account: account, c: c); -Future getDbHeight({required Coin c}) => RustLib.instance.api.crateApiSyncGetDbHeight(c: c); +Future getDbHeight({required Coin c}) => + RustLib.instance.api.crateApiSyncGetDbHeight(c: c); -Future fetchTxDetails({required int account, required Coin c}) => RustLib.instance.api.crateApiSyncFetchTxDetails(account: account, c: c); +Future fetchTxDetails({required int account, required Coin c}) => + RustLib.instance.api.crateApiSyncFetchTxDetails(account: account, c: c); -Future cacheBlockTime({required int height, required Coin c}) => RustLib.instance.api.crateApiSyncCacheBlockTime(height: height, c: c); +Future cacheBlockTime({required int height, required Coin c}) => + RustLib.instance.api.crateApiSyncCacheBlockTime(height: height, c: c); class PoolBalance { final Uint64List field0; @@ -51,7 +57,11 @@ class PoolBalance { int get hashCode => field0.hashCode; @override - bool operator ==(Object other) => identical(this, other) || other is PoolBalance && runtimeType == other.runtimeType && field0 == other.field0; + bool operator ==(Object other) => + identical(this, other) || + other is PoolBalance && + runtimeType == other.runtimeType && + field0 == other.field0; } class SyncProgress { @@ -68,5 +78,9 @@ class SyncProgress { @override bool operator ==(Object other) => - identical(this, other) || other is SyncProgress && runtimeType == other.runtimeType && height == other.height && time == other.time; + identical(this, other) || + other is SyncProgress && + runtimeType == other.runtimeType && + height == other.height && + time == other.time; } diff --git a/lib/src/rust/api/transaction.dart b/lib/src/rust/api/transaction.dart index 2281ceff3..a3eb4e2ce 100644 --- a/lib/src/rust/api/transaction.dart +++ b/lib/src/rust/api/transaction.dart @@ -7,22 +7,36 @@ import '../frb_generated.dart'; import 'coin.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -Future fillMissingTxPrices({required String api, required String currency, required Coin c}) => - RustLib.instance.api.crateApiTransactionFillMissingTxPrices(api: api, currency: currency, c: c); - -Future updateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}) => - RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices(currency: currency, exchangeRate: exchangeRate, c: c); +Future fillMissingTxPrices( + {required String api, required String currency, required Coin c}) => + RustLib.instance.api.crateApiTransactionFillMissingTxPrices( + api: api, currency: currency, c: c); + +Future updateHistoricalPrices( + {required String currency, + required double exchangeRate, + required Coin c}) => + RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices( + currency: currency, exchangeRate: exchangeRate, c: c); Future setUserMemo({required int idTx, String? memo, required Coin c}) => - RustLib.instance.api.crateApiTransactionSetUserMemo(idTx: idTx, memo: memo, c: c); + RustLib.instance.api + .crateApiTransactionSetUserMemo(idTx: idTx, memo: memo, c: c); Future setTxCategory({required int id, int? category, required Coin c}) => - RustLib.instance.api.crateApiTransactionSetTxCategory(id: id, category: category, c: c); - -Future setTxPrice({required int id, double? price, required Coin c}) => RustLib.instance.api.crateApiTransactionSetTxPrice(id: id, price: price, c: c); - -Future> fetchCategoryAmounts({int? from, int? to, required Coin c}) => - RustLib.instance.api.crateApiTransactionFetchCategoryAmounts(from: from, to: to, c: c); - -Future> fetchAmounts({int? from, int? to, required int category, required Coin c}) => - RustLib.instance.api.crateApiTransactionFetchAmounts(from: from, to: to, category: category, c: c); + RustLib.instance.api + .crateApiTransactionSetTxCategory(id: id, category: category, c: c); + +Future setTxPrice({required int id, double? price, required Coin c}) => + RustLib.instance.api + .crateApiTransactionSetTxPrice(id: id, price: price, c: c); + +Future> fetchCategoryAmounts( + {int? from, int? to, required Coin c}) => + RustLib.instance.api + .crateApiTransactionFetchCategoryAmounts(from: from, to: to, c: c); + +Future> fetchAmounts( + {int? from, int? to, required int category, required Coin c}) => + RustLib.instance.api.crateApiTransactionFetchAmounts( + from: from, to: to, category: category, c: c); diff --git a/lib/src/rust/api/vault.dart b/lib/src/rust/api/vault.dart index 4dbc93860..749ed9dab 100644 --- a/lib/src/rust/api/vault.dart +++ b/lib/src/rust/api/vault.dart @@ -8,17 +8,28 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` -Future initVault({required FutureOr Function(Uint8List) append}) => RustLib.instance.api.crateApiVaultInitVault(append: append); +Future initVault( + {required FutureOr Function(Uint8List) append}) => + RustLib.instance.api.crateApiVaultInitVault(append: append); // Rust type: RustOpaqueMoi> abstract class DartVault implements RustOpaqueInterface { - Future> recover({required List vaultBytes, required String masterPassword}); + Future> recover( + {required List vaultBytes, required String masterPassword}); - Future> recoverWithPrf({required List vaultBytes, required String deviceIdStr, required List prfOutput}); + Future> recoverWithPrf( + {required List vaultBytes, + required String deviceIdStr, + required List prfOutput}); - Future registerDevice({required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}); + Future registerDevice( + {required List initBytes, + required String masterPassword, + required String deviceIdStr, + required List prfOutput}); - Future setMasterPassword({String? oldPassword, required String newPassword, Uint8List? oldBytes}); + Future setMasterPassword( + {String? oldPassword, required String newPassword, Uint8List? oldBytes}); Future storeAccount( {required int timestamp, @@ -50,7 +61,13 @@ class RestoredAccount { }); @override - int get hashCode => timestamp.hashCode ^ name.hashCode ^ seed.hashCode ^ aindex.hashCode ^ useInternal.hashCode ^ birthHeight.hashCode; + int get hashCode => + timestamp.hashCode ^ + name.hashCode ^ + seed.hashCode ^ + aindex.hashCode ^ + useInternal.hashCode ^ + birthHeight.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/api/zsa.dart b/lib/src/rust/api/zsa.dart index fd7aaa061..a8ade42f8 100644 --- a/lib/src/rust/api/zsa.dart +++ b/lib/src/rust/api/zsa.dart @@ -11,17 +11,23 @@ part 'zsa.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt`, `from` -Future> listZsaHoldings({required Coin c}) => RustLib.instance.api.crateApiZsaListZsaHoldings(c: c); +Future> listZsaHoldings({required Coin c}) => + RustLib.instance.api.crateApiZsaListZsaHoldings(c: c); /// Set or update the human-readable name for a ZSA asset. /// Pass an empty string to clear the name (reverting to the hex fallback display). -Future setAssetName({required PlatformInt64 idAsset, required String name, required Coin c}) => - RustLib.instance.api.crateApiZsaSetAssetName(idAsset: idAsset, name: name, c: c); +Future setAssetName( + {required PlatformInt64 idAsset, + required String name, + required Coin c}) => + RustLib.instance.api + .crateApiZsaSetAssetName(idAsset: idAsset, name: name, c: c); /// Check whether ZSA (Zcash Shielded Assets) is available on the current network. /// /// ZSA is enabled when the network's [`OrchardMode`] is set to [`OrchardMode::Zsa`]. -Future isZsaAvailable({required Coin c}) => RustLib.instance.api.crateApiZsaIsZsaAvailable(c: c); +Future isZsaAvailable({required Coin c}) => + RustLib.instance.api.crateApiZsaIsZsaAvailable(c: c); /// A ZSA token holding representing a balance of a specific asset. @freezed diff --git a/lib/src/rust/api/zsa.freezed.dart b/lib/src/rust/api/zsa.freezed.dart index ce3e0f66d..921cf9e94 100644 --- a/lib/src/rust/api/zsa.freezed.dart +++ b/lib/src/rust/api/zsa.freezed.dart @@ -27,7 +27,8 @@ mixin _$ZsaHolding { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $ZsaHoldingCopyWith get copyWith => _$ZsaHoldingCopyWithImpl(this as ZsaHolding, _$identity); + $ZsaHoldingCopyWith get copyWith => + _$ZsaHoldingCopyWithImpl(this as ZsaHolding, _$identity); @override bool operator ==(Object other) { @@ -35,18 +36,30 @@ mixin _$ZsaHolding { (other.runtimeType == runtimeType && other is ZsaHolding && (identical(other.idAsset, idAsset) || other.idAsset == idAsset) && - const DeepCollectionEquality().equals(other.assetDescHash, assetDescHash) && - (identical(other.assetName, assetName) || other.assetName == assetName) && + const DeepCollectionEquality() + .equals(other.assetDescHash, assetDescHash) && + (identical(other.assetName, assetName) || + other.assetName == assetName) && const DeepCollectionEquality().equals(other.ik, ik) && const DeepCollectionEquality().equals(other.assetBase, assetBase) && - (identical(other.finalized, finalized) || other.finalized == finalized) && - (identical(other.firstSeenHeight, firstSeenHeight) || other.firstSeenHeight == firstSeenHeight) && + (identical(other.finalized, finalized) || + other.finalized == finalized) && + (identical(other.firstSeenHeight, firstSeenHeight) || + other.firstSeenHeight == firstSeenHeight) && (identical(other.balance, balance) || other.balance == balance)); } @override - int get hashCode => Object.hash(runtimeType, idAsset, const DeepCollectionEquality().hash(assetDescHash), assetName, const DeepCollectionEquality().hash(ik), - const DeepCollectionEquality().hash(assetBase), finalized, firstSeenHeight, balance); + int get hashCode => Object.hash( + runtimeType, + idAsset, + const DeepCollectionEquality().hash(assetDescHash), + assetName, + const DeepCollectionEquality().hash(ik), + const DeepCollectionEquality().hash(assetBase), + finalized, + firstSeenHeight, + balance); @override String toString() { @@ -56,7 +69,9 @@ mixin _$ZsaHolding { /// @nodoc abstract mixin class $ZsaHoldingCopyWith<$Res> { - factory $ZsaHoldingCopyWith(ZsaHolding value, $Res Function(ZsaHolding) _then) = _$ZsaHoldingCopyWithImpl; + factory $ZsaHoldingCopyWith( + ZsaHolding value, $Res Function(ZsaHolding) _then) = + _$ZsaHoldingCopyWithImpl; @useResult $Res call( {PlatformInt64 idAsset, @@ -218,7 +233,14 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult maybeWhen( - TResult Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, + TResult Function( + PlatformInt64 idAsset, + Uint8List assetDescHash, + String assetName, + Uint8List ik, + Uint8List assetBase, + bool finalized, + int firstSeenHeight, BigInt balance)? $default, { required TResult orElse(), @@ -226,7 +248,15 @@ extension ZsaHoldingPatterns on ZsaHolding { final _that = this; switch (_that) { case _ZsaHolding() when $default != null: - return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); + return $default( + _that.idAsset, + _that.assetDescHash, + _that.assetName, + _that.ik, + _that.assetBase, + _that.finalized, + _that.firstSeenHeight, + _that.balance); case _: return orElse(); } @@ -247,14 +277,29 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult when( - TResult Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, + TResult Function( + PlatformInt64 idAsset, + Uint8List assetDescHash, + String assetName, + Uint8List ik, + Uint8List assetBase, + bool finalized, + int firstSeenHeight, BigInt balance) $default, ) { final _that = this; switch (_that) { case _ZsaHolding(): - return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); + return $default( + _that.idAsset, + _that.assetDescHash, + _that.assetName, + _that.ik, + _that.assetBase, + _that.finalized, + _that.firstSeenHeight, + _that.balance); } } @@ -272,14 +317,29 @@ extension ZsaHoldingPatterns on ZsaHolding { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(PlatformInt64 idAsset, Uint8List assetDescHash, String assetName, Uint8List ik, Uint8List assetBase, bool finalized, int firstSeenHeight, + TResult? Function( + PlatformInt64 idAsset, + Uint8List assetDescHash, + String assetName, + Uint8List ik, + Uint8List assetBase, + bool finalized, + int firstSeenHeight, BigInt balance)? $default, ) { final _that = this; switch (_that) { case _ZsaHolding() when $default != null: - return $default(_that.idAsset, _that.assetDescHash, _that.assetName, _that.ik, _that.assetBase, _that.finalized, _that.firstSeenHeight, _that.balance); + return $default( + _that.idAsset, + _that.assetDescHash, + _that.assetName, + _that.ik, + _that.assetBase, + _that.finalized, + _that.firstSeenHeight, + _that.balance); case _: return null; } @@ -321,7 +381,8 @@ class _ZsaHolding implements ZsaHolding { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$ZsaHoldingCopyWith<_ZsaHolding> get copyWith => __$ZsaHoldingCopyWithImpl<_ZsaHolding>(this, _$identity); + _$ZsaHoldingCopyWith<_ZsaHolding> get copyWith => + __$ZsaHoldingCopyWithImpl<_ZsaHolding>(this, _$identity); @override bool operator ==(Object other) { @@ -329,18 +390,30 @@ class _ZsaHolding implements ZsaHolding { (other.runtimeType == runtimeType && other is _ZsaHolding && (identical(other.idAsset, idAsset) || other.idAsset == idAsset) && - const DeepCollectionEquality().equals(other.assetDescHash, assetDescHash) && - (identical(other.assetName, assetName) || other.assetName == assetName) && + const DeepCollectionEquality() + .equals(other.assetDescHash, assetDescHash) && + (identical(other.assetName, assetName) || + other.assetName == assetName) && const DeepCollectionEquality().equals(other.ik, ik) && const DeepCollectionEquality().equals(other.assetBase, assetBase) && - (identical(other.finalized, finalized) || other.finalized == finalized) && - (identical(other.firstSeenHeight, firstSeenHeight) || other.firstSeenHeight == firstSeenHeight) && + (identical(other.finalized, finalized) || + other.finalized == finalized) && + (identical(other.firstSeenHeight, firstSeenHeight) || + other.firstSeenHeight == firstSeenHeight) && (identical(other.balance, balance) || other.balance == balance)); } @override - int get hashCode => Object.hash(runtimeType, idAsset, const DeepCollectionEquality().hash(assetDescHash), assetName, const DeepCollectionEquality().hash(ik), - const DeepCollectionEquality().hash(assetBase), finalized, firstSeenHeight, balance); + int get hashCode => Object.hash( + runtimeType, + idAsset, + const DeepCollectionEquality().hash(assetDescHash), + assetName, + const DeepCollectionEquality().hash(ik), + const DeepCollectionEquality().hash(assetBase), + finalized, + firstSeenHeight, + balance); @override String toString() { @@ -349,8 +422,11 @@ class _ZsaHolding implements ZsaHolding { } /// @nodoc -abstract mixin class _$ZsaHoldingCopyWith<$Res> implements $ZsaHoldingCopyWith<$Res> { - factory _$ZsaHoldingCopyWith(_ZsaHolding value, $Res Function(_ZsaHolding) _then) = __$ZsaHoldingCopyWithImpl; +abstract mixin class _$ZsaHoldingCopyWith<$Res> + implements $ZsaHoldingCopyWith<$Res> { + factory _$ZsaHoldingCopyWith( + _ZsaHolding value, $Res Function(_ZsaHolding) _then) = + __$ZsaHoldingCopyWithImpl; @override @useResult $Res call( diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 7cc428d55..c2c201e83 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -27,7 +27,8 @@ import 'api/zsa.dart'; import 'dart:async'; import 'dart:convert'; import 'frb_generated.dart'; -import 'frb_generated.io.dart' if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'frb_generated.io.dart' + if (dart.library.js_interop) 'frb_generated.web.dart'; import 'io.dart'; import 'lib.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; @@ -72,10 +73,12 @@ class RustLib extends BaseEntrypoint { static void dispose() => instance.disposeImpl(); @override - ApiImplConstructor get apiImplConstructor => RustLibApiImpl.new; + ApiImplConstructor get apiImplConstructor => + RustLibApiImpl.new; @override - WireConstructor get wireConstructor => RustLibWire.fromExternalLibrary; + WireConstructor get wireConstructor => + RustLibWire.fromExternalLibrary; @override Future executeRustInitializers() async { @@ -84,7 +87,8 @@ class RustLib extends BaseEntrypoint { } @override - ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => kDefaultExternalLibraryLoaderConfig; + ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => + kDefaultExternalLibraryLoaderConfig; @override String get codegenVersion => '2.12.0'; @@ -92,7 +96,8 @@ class RustLib extends BaseEntrypoint { @override int get rustContentHash => 151776773; - static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( + static const kDefaultExternalLibraryLoaderConfig = + ExternalLibraryLoaderConfig( stem: 'rlz', ioDirectory: 'rust/target/release/', webPrefix: 'pkg/', @@ -101,15 +106,29 @@ class RustLib extends BaseEntrypoint { } abstract class RustLibApi extends BaseApi { - Future> crateApiVaultDartVaultRecover({required DartVault that, required List vaultBytes, required String masterPassword}); + Future> crateApiVaultDartVaultRecover( + {required DartVault that, + required List vaultBytes, + required String masterPassword}); Future> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, required List vaultBytes, required String deviceIdStr, required List prfOutput}); + {required DartVault that, + required List vaultBytes, + required String deviceIdStr, + required List prfOutput}); Future crateApiVaultDartVaultRegisterDevice( - {required DartVault that, required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}); + {required DartVault that, + required List initBytes, + required String masterPassword, + required String deviceIdStr, + required List prfOutput}); - Future crateApiVaultDartVaultSetMasterPassword({required DartVault that, String? oldPassword, required String newPassword, Uint8List? oldBytes}); + Future crateApiVaultDartVaultSetMasterPassword( + {required DartVault that, + String? oldPassword, + required String newPassword, + Uint8List? oldBytes}); Future crateApiVaultDartVaultStoreAccount( {required DartVault that, @@ -127,35 +146,52 @@ abstract class RustLibApi extends BaseApi { Mempool crateApiMempoolMempoolNew(); - Stream crateApiMempoolMempoolRun({required Mempool that, required Coin c}); + Stream crateApiMempoolMempoolRun( + {required Mempool that, required Coin c}); - Future crateApiMigrateNoteMigrationCancel({required NoteMigration that}); + Future crateApiMigrateNoteMigrationCancel( + {required NoteMigration that}); NoteMigration crateApiMigrateNoteMigrationNew(); - Stream crateApiMigrateNoteMigrationRun({required NoteMigration that, required Coin c, required BigInt meanDelayMs}); + Stream crateApiMigrateNoteMigrationRun( + {required NoteMigration that, + required Coin c, + required BigInt meanDelayMs}); - void crateApiMigrateNoteMigrationUpdateHeight({required NoteMigration that, required int height}); + void crateApiMigrateNoteMigrationUpdateHeight( + {required NoteMigration that, required int height}); - Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}); + Future crateApiSweepTransparentScannerCancel( + {required TransparentScanner that}); Future crateApiSweepTransparentScannerNew(); - Stream crateApiSweepTransparentScannerRun({required TransparentScanner that, required int endHeight, required int gapLimit, required Coin c}); + Stream crateApiSweepTransparentScannerRun( + {required TransparentScanner that, + required int endHeight, + required int gapLimit, + required Coin c}); Future crateApiSyncBalance({required Coin c}); - Future crateApiPayBroadcastTransaction({required int height, required List txBytes, required Coin c}); + Future crateApiPayBroadcastTransaction( + {required int height, required List txBytes, required Coin c}); Future crateApiPayBuildPuri({required List recipients}); - Future crateApiSyncCacheBlockTime({required int height, required Coin c}); + Future crateApiSyncCacheBlockTime( + {required int height, required Coin c}); Future crateApiFrostCancelDkg({required Coin c}); Future crateApiSyncCancelSync(); - Future crateApiDbChangeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}); + Future crateApiDbChangeDbPassword( + {required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword}); SaplingParamsStatus crateApiSaplingCheckSaplingParams(); @@ -165,31 +201,45 @@ abstract class RustLibApi extends BaseApi { Coin crateApiCoinCoinNew({int? defaultCoin}); - Future crateApiCoinCoinOpenDatabase({required Coin that, required String dbFilepath, String? password}); + Future crateApiCoinCoinOpenDatabase( + {required Coin that, required String dbFilepath, String? password}); - Future crateApiCoinCoinSetAccount({required Coin that, required int account}); + Future crateApiCoinCoinSetAccount( + {required Coin that, required int account}); - Coin crateApiCoinCoinSetLwd({required Coin that, required int serverType, required String url}); + Coin crateApiCoinCoinSetLwd( + {required Coin that, required int serverType, required String url}); Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}); - Future crateApiCoinCoinSetUseTor({required Coin that, required bool useTor}); + Future crateApiCoinCoinSetUseTor( + {required Coin that, required bool useTor}); - Future crateApiContactsCreateContact({required String name, required List addresses, required String notes, required Coin c}); + Future crateApiContactsCreateContact( + {required String name, + required List addresses, + required String notes, + required Coin c}); - Future crateApiAccountCreateNewCategory({required Category category, required Coin c}); + Future crateApiAccountCreateNewCategory( + {required Category category, required Coin c}); - Future crateApiAccountCreateNewFolder({required String name, required Coin c}); + Future crateApiAccountCreateNewFolder( + {required String name, required Coin c}); Future crateApiRaptorDecode({required List packet}); - Future crateApiAccountDeleteAccount({required int account, required Coin c}); + Future crateApiAccountDeleteAccount( + {required int account, required Coin c}); - Future crateApiAccountDeleteCategories({required List ids, required Coin c}); + Future crateApiAccountDeleteCategories( + {required List ids, required Coin c}); - Future crateApiContactsDeleteContacts({required List ids, required Coin c}); + Future crateApiContactsDeleteContacts( + {required List ids, required Coin c}); - Future crateApiAccountDeleteFolders({required List ids, required Coin c}); + Future crateApiAccountDeleteFolders( + {required List ids, required Coin c}); Stream crateApiFrostDoDkg({required Coin c}); @@ -199,29 +249,39 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountDummyExport({required SigningEvent a}); - Future> crateApiRaptorEncode({required String path, required RaptorQParams params}); + Future> crateApiRaptorEncode( + {required String path, required RaptorQParams params}); Future crateApiRaptorEndDecode(); - Future crateApiAccountExportAccount({required int id, required String passphrase, required Coin c}); + Future crateApiAccountExportAccount( + {required int id, required String passphrase, required Coin c}); Future crateApiContactsExportContactsVcard({required Coin c}); - Future crateApiPayExtractTransaction({required PcztPackage package}); + Future crateApiPayExtractTransaction( + {required PcztPackage package}); - Future> crateApiAccountFetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}); + Future> crateApiAccountFetchAddressTxCount( + {required Coin c, required bool aggregate, required int poolFilter}); - Future> crateApiTransactionFetchAmounts({int? from, int? to, required int category, required Coin c}); + Future> crateApiTransactionFetchAmounts( + {int? from, int? to, required int category, required Coin c}); - Future> crateApiTransactionFetchCategoryAmounts({int? from, int? to, required Coin c}); + Future> crateApiTransactionFetchCategoryAmounts( + {int? from, int? to, required Coin c}); - Future> crateApiAccountFetchTransparentAddressTxCount({required Coin c}); + Future> crateApiAccountFetchTransparentAddressTxCount( + {required Coin c}); - Future crateApiSyncFetchTxDetails({required int account, required Coin c}); + Future crateApiSyncFetchTxDetails( + {required int account, required Coin c}); - Future crateApiTransactionFillMissingTxPrices({required String api, required String currency, required Coin c}); + Future crateApiTransactionFillMissingTxPrices( + {required String api, required String currency, required Coin c}); - Future> crateApiContactsFindContactsForAddress({required String address, required Coin c}); + Future> crateApiContactsFindContactsForAddress( + {required String address, required Coin c}); Future crateApiFrostFrostSignParamsDefault(); @@ -231,21 +291,28 @@ abstract class RustLibApi extends BaseApi { String crateApiKeyGenerateSeed(); - Future crateApiAccountGetAccountAddresses({required int account, required int uaPools, required Coin c}); + Future crateApiAccountGetAccountAddresses( + {required int account, required int uaPools, required Coin c}); - Future crateApiAccountGetAccountFingerprint({required int account, required Coin c}); + Future crateApiAccountGetAccountFingerprint( + {required int account, required Coin c}); Future crateApiAccountGetAccountFrostParams({required Coin c}); - Future crateApiAccountGetAccountPools({required int account, required Coin c}); + Future crateApiAccountGetAccountPools( + {required int account, required Coin c}); - Future crateApiAccountGetAccountSeed({required int account, required Coin c}); + Future crateApiAccountGetAccountSeed( + {required int account, required Coin c}); - Future crateApiAccountGetAccountUfvk({required int account, required int pools, required Coin c}); + Future crateApiAccountGetAccountUfvk( + {required int account, required int pools, required Coin c}); - Future crateApiAccountGetAddresses({required int uaPools, required Coin c}); + Future crateApiAccountGetAddresses( + {required int uaPools, required Coin c}); - Future crateApiNetworkGetCoingeckoPrice({required String api, required String currency}); + Future crateApiNetworkGetCoingeckoPrice( + {required String api, required String currency}); Future crateApiNetworkGetCurrentHeight({required Coin c}); @@ -253,13 +320,18 @@ abstract class RustLibApi extends BaseApi { Future> crateApiFrostGetDkgAddresses({required Coin c}); - Future crateApiNetworkGetExchangeRate({required String api, required String fromCurrency, required String toCurrency}); + Future crateApiNetworkGetExchangeRate( + {required String api, + required String fromCurrency, + required String toCurrency}); - Future crateApiAccountGetExportedData({required int type, required Coin c}); + Future crateApiAccountGetExportedData( + {required int type, required Coin c}); int crateApiKeyGetKeyPools({required String key, required Coin c}); - Future crateApiMempoolGetMempoolTx({required String txId, required Coin c}); + Future crateApiMempoolGetMempoolTx( + {required String txId, required Coin c}); Future crateApiMigrateGetMigrationStatus({required Coin c}); @@ -269,11 +341,13 @@ abstract class RustLibApi extends BaseApi { Uint8List crateApiRaptorGetQrBytes({required List data}); - Future> crateApiNetworkGetSupportedVsCurrencies({required String api}); + Future> crateApiNetworkGetSupportedVsCurrencies( + {required String api}); Future crateApiCoinGetTorClient(); - Future crateApiAccountGetTxDetails({required int idTx, required Coin c}); + Future crateApiAccountGetTxDetails( + {required int idTx, required Coin c}); Future crateApiFrostHasDkgAddresses({required Coin c}); @@ -281,9 +355,11 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountHasTransparentPubKey({required Coin c}); - Future crateApiAccountImportAccount({required String passphrase, required List data, required Coin c}); + Future crateApiAccountImportAccount( + {required String passphrase, required List data, required Coin c}); - Future> crateApiContactsImportContactsVcard({required String vcardData, required Coin c}); + Future> crateApiContactsImportContactsVcard( + {required String vcardData, required Coin c}); Future crateApiInitInitApp(); @@ -297,11 +373,17 @@ abstract class RustLibApi extends BaseApi { void crateApiPluginInitPlugins(); - Future crateApiFrostInitSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}); + Future crateApiFrostInitSign( + {required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c}); - Future crateApiVaultInitVault({required FutureOr Function(Uint8List) append}); + Future crateApiVaultInitVault( + {required FutureOr Function(Uint8List) append}); - Future crateApiPluginInstallPlugin({required String url, required Coin c}); + Future crateApiPluginInstallPlugin( + {required String url, required Coin c}); Future crateApiNetworkIsIronwoodActive({required Coin c}); @@ -317,7 +399,8 @@ abstract class RustLibApi extends BaseApi { bool crateApiKeyIsValidPhrase({required String phrase}); - bool crateApiKeyIsValidTransparentAddress({required String address, required Coin c}); + bool crateApiKeyIsValidTransparentAddress( + {required String address, required Coin c}); Future crateApiZsaIsZsaAvailable({required Coin c}); @@ -336,7 +419,8 @@ abstract class RustLibApi extends BaseApi { Future> crateApiContactsListContacts({required Coin c}); - Future> crateApiDbListDbAccounts({required String dbFilepath}); + Future> crateApiDbListDbAccounts( + {required String dbFilepath}); Future> crateApiDbListDbNames({required String dir}); @@ -352,87 +436,128 @@ abstract class RustLibApi extends BaseApi { Future> crateApiZsaListZsaHoldings({required Coin c}); - Future crateApiAccountLockNote({required int id, required bool locked, required Coin c}); + Future crateApiAccountLockNote( + {required int id, required bool locked, required Coin c}); - Future crateApiAccountLockRecentNotes({required int height, required int threshold, required Coin c}); + Future crateApiAccountLockRecentNotes( + {required int height, required int threshold, required Coin c}); Future crateApiAccountMaxSpendable({required Coin c}); - Future crateApiAccountNewAccount({required NewAccount na, required Coin c}); + Future crateApiAccountNewAccount( + {required NewAccount na, required Coin c}); Future crateApiPayPackTransaction({required PcztPackage pczt}); - Future> crateApiPluginParseMemoWithPlugins({required List memoBytes, required Coin c}); + Future> crateApiPluginParseMemoWithPlugins( + {required List memoBytes, required Coin c}); List? crateApiPayParsePaymentUri({required String uri}); - Future crateApiPayPrepare({required List recipients, required PaymentOptions options, required Coin c}); + Future crateApiPayPrepare( + {required List recipients, + required PaymentOptions options, + required Coin c}); - Future crateApiPayPrepareMigration({required List recipients, required int srcPools, required Coin c}); + Future crateApiPayPrepareMigration( + {required List recipients, + required int srcPools, + required Coin c}); Future crateApiAccountPrintKeys({required int id, required Coin c}); - Future crateApiDbPutProp({required String key, required String value, required Coin c}); + Future crateApiDbPutProp( + {required String key, required String value, required Coin c}); Future> crateApiNetworkQueryLwdList({required int coin}); Future crateApiAccountReceiversDefault(); - Receivers crateApiAccountReceiversFromUa({required String ua, required Coin c}); + Receivers crateApiAccountReceiversFromUa( + {required String ua, required Coin c}); - Future crateApiAccountRemoveAccount({required int accountId, required Coin c}); + Future crateApiAccountRemoveAccount( + {required int accountId, required Coin c}); - Future crateApiPluginRemovePlugin({required String id, required Coin c}); + Future crateApiPluginRemovePlugin( + {required String id, required Coin c}); - Future crateApiAccountRenameCategory({required Category category, required Coin c}); + Future crateApiAccountRenameCategory( + {required Category category, required Coin c}); - Future crateApiAccountRenameFolder({required int id, required String name, required Coin c}); + Future crateApiAccountRenameFolder( + {required int id, required String name, required Coin c}); - Future crateApiAccountReorderAccount({required int oldPosition, required int newPosition, required Coin c}); + Future crateApiAccountReorderAccount( + {required int oldPosition, required int newPosition, required Coin c}); Future crateApiFrostResetSign({required Coin c}); Future crateApiAccountResetSync({required int id, required Coin c}); - Future crateApiOpenaliasResolveOpenalias({required String alias, required Coin c}); + Future crateApiOpenaliasResolveOpenalias( + {required String alias, required Coin c}); - Future crateApiOpenaliasResolveOpenaliasAll({required String alias}); + Future crateApiOpenaliasResolveOpenaliasAll( + {required String alias}); - Future crateApiOpenaliasResolveOpenaliasRaw({required String alias}); + Future crateApiOpenaliasResolveOpenaliasRaw( + {required String alias}); - Future crateApiSyncRewindSync({required int height, required int account, required Coin c}); + Future crateApiSyncRewindSync( + {required int height, required int account, required Coin c}); - Future crateApiPaySend({required int height, required List data, required Coin c}); + Future crateApiPaySend( + {required int height, required List data, required Coin c}); - Future crateApiZsaSetAssetName({required PlatformInt64 idAsset, required String name, required Coin c}); + Future crateApiZsaSetAssetName( + {required PlatformInt64 idAsset, required String name, required Coin c}); - Future crateApiFrostSetDkgAddress({required int id, required String address, required Coin c}); + Future crateApiFrostSetDkgAddress( + {required int id, required String address, required Coin c}); - Future crateApiFrostSetDkgParams({required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}); + Future crateApiFrostSetDkgParams( + {required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c}); void crateApiInitSetExpertMode({required bool enabled}); Stream crateApiInitSetLogStream(); - Future crateApiPluginSetPluginEnabled({required String id, required bool enabled, required Coin c}); + Future crateApiPluginSetPluginEnabled( + {required String id, required bool enabled, required Coin c}); - Future crateApiTransactionSetTxCategory({required int id, int? category, required Coin c}); + Future crateApiTransactionSetTxCategory( + {required int id, int? category, required Coin c}); - Future crateApiTransactionSetTxPrice({required int id, double? price, required Coin c}); + Future crateApiTransactionSetTxPrice( + {required int id, double? price, required Coin c}); - Future crateApiTransactionSetUserMemo({required int idTx, String? memo, required Coin c}); + Future crateApiTransactionSetUserMemo( + {required int idTx, String? memo, required Coin c}); Future crateApiAccountShowLedgerSaplingAddress({required Coin c}); Future crateApiAccountShowLedgerTransparentAddress({required Coin c}); - Stream crateApiAccountSignLedgerTransaction({required PcztPackage package, required Coin c}); + Stream crateApiAccountSignLedgerTransaction( + {required PcztPackage package, required Coin c}); - Future crateApiPaySignTransaction({required PcztPackage pczt, required Coin c}); + Future crateApiPaySignTransaction( + {required PcztPackage pczt, required Coin c}); Future crateApiMigrateStepMigration({required Coin c}); - Future crateApiPayStorePendingTx({required int height, required List txid, double? price, int? category, required Coin c}); + Future crateApiPayStorePendingTx( + {required int height, + required List txid, + double? price, + int? category, + required Coin c}); Stream crateApiSyncSynchronize( {required List accounts, @@ -447,7 +572,8 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountToggleAllNotes({required Coin c}); - void crateApiOpenaliasTryValidateZcashAddress({required String address, required Coin c}); + void crateApiOpenaliasTryValidateZcashAddress( + {required String address, required Coin c}); Future crateApiAccountTxAccountDefault(); @@ -459,25 +585,38 @@ abstract class RustLibApi extends BaseApi { Future crateApiAccountTxSpendDefault(); - String crateApiAccountUaFromUfvk({required String ufvk, int? di, required Coin c}); + String crateApiAccountUaFromUfvk( + {required String ufvk, int? di, required Coin c}); Future crateApiAccountUnlockAllNotes({required Coin c}); Future crateApiPayUnpackTransaction({required List bytes}); - Future crateApiAccountUpdateAccount({required AccountUpdate update, required Coin c}); + Future crateApiAccountUpdateAccount( + {required AccountUpdate update, required Coin c}); - Future crateApiContactsUpdateContact({required int id, String? name, List? addresses, String? notes, required Coin c}); + Future crateApiContactsUpdateContact( + {required int id, + String? name, + List? addresses, + String? notes, + required Coin c}); - Future crateApiTransactionUpdateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}); + Future crateApiTransactionUpdateHistoricalPrices( + {required String currency, + required double exchangeRate, + required Coin c}); bool crateApiOpenaliasValidateOpenaliasName({required String alias}); - bool crateApiOpenaliasValidateZcashAddress({required String address, required Coin c}); + bool crateApiOpenaliasValidateZcashAddress( + {required String address, required Coin c}); - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_DartVault; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_DartVault; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_DartVault; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr; @@ -487,17 +626,23 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_NoteMigration; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_NoteMigration; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_NoteMigration; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_NoteMigration; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_TransparentScanner; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_TransparentScanner; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_TransparentScanner; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_TransparentScannerPtr; } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -509,115 +654,139 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }); @override - Future> crateApiVaultDartVaultRecover({required DartVault that, required List vaultBytes, required String masterPassword}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - sse_encode_list_prim_u_8_loose(vaultBytes, serializer); - sse_encode_String(masterPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_restored_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRecoverConstMeta, - argValues: [that, vaultBytes, masterPassword], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiVaultDartVaultRecoverConstMeta => const TaskConstMeta( + Future> crateApiVaultDartVaultRecover( + {required DartVault that, + required List vaultBytes, + required String masterPassword}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(vaultBytes, serializer); + sse_encode_String(masterPassword, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 1, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_restored_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRecoverConstMeta, + argValues: [that, vaultBytes, masterPassword], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiVaultDartVaultRecoverConstMeta => + const TaskConstMeta( debugName: "DartVault_recover", argNames: ["that", "vaultBytes", "masterPassword"], ); @override Future> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, required List vaultBytes, required String deviceIdStr, required List prfOutput}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - sse_encode_list_prim_u_8_loose(vaultBytes, serializer); - sse_encode_String(deviceIdStr, serializer); - sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_restored_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRecoverWithPrfConstMeta, - argValues: [that, vaultBytes, deviceIdStr, prfOutput], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiVaultDartVaultRecoverWithPrfConstMeta => const TaskConstMeta( + {required DartVault that, + required List vaultBytes, + required String deviceIdStr, + required List prfOutput}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(vaultBytes, serializer); + sse_encode_String(deviceIdStr, serializer); + sse_encode_list_prim_u_8_loose(prfOutput, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 2, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_restored_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRecoverWithPrfConstMeta, + argValues: [that, vaultBytes, deviceIdStr, prfOutput], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiVaultDartVaultRecoverWithPrfConstMeta => + const TaskConstMeta( debugName: "DartVault_recover_with_prf", argNames: ["that", "vaultBytes", "deviceIdStr", "prfOutput"], ); @override Future crateApiVaultDartVaultRegisterDevice( - {required DartVault that, required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - sse_encode_list_prim_u_8_loose(initBytes, serializer); - sse_encode_String(masterPassword, serializer); - sse_encode_String(deviceIdStr, serializer); - sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 3, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRegisterDeviceConstMeta, - argValues: [that, initBytes, masterPassword, deviceIdStr, prfOutput], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiVaultDartVaultRegisterDeviceConstMeta => const TaskConstMeta( + {required DartVault that, + required List initBytes, + required String masterPassword, + required String deviceIdStr, + required List prfOutput}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(initBytes, serializer); + sse_encode_String(masterPassword, serializer); + sse_encode_String(deviceIdStr, serializer); + sse_encode_list_prim_u_8_loose(prfOutput, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 3, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRegisterDeviceConstMeta, + argValues: [that, initBytes, masterPassword, deviceIdStr, prfOutput], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiVaultDartVaultRegisterDeviceConstMeta => + const TaskConstMeta( debugName: "DartVault_register_device", - argNames: ["that", "initBytes", "masterPassword", "deviceIdStr", "prfOutput"], - ); - - @override - Future crateApiVaultDartVaultSetMasterPassword({required DartVault that, String? oldPassword, required String newPassword, Uint8List? oldBytes}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - sse_encode_opt_String(oldPassword, serializer); - sse_encode_String(newPassword, serializer); - sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 4, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultSetMasterPasswordConstMeta, - argValues: [that, oldPassword, newPassword, oldBytes], - apiImpl: this, - ), - ); - } + argNames: [ + "that", + "initBytes", + "masterPassword", + "deviceIdStr", + "prfOutput" + ], + ); - TaskConstMeta get kCrateApiVaultDartVaultSetMasterPasswordConstMeta => const TaskConstMeta( + @override + Future crateApiVaultDartVaultSetMasterPassword( + {required DartVault that, + String? oldPassword, + required String newPassword, + Uint8List? oldBytes}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_opt_String(oldPassword, serializer); + sse_encode_String(newPassword, serializer); + sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 4, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultSetMasterPasswordConstMeta, + argValues: [that, oldPassword, newPassword, oldBytes], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiVaultDartVaultSetMasterPasswordConstMeta => + const TaskConstMeta( debugName: "DartVault_set_master_password", argNames: ["that", "oldPassword", "newPassword", "oldBytes"], ); @@ -632,54 +801,73 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required bool useInternal, required int birthHeight, required List pk}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - sse_encode_u_32(timestamp, serializer); - sse_encode_String(name, serializer); - sse_encode_String(seed, serializer); - sse_encode_u_32(aindex, serializer); - sse_encode_bool(useInternal, serializer); - sse_encode_u_32(birthHeight, serializer); - sse_encode_list_prim_u_8_loose(pk, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 5, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultStoreAccountConstMeta, - argValues: [that, timestamp, name, seed, aindex, useInternal, birthHeight, pk], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiVaultDartVaultStoreAccountConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_u_32(timestamp, serializer); + sse_encode_String(name, serializer); + sse_encode_String(seed, serializer); + sse_encode_u_32(aindex, serializer); + sse_encode_bool(useInternal, serializer); + sse_encode_u_32(birthHeight, serializer); + sse_encode_list_prim_u_8_loose(pk, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 5, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultStoreAccountConstMeta, + argValues: [ + that, + timestamp, + name, + seed, + aindex, + useInternal, + birthHeight, + pk + ], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiVaultDartVaultStoreAccountConstMeta => + const TaskConstMeta( debugName: "DartVault_store_account", - argNames: ["that", "timestamp", "name", "seed", "aindex", "useInternal", "birthHeight", "pk"], + argNames: [ + "that", + "timestamp", + "name", + "seed", + "aindex", + "useInternal", + "birthHeight", + "pk" + ], ); @override Future crateApiVaultDartVaultTest({required DartVault that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 6, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiVaultDartVaultTestConstMeta, - argValues: [that], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 6, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiVaultDartVaultTestConstMeta, + argValues: [that], + apiImpl: this, + )); } TaskConstMeta get kCrateApiVaultDartVaultTestConstMeta => const TaskConstMeta( @@ -689,46 +877,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMempoolMempoolCancel({required Mempool that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolMempoolCancelConstMeta, - argValues: [that], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 7, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMempoolMempoolCancelConstMeta, + argValues: [that], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => + const TaskConstMeta( debugName: "Mempool_cancel", argNames: ["that"], ); @override Mempool crateApiMempoolMempoolNew() { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, - decodeErrorData: null, - ), - constMeta: kCrateApiMempoolMempoolNewConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, + decodeErrorData: null, + ), + constMeta: kCrateApiMempoolMempoolNewConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiMempoolMempoolNewConstMeta => const TaskConstMeta( @@ -737,28 +925,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Stream crateApiMempoolMempoolRun({required Mempool that, required Coin c}) { + Stream crateApiMempoolMempoolRun( + {required Mempool that, required Coin c}) { final mempoolSink = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(that, serializer); - sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolMempoolRunConstMeta, - argValues: [that, mempoolSink, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + that, serializer); + sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 9, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMempoolMempoolRunConstMeta, + argValues: [that, mempoolSink, c], + apiImpl: this, + ))); return mempoolSink.stream; } @@ -768,212 +955,222 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiMigrateNoteMigrationCancel({required NoteMigration that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationCancelConstMeta, - argValues: [that], - apiImpl: this, + Future crateApiMigrateNoteMigrationCancel( + {required NoteMigration that}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 10, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, ), - ); + constMeta: kCrateApiMigrateNoteMigrationCancelConstMeta, + argValues: [that], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => + const TaskConstMeta( debugName: "NoteMigration_cancel", argNames: ["that"], ); @override NoteMigration crateApiMigrateNoteMigrationNew() { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => const TaskConstMeta( + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => + const TaskConstMeta( debugName: "NoteMigration_new", argNames: [], ); @override - Stream crateApiMigrateNoteMigrationRun({required NoteMigration that, required Coin c, required BigInt meanDelayMs}) { + Stream crateApiMigrateNoteMigrationRun( + {required NoteMigration that, + required Coin c, + required BigInt meanDelayMs}) { final sink = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); - sse_encode_StreamSink_migration_status_Sse(sink, serializer); - sse_encode_box_autoadd_coin(c, serializer); - sse_encode_u_64(meanDelayMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateNoteMigrationRunConstMeta, - argValues: [that, sink, c, meanDelayMs], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + sse_encode_StreamSink_migration_status_Sse(sink, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_u_64(meanDelayMs, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 12, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateNoteMigrationRunConstMeta, + argValues: [that, sink, c, meanDelayMs], + apiImpl: this, + ))); return sink.stream; } - TaskConstMeta get kCrateApiMigrateNoteMigrationRunConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationRunConstMeta => + const TaskConstMeta( debugName: "NoteMigration_run", argNames: ["that", "sink", "c", "meanDelayMs"], ); @override - void crateApiMigrateNoteMigrationUpdateHeight({required NoteMigration that, required int height}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(that, serializer); - sse_encode_u_32(height, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationUpdateHeightConstMeta, - argValues: [that, height], - apiImpl: this, + void crateApiMigrateNoteMigrationUpdateHeight( + {required NoteMigration that, required int height}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + sse_encode_u_32(height, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, ), - ); + constMeta: kCrateApiMigrateNoteMigrationUpdateHeightConstMeta, + argValues: [that, height], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiMigrateNoteMigrationUpdateHeightConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiMigrateNoteMigrationUpdateHeightConstMeta => + const TaskConstMeta( debugName: "NoteMigration_update_height", argNames: ["that", "height"], ); @override - Future crateApiSweepTransparentScannerCancel({required TransparentScanner that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerCancelConstMeta, - argValues: [that], - apiImpl: this, + Future crateApiSweepTransparentScannerCancel( + {required TransparentScanner that}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 14, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiSweepTransparentScannerCancelConstMeta, + argValues: [that], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiSweepTransparentScannerCancelConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiSweepTransparentScannerCancelConstMeta => + const TaskConstMeta( debugName: "TransparentScanner_cancel", argNames: ["that"], ); @override Future crateApiSweepTransparentScannerNew() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerNewConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 15, port: port_); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSweepTransparentScannerNewConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => + const TaskConstMeta( debugName: "TransparentScanner_new", argNames: [], ); @override - Stream crateApiSweepTransparentScannerRun({required TransparentScanner that, required int endHeight, required int gapLimit, required Coin c}) { + Stream crateApiSweepTransparentScannerRun( + {required TransparentScanner that, + required int endHeight, + required int gapLimit, + required Coin c}) { final addressStream = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(that, serializer); - sse_encode_StreamSink_String_Sse(addressStream, serializer); - sse_encode_u_32(endHeight, serializer); - sse_encode_u_32(gapLimit, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerRunConstMeta, - argValues: [that, addressStream, endHeight, gapLimit, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + that, serializer); + sse_encode_StreamSink_String_Sse(addressStream, serializer); + sse_encode_u_32(endHeight, serializer); + sse_encode_u_32(gapLimit, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 16, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSweepTransparentScannerRunConstMeta, + argValues: [that, addressStream, endHeight, gapLimit, c], + apiImpl: this, + ))); return addressStream.stream; } - TaskConstMeta get kCrateApiSweepTransparentScannerRunConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiSweepTransparentScannerRunConstMeta => + const TaskConstMeta( debugName: "TransparentScanner_run", argNames: ["that", "addressStream", "endHeight", "gapLimit", "c"], ); @override Future crateApiSyncBalance({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pool_balance, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncBalanceConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 17, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pool_balance, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncBalanceConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncBalanceConstMeta => const TaskConstMeta( @@ -982,50 +1179,50 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayBroadcastTransaction({required int height, required List txBytes, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(txBytes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayBroadcastTransactionConstMeta, - argValues: [height, txBytes, c], - apiImpl: this, + Future crateApiPayBroadcastTransaction( + {required int height, required List txBytes, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(txBytes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 18, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPayBroadcastTransactionConstMeta, + argValues: [height, txBytes, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiPayBroadcastTransactionConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiPayBroadcastTransactionConstMeta => + const TaskConstMeta( debugName: "broadcast_transaction", argNames: ["height", "txBytes", "c"], ); @override Future crateApiPayBuildPuri({required List recipients}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayBuildPuriConstMeta, - argValues: [recipients], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 19, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayBuildPuriConstMeta, + argValues: [recipients], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayBuildPuriConstMeta => const TaskConstMeta( @@ -1034,24 +1231,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiSyncCacheBlockTime({required int height, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncCacheBlockTimeConstMeta, - argValues: [height, c], - apiImpl: this, + Future crateApiSyncCacheBlockTime( + {required int height, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 20, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiSyncCacheBlockTimeConstMeta, + argValues: [height, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncCacheBlockTimeConstMeta => const TaskConstMeta( @@ -1061,22 +1258,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostCancelDkg({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostCancelDkgConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 21, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostCancelDkgConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostCancelDkgConstMeta => const TaskConstMeta( @@ -1086,21 +1282,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncCancelSync() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncCancelSyncConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 22, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncCancelSyncConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncCancelSyncConstMeta => const TaskConstMeta( @@ -1109,26 +1304,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiDbChangeDbPassword({required String dbFilepath, required String tmpDir, required String oldPassword, required String newPassword}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - sse_encode_String(tmpDir, serializer); - sse_encode_String(oldPassword, serializer); - sse_encode_String(newPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbChangeDbPasswordConstMeta, - argValues: [dbFilepath, tmpDir, oldPassword, newPassword], - apiImpl: this, - ), - ); + Future crateApiDbChangeDbPassword( + {required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + sse_encode_String(tmpDir, serializer); + sse_encode_String(oldPassword, serializer); + sse_encode_String(newPassword, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 23, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbChangeDbPasswordConstMeta, + argValues: [dbFilepath, tmpDir, oldPassword, newPassword], + apiImpl: this, + )); } TaskConstMeta get kCrateApiDbChangeDbPasswordConstMeta => const TaskConstMeta( @@ -1138,46 +1336,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override SaplingParamsStatus crateApiSaplingCheckSaplingParams() { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_sapling_params_status, - decodeErrorData: null, - ), - constMeta: kCrateApiSaplingCheckSaplingParamsConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => const TaskConstMeta( + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_sapling_params_status, + decodeErrorData: null, + ), + constMeta: kCrateApiSaplingCheckSaplingParamsConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => + const TaskConstMeta( debugName: "check_sapling_params", argNames: [], ); @override Future crateApiCoinClosePool({required String dbFilepath}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinClosePoolConstMeta, - argValues: [dbFilepath], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 25, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinClosePoolConstMeta, + argValues: [dbFilepath], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinClosePoolConstMeta => const TaskConstMeta( @@ -1187,22 +1383,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinCoinGetName({required Coin that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinCoinGetNameConstMeta, - argValues: [that], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 26, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinCoinGetNameConstMeta, + argValues: [that], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinGetNameConstMeta => const TaskConstMeta( @@ -1212,22 +1407,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Coin crateApiCoinCoinNew({int? defaultCoin}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinCoinNewConstMeta, - argValues: [defaultCoin], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinCoinNewConstMeta, + argValues: [defaultCoin], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinNewConstMeta => const TaskConstMeta( @@ -1236,51 +1429,52 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiCoinCoinOpenDatabase({required Coin that, required String dbFilepath, String? password}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_String(dbFilepath, serializer); - sse_encode_opt_String(password, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinOpenDatabaseConstMeta, - argValues: [that, dbFilepath, password], - apiImpl: this, + Future crateApiCoinCoinOpenDatabase( + {required Coin that, required String dbFilepath, String? password}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_String(dbFilepath, serializer); + sse_encode_opt_String(password, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 28, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiCoinCoinOpenDatabaseConstMeta, + argValues: [that, dbFilepath, password], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiCoinCoinOpenDatabaseConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiCoinCoinOpenDatabaseConstMeta => + const TaskConstMeta( debugName: "coin_open_database", argNames: ["that", "dbFilepath", "password"], ); @override - Future crateApiCoinCoinSetAccount({required Coin that, required int account}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_u_32(account, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetAccountConstMeta, - argValues: [that, account], - apiImpl: this, + Future crateApiCoinCoinSetAccount( + {required Coin that, required int account}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_u_32(account, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 29, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiCoinCoinSetAccountConstMeta, + argValues: [that, account], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinSetAccountConstMeta => const TaskConstMeta( @@ -1289,25 +1483,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Coin crateApiCoinCoinSetLwd({required Coin that, required int serverType, required String url}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_u_8(serverType, serializer); - sse_encode_String(url, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetLwdConstMeta, - argValues: [that, serverType, url], - apiImpl: this, + Coin crateApiCoinCoinSetLwd( + {required Coin that, required int serverType, required String url}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_u_8(serverType, serializer); + sse_encode_String(url, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiCoinCoinSetLwdConstMeta, + argValues: [that, serverType, url], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinSetLwdConstMeta => const TaskConstMeta( @@ -1317,23 +1510,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_String(proxy, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetProxyConstMeta, - argValues: [that, proxy], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_String(proxy, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinSetProxyConstMeta, + argValues: [that, proxy], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinSetProxyConstMeta => const TaskConstMeta( @@ -1342,24 +1533,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiCoinCoinSetUseTor({required Coin that, required bool useTor}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_bool(useTor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetUseTorConstMeta, - argValues: [that, useTor], - apiImpl: this, + Future crateApiCoinCoinSetUseTor( + {required Coin that, required bool useTor}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_bool(useTor, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 32, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiCoinCoinSetUseTorConstMeta, + argValues: [that, useTor], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinCoinSetUseTorConstMeta => const TaskConstMeta( @@ -1368,103 +1559,108 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiContactsCreateContact({required String name, required List addresses, required String notes, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_list_String(addresses, serializer); - sse_encode_String(notes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsCreateContactConstMeta, - argValues: [name, addresses, notes, c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiContactsCreateContactConstMeta => const TaskConstMeta( + Future crateApiContactsCreateContact( + {required String name, + required List addresses, + required String notes, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_list_String(addresses, serializer); + sse_encode_String(notes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 33, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_contact, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsCreateContactConstMeta, + argValues: [name, addresses, notes, c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiContactsCreateContactConstMeta => + const TaskConstMeta( debugName: "create_contact", argNames: ["name", "addresses", "notes", "c"], ); @override - Future crateApiAccountCreateNewCategory({required Category category, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_category(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountCreateNewCategoryConstMeta, - argValues: [category, c], - apiImpl: this, + Future crateApiAccountCreateNewCategory( + {required Category category, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_category(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 34, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountCreateNewCategoryConstMeta, + argValues: [category, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountCreateNewCategoryConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountCreateNewCategoryConstMeta => + const TaskConstMeta( debugName: "create_new_category", argNames: ["category", "c"], ); @override - Future crateApiAccountCreateNewFolder({required String name, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_folder, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountCreateNewFolderConstMeta, - argValues: [name, c], - apiImpl: this, + Future crateApiAccountCreateNewFolder( + {required String name, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 35, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_folder, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountCreateNewFolderConstMeta, + argValues: [name, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountCreateNewFolderConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountCreateNewFolderConstMeta => + const TaskConstMeta( debugName: "create_new_folder", argNames: ["name", "c"], ); @override Future crateApiRaptorDecode({required List packet}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(packet, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorDecodeConstMeta, - argValues: [packet], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(packet, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 36, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorDecodeConstMeta, + argValues: [packet], + apiImpl: this, + )); } TaskConstMeta get kCrateApiRaptorDecodeConstMeta => const TaskConstMeta( @@ -1473,105 +1669,109 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountDeleteAccount({required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteAccountConstMeta, - argValues: [account, c], - apiImpl: this, + Future crateApiAccountDeleteAccount( + {required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 37, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountDeleteAccountConstMeta, + argValues: [account, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => + const TaskConstMeta( debugName: "delete_account", argNames: ["account", "c"], ); @override - Future crateApiAccountDeleteCategories({required List ids, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteCategoriesConstMeta, - argValues: [ids, c], - apiImpl: this, + Future crateApiAccountDeleteCategories( + {required List ids, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 38, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountDeleteCategoriesConstMeta, + argValues: [ids, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => + const TaskConstMeta( debugName: "delete_categories", argNames: ["ids", "c"], ); @override - Future crateApiContactsDeleteContacts({required List ids, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsDeleteContactsConstMeta, - argValues: [ids, c], - apiImpl: this, + Future crateApiContactsDeleteContacts( + {required List ids, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 39, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiContactsDeleteContactsConstMeta, + argValues: [ids, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => + const TaskConstMeta( debugName: "delete_contacts", argNames: ["ids", "c"], ); @override - Future crateApiAccountDeleteFolders({required List ids, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteFoldersConstMeta, - argValues: [ids, c], - apiImpl: this, + Future crateApiAccountDeleteFolders( + {required List ids, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 40, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountDeleteFoldersConstMeta, + argValues: [ids, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => + const TaskConstMeta( debugName: "delete_folders", argNames: ["ids", "c"], ); @@ -1579,25 +1779,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiFrostDoDkg({required Coin c}) { final status = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_dkg_status_Sse(status, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostDoDkgConstMeta, - argValues: [status, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_dkg_status_Sse(status, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 41, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostDoDkgConstMeta, + argValues: [status, c], + apiImpl: this, + ))); return status.stream; } @@ -1609,25 +1806,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiFrostDoSign({required Coin c}) { final status = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_signing_status_Sse(status, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostDoSignConstMeta, - argValues: [status, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_signing_status_Sse(status, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 42, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostDoSignConstMeta, + argValues: [status, c], + apiImpl: this, + ))); return status.stream; } @@ -1638,46 +1832,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSaplingDownloadSaplingParams() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSaplingDownloadSaplingParamsConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 43, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSaplingDownloadSaplingParamsConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => + const TaskConstMeta( debugName: "download_sapling_params", argNames: [], ); @override Future crateApiAccountDummyExport({required SigningEvent a}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_signing_event(a, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountDummyExportConstMeta, - argValues: [a], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_signing_event(a, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 44, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountDummyExportConstMeta, + argValues: [a], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountDummyExportConstMeta => const TaskConstMeta( @@ -1686,24 +1879,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiRaptorEncode({required String path, required RaptorQParams params}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(path, serializer); - sse_encode_box_autoadd_raptor_q_params(params, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorEncodeConstMeta, - argValues: [path, params], - apiImpl: this, + Future> crateApiRaptorEncode( + {required String path, required RaptorQParams params}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(path, serializer); + sse_encode_box_autoadd_raptor_q_params(params, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 45, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiRaptorEncodeConstMeta, + argValues: [path, params], + apiImpl: this, + )); } TaskConstMeta get kCrateApiRaptorEncodeConstMeta => const TaskConstMeta( @@ -1713,21 +1906,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiRaptorEndDecode() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorEndDecodeConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 46, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorEndDecodeConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiRaptorEndDecodeConstMeta => const TaskConstMeta( @@ -1736,208 +1928,214 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountExportAccount({required int id, required String passphrase, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_String(passphrase, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountExportAccountConstMeta, - argValues: [id, passphrase, c], - apiImpl: this, + Future crateApiAccountExportAccount( + {required int id, required String passphrase, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_String(passphrase, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 47, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountExportAccountConstMeta, + argValues: [id, passphrase, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountExportAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountExportAccountConstMeta => + const TaskConstMeta( debugName: "export_account", argNames: ["id", "passphrase", "c"], ); @override Future crateApiContactsExportContactsVcard({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsExportContactsVcardConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 48, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsExportContactsVcardConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => + const TaskConstMeta( debugName: "export_contacts_vcard", argNames: ["c"], ); @override - Future crateApiPayExtractTransaction({required PcztPackage package}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(package, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayExtractTransactionConstMeta, - argValues: [package], - apiImpl: this, + Future crateApiPayExtractTransaction( + {required PcztPackage package}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(package, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 49, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPayExtractTransactionConstMeta, + argValues: [package], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiPayExtractTransactionConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiPayExtractTransactionConstMeta => + const TaskConstMeta( debugName: "extract_transaction", argNames: ["package"], ); @override - Future> crateApiAccountFetchAddressTxCount({required Coin c, required bool aggregate, required int poolFilter}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - sse_encode_bool(aggregate, serializer); - sse_encode_u_8(poolFilter, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_t_address_tx_count, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountFetchAddressTxCountConstMeta, - argValues: [c, aggregate, poolFilter], - apiImpl: this, + Future> crateApiAccountFetchAddressTxCount( + {required Coin c, required bool aggregate, required int poolFilter}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_bool(aggregate, serializer); + sse_encode_u_8(poolFilter, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 50, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_t_address_tx_count, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountFetchAddressTxCountConstMeta, + argValues: [c, aggregate, poolFilter], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountFetchAddressTxCountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountFetchAddressTxCountConstMeta => + const TaskConstMeta( debugName: "fetch_address_tx_count", argNames: ["c", "aggregate", "poolFilter"], ); @override - Future> crateApiTransactionFetchAmounts({int? from, int? to, required int category, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_32(from, serializer); - sse_encode_opt_box_autoadd_u_32(to, serializer); - sse_encode_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_record_u_32_f_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFetchAmountsConstMeta, - argValues: [from, to, category, c], - apiImpl: this, + Future> crateApiTransactionFetchAmounts( + {int? from, int? to, required int category, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_32(from, serializer); + sse_encode_opt_box_autoadd_u_32(to, serializer); + sse_encode_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 51, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_record_u_32_f_64, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionFetchAmountsConstMeta, + argValues: [from, to, category, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionFetchAmountsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFetchAmountsConstMeta => + const TaskConstMeta( debugName: "fetch_amounts", argNames: ["from", "to", "category", "c"], ); @override - Future> crateApiTransactionFetchCategoryAmounts({int? from, int? to, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_32(from, serializer); - sse_encode_opt_box_autoadd_u_32(to, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_record_string_f_64_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFetchCategoryAmountsConstMeta, - argValues: [from, to, c], - apiImpl: this, + Future> crateApiTransactionFetchCategoryAmounts( + {int? from, int? to, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_32(from, serializer); + sse_encode_opt_box_autoadd_u_32(to, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 52, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_record_string_f_64_bool, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionFetchCategoryAmountsConstMeta, + argValues: [from, to, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionFetchCategoryAmountsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFetchCategoryAmountsConstMeta => + const TaskConstMeta( debugName: "fetch_category_amounts", argNames: ["from", "to", "c"], ); @override - Future> crateApiAccountFetchTransparentAddressTxCount({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_t_address_tx_count, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountFetchTransparentAddressTxCountConstMeta, - argValues: [c], - apiImpl: this, + Future> crateApiAccountFetchTransparentAddressTxCount( + {required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 53, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_t_address_tx_count, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountFetchTransparentAddressTxCountConstMeta, + argValues: [c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountFetchTransparentAddressTxCountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountFetchTransparentAddressTxCountConstMeta => + const TaskConstMeta( debugName: "fetch_transparent_address_tx_count", argNames: ["c"], ); @override - Future crateApiSyncFetchTxDetails({required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncFetchTxDetailsConstMeta, - argValues: [account, c], - apiImpl: this, + Future crateApiSyncFetchTxDetails( + {required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 54, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiSyncFetchTxDetailsConstMeta, + argValues: [account, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncFetchTxDetailsConstMeta => const TaskConstMeta( @@ -1946,149 +2144,149 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiTransactionFillMissingTxPrices({required String api, required String currency, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(currency, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 55, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFillMissingTxPricesConstMeta, - argValues: [api, currency, c], - apiImpl: this, + Future crateApiTransactionFillMissingTxPrices( + {required String api, required String currency, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(currency, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 55, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionFillMissingTxPricesConstMeta, + argValues: [api, currency, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionFillMissingTxPricesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionFillMissingTxPricesConstMeta => + const TaskConstMeta( debugName: "fill_missing_tx_prices", argNames: ["api", "currency", "c"], ); @override - Future> crateApiContactsFindContactsForAddress({required String address, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 56, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact_match, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsFindContactsForAddressConstMeta, - argValues: [address, c], - apiImpl: this, + Future> crateApiContactsFindContactsForAddress( + {required String address, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 56, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact_match, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiContactsFindContactsForAddressConstMeta, + argValues: [address, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiContactsFindContactsForAddressConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiContactsFindContactsForAddressConstMeta => + const TaskConstMeta( debugName: "find_contacts_for_address", argNames: ["address", "c"], ); @override Future crateApiFrostFrostSignParamsDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 57, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_frost_sign_params, - decodeErrorData: null, - ), - constMeta: kCrateApiFrostFrostSignParamsDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 57, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_frost_sign_params, + decodeErrorData: null, + ), + constMeta: kCrateApiFrostFrostSignParamsDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => + const TaskConstMeta( debugName: "frost_sign_params_default", argNames: [], ); @override Future crateApiAccountGenerateNextChangeAddress({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 58, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGenerateNextChangeAddressConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountGenerateNextChangeAddressConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 58, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGenerateNextChangeAddressConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountGenerateNextChangeAddressConstMeta => + const TaskConstMeta( debugName: "generate_next_change_address", argNames: ["c"], ); @override Future crateApiAccountGenerateNextDindex({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 59, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGenerateNextDindexConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 59, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGenerateNextDindexConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => + const TaskConstMeta( debugName: "generate_next_dindex", argNames: ["c"], ); @override String crateApiKeyGenerateSeed() { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiKeyGenerateSeedConstMeta, - argValues: [], - apiImpl: this, + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiKeyGenerateSeedConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyGenerateSeedConstMeta => const TaskConstMeta( @@ -2097,257 +2295,263 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountGetAccountAddresses({required int account, required int uaPools, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_u_8(uaPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 61, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_addresses, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountAddressesConstMeta, - argValues: [account, uaPools, c], - apiImpl: this, + Future crateApiAccountGetAccountAddresses( + {required int account, required int uaPools, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_u_8(uaPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 61, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_addresses, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAccountAddressesConstMeta, + argValues: [account, uaPools, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAccountAddressesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountAddressesConstMeta => + const TaskConstMeta( debugName: "get_account_addresses", argNames: ["account", "uaPools", "c"], ); @override - Future crateApiAccountGetAccountFingerprint({required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 62, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountFingerprintConstMeta, - argValues: [account, c], - apiImpl: this, + Future crateApiAccountGetAccountFingerprint( + {required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 62, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAccountFingerprintConstMeta, + argValues: [account, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAccountFingerprintConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountFingerprintConstMeta => + const TaskConstMeta( debugName: "get_account_fingerprint", argNames: ["account", "c"], ); @override Future crateApiAccountGetAccountFrostParams({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 63, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountFrostParamsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountGetAccountFrostParamsConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 63, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountFrostParamsConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountGetAccountFrostParamsConstMeta => + const TaskConstMeta( debugName: "get_account_frost_params", argNames: ["c"], ); @override - Future crateApiAccountGetAccountPools({required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_8, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountPoolsConstMeta, - argValues: [account, c], - apiImpl: this, + Future crateApiAccountGetAccountPools( + {required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 64, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_8, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAccountPoolsConstMeta, + argValues: [account, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAccountPoolsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountPoolsConstMeta => + const TaskConstMeta( debugName: "get_account_pools", argNames: ["account", "c"], ); @override - Future crateApiAccountGetAccountSeed({required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_box_autoadd_seed, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountSeedConstMeta, - argValues: [account, c], - apiImpl: this, + Future crateApiAccountGetAccountSeed( + {required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 65, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_seed, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAccountSeedConstMeta, + argValues: [account, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAccountSeedConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountSeedConstMeta => + const TaskConstMeta( debugName: "get_account_seed", argNames: ["account", "c"], ); @override - Future crateApiAccountGetAccountUfvk({required int account, required int pools, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_u_8(pools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 66, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountUfvkConstMeta, - argValues: [account, pools, c], - apiImpl: this, + Future crateApiAccountGetAccountUfvk( + {required int account, required int pools, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_u_8(pools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 66, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAccountUfvkConstMeta, + argValues: [account, pools, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAccountUfvkConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAccountUfvkConstMeta => + const TaskConstMeta( debugName: "get_account_ufvk", argNames: ["account", "pools", "c"], ); @override - Future crateApiAccountGetAddresses({required int uaPools, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(uaPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_addresses, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAddressesConstMeta, - argValues: [uaPools, c], - apiImpl: this, + Future crateApiAccountGetAddresses( + {required int uaPools, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(uaPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 67, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_addresses, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetAddressesConstMeta, + argValues: [uaPools, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetAddressesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetAddressesConstMeta => + const TaskConstMeta( debugName: "get_addresses", argNames: ["uaPools", "c"], ); @override - Future crateApiNetworkGetCoingeckoPrice({required String api, required String currency}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(currency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 68, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_f_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetCoingeckoPriceConstMeta, - argValues: [api, currency], - apiImpl: this, + Future crateApiNetworkGetCoingeckoPrice( + {required String api, required String currency}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(currency, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 68, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_f_64, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiNetworkGetCoingeckoPriceConstMeta, + argValues: [api, currency], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiNetworkGetCoingeckoPriceConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetCoingeckoPriceConstMeta => + const TaskConstMeta( debugName: "get_coingecko_price", argNames: ["api", "currency"], ); @override Future crateApiNetworkGetCurrentHeight({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetCurrentHeightConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 69, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetCurrentHeightConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => + const TaskConstMeta( debugName: "get_current_height", argNames: ["c"], ); @override Future crateApiSyncGetDbHeight({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_sync_height, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncGetDbHeightConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 70, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_sync_height, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncGetDbHeightConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncGetDbHeightConstMeta => const TaskConstMeta( @@ -2357,101 +2561,103 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiFrostGetDkgAddresses({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostGetDkgAddressesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 71, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostGetDkgAddressesConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => + const TaskConstMeta( debugName: "get_dkg_addresses", argNames: ["c"], ); @override - Future crateApiNetworkGetExchangeRate({required String api, required String fromCurrency, required String toCurrency}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(fromCurrency, serializer); - sse_encode_String(toCurrency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 72, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_exchange_rate, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetExchangeRateConstMeta, - argValues: [api, fromCurrency, toCurrency], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiNetworkGetExchangeRateConstMeta => const TaskConstMeta( + Future crateApiNetworkGetExchangeRate( + {required String api, + required String fromCurrency, + required String toCurrency}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(fromCurrency, serializer); + sse_encode_String(toCurrency, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 72, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_exchange_rate, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetExchangeRateConstMeta, + argValues: [api, fromCurrency, toCurrency], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiNetworkGetExchangeRateConstMeta => + const TaskConstMeta( debugName: "get_exchange_rate", argNames: ["api", "fromCurrency", "toCurrency"], ); @override - Future crateApiAccountGetExportedData({required int type, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(type, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetExportedDataConstMeta, - argValues: [type, c], - apiImpl: this, + Future crateApiAccountGetExportedData( + {required int type, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(type, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 73, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetExportedDataConstMeta, + argValues: [type, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetExportedDataConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetExportedDataConstMeta => + const TaskConstMeta( debugName: "get_exported_data", argNames: ["type", "c"], ); @override int crateApiKeyGetKeyPools({required String key, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_8, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiKeyGetKeyPoolsConstMeta, - argValues: [key, c], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_8, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiKeyGetKeyPoolsConstMeta, + argValues: [key, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyGetKeyPoolsConstMeta => const TaskConstMeta( @@ -2460,100 +2666,100 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiMempoolGetMempoolTx({required String txId, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(txId, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolGetMempoolTxConstMeta, - argValues: [txId, c], - apiImpl: this, + Future crateApiMempoolGetMempoolTx( + {required String txId, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(txId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 75, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiMempoolGetMempoolTxConstMeta, + argValues: [txId, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => + const TaskConstMeta( debugName: "get_mempool_tx", argNames: ["txId", "c"], ); @override Future crateApiMigrateGetMigrationStatus({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_migration_status, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateGetMigrationStatusConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 76, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_migration_status, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateGetMigrationStatusConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => + const TaskConstMeta( debugName: "get_migration_status", argNames: ["c"], ); @override Future crateApiNetworkGetNetworkName({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 77, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: null, - ), - constMeta: kCrateApiNetworkGetNetworkNameConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 77, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kCrateApiNetworkGetNetworkNameConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => + const TaskConstMeta( debugName: "get_network_name", argNames: ["c"], ); @override Future crateApiDbGetProp({required String key, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbGetPropConstMeta, - argValues: [key, c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 78, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbGetPropConstMeta, + argValues: [key, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiDbGetPropConstMeta => const TaskConstMeta( @@ -2563,22 +2769,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Uint8List crateApiRaptorGetQrBytes({required List data}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorGetQrBytesConstMeta, - argValues: [data], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(data, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorGetQrBytesConstMeta, + argValues: [data], + apiImpl: this, + )); } TaskConstMeta get kCrateApiRaptorGetQrBytesConstMeta => const TaskConstMeta( @@ -2587,47 +2791,47 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiNetworkGetSupportedVsCurrencies({required String api}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 80, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetSupportedVsCurrenciesConstMeta, - argValues: [api], - apiImpl: this, + Future> crateApiNetworkGetSupportedVsCurrencies( + {required String api}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 80, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiNetworkGetSupportedVsCurrenciesConstMeta, + argValues: [api], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiNetworkGetSupportedVsCurrenciesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiNetworkGetSupportedVsCurrenciesConstMeta => + const TaskConstMeta( debugName: "get_supported_vs_currencies", argNames: ["api"], ); @override Future crateApiCoinGetTorClient() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 81, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinGetTorClientConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 81, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinGetTorClientConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinGetTorClientConstMeta => const TaskConstMeta( @@ -2636,74 +2840,74 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountGetTxDetails({required int idTx, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(idTx, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 82, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetTxDetailsConstMeta, - argValues: [idTx, c], - apiImpl: this, + Future crateApiAccountGetTxDetails( + {required int idTx, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(idTx, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 82, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_account, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountGetTxDetailsConstMeta, + argValues: [idTx, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => + const TaskConstMeta( debugName: "get_tx_details", argNames: ["idTx", "c"], ); @override Future crateApiFrostHasDkgAddresses({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostHasDkgAddressesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 83, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostHasDkgAddressesConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => + const TaskConstMeta( debugName: "has_dkg_addresses", argNames: ["c"], ); @override Future crateApiFrostHasDkgParams({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 84, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostHasDkgParamsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 84, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostHasDkgParamsConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostHasDkgParamsConstMeta => const TaskConstMeta( @@ -2713,99 +2917,100 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountHasTransparentPubKey({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 85, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountHasTransparentPubKeyConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountHasTransparentPubKeyConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 85, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountHasTransparentPubKeyConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountHasTransparentPubKeyConstMeta => + const TaskConstMeta( debugName: "has_transparent_pub_key", argNames: ["c"], ); @override - Future crateApiAccountImportAccount({required String passphrase, required List data, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(passphrase, serializer); - sse_encode_list_prim_u_8_loose(data, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 86, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountImportAccountConstMeta, - argValues: [passphrase, data, c], - apiImpl: this, + Future crateApiAccountImportAccount( + {required String passphrase, required List data, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(passphrase, serializer); + sse_encode_list_prim_u_8_loose(data, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 86, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountImportAccountConstMeta, + argValues: [passphrase, data, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountImportAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountImportAccountConstMeta => + const TaskConstMeta( debugName: "import_account", argNames: ["passphrase", "data", "c"], ); @override - Future> crateApiContactsImportContactsVcard({required String vcardData, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(vcardData, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 87, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsImportContactsVcardConstMeta, - argValues: [vcardData, c], - apiImpl: this, + Future> crateApiContactsImportContactsVcard( + {required String vcardData, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(vcardData, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 87, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiContactsImportContactsVcardConstMeta, + argValues: [vcardData, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiContactsImportContactsVcardConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiContactsImportContactsVcardConstMeta => + const TaskConstMeta( debugName: "import_contacts_vcard", argNames: ["vcardData", "c"], ); @override Future crateApiInitInitApp() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 88, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitInitAppConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 88, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitInitAppConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiInitInitAppConstMeta => const TaskConstMeta( @@ -2815,21 +3020,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiRaptorInitApp() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 89, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiRaptorInitAppConstMeta, - argValues: [], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 89, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiRaptorInitAppConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiRaptorInitAppConstMeta => const TaskConstMeta( @@ -2839,22 +3043,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinInitDatadir({required String directory}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 90, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinInitDatadirConstMeta, - argValues: [directory], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(directory, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 90, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinInitDatadirConstMeta, + argValues: [directory], + apiImpl: this, + )); } TaskConstMeta get kCrateApiCoinInitDatadirConstMeta => const TaskConstMeta( @@ -2864,22 +3067,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkInitDatadir({required String directory}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 91, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkInitDatadirConstMeta, - argValues: [directory], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(directory, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 91, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkInitDatadirConstMeta, + argValues: [directory], + apiImpl: this, + )); } TaskConstMeta get kCrateApiNetworkInitDatadirConstMeta => const TaskConstMeta( @@ -2889,22 +3091,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostInitDkg({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 92, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostInitDkgConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 92, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostInitDkgConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostInitDkgConstMeta => const TaskConstMeta( @@ -2914,21 +3115,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiPluginInitPlugins() { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginInitPluginsConstMeta, - argValues: [], - apiImpl: this, + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPluginInitPluginsConstMeta, + argValues: [], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPluginInitPluginsConstMeta => const TaskConstMeta( @@ -2937,26 +3136,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiFrostInitSign({required int coordinator, required int fundingAccount, required PcztPackage pczt, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(coordinator, serializer); - sse_encode_u_32(fundingAccount, serializer); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 94, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostInitSignConstMeta, - argValues: [coordinator, fundingAccount, pczt, c], - apiImpl: this, - ), - ); + Future crateApiFrostInitSign( + {required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(coordinator, serializer); + sse_encode_u_32(fundingAccount, serializer); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 94, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostInitSignConstMeta, + argValues: [coordinator, fundingAccount, pczt, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostInitSignConstMeta => const TaskConstMeta( @@ -2965,23 +3167,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiVaultInitVault({required FutureOr Function(Uint8List) append}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(append, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 95, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultInitVaultConstMeta, - argValues: [append], - apiImpl: this, + Future crateApiVaultInitVault( + {required FutureOr Function(Uint8List) append}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + append, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 95, port: port_); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiVaultInitVaultConstMeta, + argValues: [append], + apiImpl: this, + )); } TaskConstMeta get kCrateApiVaultInitVaultConstMeta => const TaskConstMeta( @@ -2990,100 +3194,99 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPluginInstallPlugin({required String url, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(url, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 96, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_plugin_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginInstallPluginConstMeta, - argValues: [url, c], - apiImpl: this, + Future crateApiPluginInstallPlugin( + {required String url, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(url, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 96, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_plugin_info, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPluginInstallPluginConstMeta, + argValues: [url, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => + const TaskConstMeta( debugName: "install_plugin", argNames: ["url", "c"], ); @override Future crateApiNetworkIsIronwoodActive({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkIsIronwoodActiveConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 97, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkIsIronwoodActiveConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => + const TaskConstMeta( debugName: "is_ironwood_active", argNames: ["c"], ); @override Future crateApiFrostIsSigningInProgress({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 98, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostIsSigningInProgressConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 98, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostIsSigningInProgressConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => + const TaskConstMeta( debugName: "is_signing_in_progress", argNames: ["c"], ); @override bool crateApiKeyIsTexAddress({required String address, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsTexAddressConstMeta, - argValues: [address, c], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsTexAddressConstMeta, + argValues: [address, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyIsTexAddressConstMeta => const TaskConstMeta( @@ -3093,22 +3296,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidAddress({required String address}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidAddressConstMeta, - argValues: [address], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidAddressConstMeta, + argValues: [address], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyIsValidAddressConstMeta => const TaskConstMeta( @@ -3118,23 +3319,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidFvk({required String fvk, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(fvk, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidFvkConstMeta, - argValues: [fvk, c], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(fvk, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidFvkConstMeta, + argValues: [fvk, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyIsValidFvkConstMeta => const TaskConstMeta( @@ -3144,23 +3343,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidKey({required String key, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidKeyConstMeta, - argValues: [key, c], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidKeyConstMeta, + argValues: [key, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyIsValidKeyConstMeta => const TaskConstMeta( @@ -3170,22 +3367,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidPhrase({required String phrase}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidPhraseConstMeta, - argValues: [phrase], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(phrase, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidPhraseConstMeta, + argValues: [phrase], + apiImpl: this, + )); } TaskConstMeta get kCrateApiKeyIsValidPhraseConstMeta => const TaskConstMeta( @@ -3194,49 +3389,48 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - bool crateApiKeyIsValidTransparentAddress({required String address, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidTransparentAddressConstMeta, - argValues: [address, c], - apiImpl: this, + bool crateApiKeyIsValidTransparentAddress( + {required String address, required Coin c}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, ), - ); + constMeta: kCrateApiKeyIsValidTransparentAddressConstMeta, + argValues: [address, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiKeyIsValidTransparentAddressConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiKeyIsValidTransparentAddressConstMeta => + const TaskConstMeta( debugName: "is_valid_transparent_address", argNames: ["address", "c"], ); @override Future crateApiZsaIsZsaAvailable({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 105, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiZsaIsZsaAvailableConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 105, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiZsaIsZsaAvailableConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiZsaIsZsaAvailableConstMeta => const TaskConstMeta( @@ -3253,128 +3447,143 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Uint8List? descHash, required int idAccount, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(assetName, serializer); - sse_encode_u_64(amount, serializer); - sse_encode_bool(firstIssuance, serializer); - sse_encode_bool(finalize, serializer); - sse_encode_opt_list_prim_u_8_strict(descHash, serializer); - sse_encode_u_32(idAccount, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 106, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiIssuanceIssueAssetConstMeta, - argValues: [assetName, amount, firstIssuance, finalize, descHash, idAccount, c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(assetName, serializer); + sse_encode_u_64(amount, serializer); + sse_encode_bool(firstIssuance, serializer); + sse_encode_bool(finalize, serializer); + sse_encode_opt_list_prim_u_8_strict(descHash, serializer); + sse_encode_u_32(idAccount, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 106, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiIssuanceIssueAssetConstMeta, + argValues: [ + assetName, + amount, + firstIssuance, + finalize, + descHash, + idAccount, + c + ], + apiImpl: this, + )); } TaskConstMeta get kCrateApiIssuanceIssueAssetConstMeta => const TaskConstMeta( debugName: "issue_asset", - argNames: ["assetName", "amount", "firstIssuance", "finalize", "descHash", "idAccount", "c"], + argNames: [ + "assetName", + "amount", + "firstIssuance", + "finalize", + "descHash", + "idAccount", + "c" + ], ); @override Future> crateApiAccountListAccounts({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 107, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListAccountsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountListAccountsConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 107, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListAccountsConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountListAccountsConstMeta => + const TaskConstMeta( debugName: "list_accounts", argNames: ["c"], ); @override Future> crateApiAccountListCategories({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 108, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_category, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListCategoriesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 108, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_category, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListCategoriesConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => + const TaskConstMeta( debugName: "list_categories", argNames: ["c"], ); @override Future> crateApiContactsListContacts({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 109, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsListContactsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiContactsListContactsConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 109, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsListContactsConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiContactsListContactsConstMeta => + const TaskConstMeta( debugName: "list_contacts", argNames: ["c"], ); @override - Future> crateApiDbListDbAccounts({required String dbFilepath}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 110, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_db_account_preview, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbListDbAccountsConstMeta, - argValues: [dbFilepath], - apiImpl: this, + Future> crateApiDbListDbAccounts( + {required String dbFilepath}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 110, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_db_account_preview, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiDbListDbAccountsConstMeta, + argValues: [dbFilepath], + apiImpl: this, + )); } TaskConstMeta get kCrateApiDbListDbAccountsConstMeta => const TaskConstMeta( @@ -3384,22 +3593,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiDbListDbNames({required String dir}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dir, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 111, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbListDbNamesConstMeta, - argValues: [dir], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dir, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 111, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbListDbNamesConstMeta, + argValues: [dir], + apiImpl: this, + )); } TaskConstMeta get kCrateApiDbListDbNamesConstMeta => const TaskConstMeta( @@ -3409,22 +3617,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListFolders({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 112, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_folder, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListFoldersConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 112, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_folder, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListFoldersConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountListFoldersConstMeta => const TaskConstMeta( @@ -3434,22 +3641,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListMemos({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 113, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_memo, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListMemosConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 113, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_memo, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListMemosConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountListMemosConstMeta => const TaskConstMeta( @@ -3459,22 +3665,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListNotes({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 114, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_tx_note, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListNotesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 114, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_tx_note, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListNotesConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountListNotesConstMeta => const TaskConstMeta( @@ -3484,22 +3689,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiPluginListPlugins({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 115, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_plugin_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginListPluginsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 115, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_plugin_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginListPluginsConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPluginListPluginsConstMeta => const TaskConstMeta( @@ -3509,47 +3713,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListTxHistory({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 116, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_tx, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListTxHistoryConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 116, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_tx, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListTxHistoryConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => + const TaskConstMeta( debugName: "list_tx_history", argNames: ["c"], ); @override Future> crateApiZsaListZsaHoldings({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 117, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_zsa_holding, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiZsaListZsaHoldingsConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 117, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_zsa_holding, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiZsaListZsaHoldingsConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiZsaListZsaHoldingsConstMeta => const TaskConstMeta( @@ -3558,25 +3761,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountLockNote({required int id, required bool locked, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_bool(locked, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 118, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountLockNoteConstMeta, - argValues: [id, locked, c], - apiImpl: this, + Future crateApiAccountLockNote( + {required int id, required bool locked, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_bool(locked, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 118, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountLockNoteConstMeta, + argValues: [id, locked, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountLockNoteConstMeta => const TaskConstMeta( @@ -3585,76 +3788,77 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountLockRecentNotes({required int height, required int threshold, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_u_32(threshold, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 119, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountLockRecentNotesConstMeta, - argValues: [height, threshold, c], - apiImpl: this, + Future crateApiAccountLockRecentNotes( + {required int height, required int threshold, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_u_32(threshold, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 119, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountLockRecentNotesConstMeta, + argValues: [height, threshold, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountLockRecentNotesConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountLockRecentNotesConstMeta => + const TaskConstMeta( debugName: "lock_recent_notes", argNames: ["height", "threshold", "c"], ); @override Future crateApiAccountMaxSpendable({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 120, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountMaxSpendableConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 120, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountMaxSpendableConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => + const TaskConstMeta( debugName: "max_spendable", argNames: ["c"], ); @override - Future crateApiAccountNewAccount({required NewAccount na, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_new_account(na, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 121, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountNewAccountConstMeta, - argValues: [na, c], - apiImpl: this, + Future crateApiAccountNewAccount( + {required NewAccount na, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_new_account(na, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 121, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountNewAccountConstMeta, + argValues: [na, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountNewAccountConstMeta => const TaskConstMeta( @@ -3664,22 +3868,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayPackTransaction({required PcztPackage pczt}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 122, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPackTransactionConstMeta, - argValues: [pczt], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 122, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPackTransactionConstMeta, + argValues: [pczt], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayPackTransactionConstMeta => const TaskConstMeta( @@ -3688,49 +3891,48 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiPluginParseMemoWithPlugins({required List memoBytes, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(memoBytes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 123, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_memo_section, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginParseMemoWithPluginsConstMeta, - argValues: [memoBytes, c], - apiImpl: this, + Future> crateApiPluginParseMemoWithPlugins( + {required List memoBytes, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(memoBytes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 123, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_memo_section, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPluginParseMemoWithPluginsConstMeta, + argValues: [memoBytes, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiPluginParseMemoWithPluginsConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiPluginParseMemoWithPluginsConstMeta => + const TaskConstMeta( debugName: "parse_memo_with_plugins", argNames: ["memoBytes", "c"], ); @override List? crateApiPayParsePaymentUri({required String uri}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(uri, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_list_recipient, - decodeErrorData: null, - ), - constMeta: kCrateApiPayParsePaymentUriConstMeta, - argValues: [uri], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(uri, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_recipient, + decodeErrorData: null, + ), + constMeta: kCrateApiPayParsePaymentUriConstMeta, + argValues: [uri], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayParsePaymentUriConstMeta => const TaskConstMeta( @@ -3739,25 +3941,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayPrepare({required List recipients, required PaymentOptions options, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - sse_encode_box_autoadd_payment_options(options, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 125, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPrepareConstMeta, - argValues: [recipients, options, c], - apiImpl: this, - ), - ); + Future crateApiPayPrepare( + {required List recipients, + required PaymentOptions options, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + sse_encode_box_autoadd_payment_options(options, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 125, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPrepareConstMeta, + argValues: [recipients, options, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayPrepareConstMeta => const TaskConstMeta( @@ -3766,51 +3970,53 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPayPrepareMigration({required List recipients, required int srcPools, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - sse_encode_u_8(srcPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 126, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPrepareMigrationConstMeta, - argValues: [recipients, srcPools, c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiPayPrepareMigrationConstMeta => const TaskConstMeta( + Future crateApiPayPrepareMigration( + {required List recipients, + required int srcPools, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + sse_encode_u_8(srcPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 126, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPrepareMigrationConstMeta, + argValues: [recipients, srcPools, c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiPayPrepareMigrationConstMeta => + const TaskConstMeta( debugName: "prepare_migration", argNames: ["recipients", "srcPools", "c"], ); @override Future crateApiAccountPrintKeys({required int id, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 127, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountPrintKeysConstMeta, - argValues: [id, c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 127, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountPrintKeysConstMeta, + argValues: [id, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountPrintKeysConstMeta => const TaskConstMeta( @@ -3819,25 +4025,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiDbPutProp({required String key, required String value, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_String(value, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 128, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbPutPropConstMeta, - argValues: [key, value, c], - apiImpl: this, + Future crateApiDbPutProp( + {required String key, required String value, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_String(value, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 128, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiDbPutPropConstMeta, + argValues: [key, value, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiDbPutPropConstMeta => const TaskConstMeta( @@ -3847,124 +4053,125 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiNetworkQueryLwdList({required int coin}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(coin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 129, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_lwd_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkQueryLwdListConstMeta, - argValues: [coin], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(coin, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 129, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_lwd_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkQueryLwdListConstMeta, + argValues: [coin], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => + const TaskConstMeta( debugName: "query_lwd_list", argNames: ["coin"], ); @override Future crateApiAccountReceiversDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 130, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_receivers, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountReceiversDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 130, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_receivers, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountReceiversDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => + const TaskConstMeta( debugName: "receivers_default", argNames: [], ); @override - Receivers crateApiAccountReceiversFromUa({required String ua, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(ua, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_receivers, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountReceiversFromUaConstMeta, - argValues: [ua, c], - apiImpl: this, + Receivers crateApiAccountReceiversFromUa( + {required String ua, required Coin c}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ua, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_receivers, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountReceiversFromUaConstMeta, + argValues: [ua, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountReceiversFromUaConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountReceiversFromUaConstMeta => + const TaskConstMeta( debugName: "receivers_from_ua", argNames: ["ua", "c"], ); @override - Future crateApiAccountRemoveAccount({required int accountId, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(accountId, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 132, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRemoveAccountConstMeta, - argValues: [accountId, c], - apiImpl: this, + Future crateApiAccountRemoveAccount( + {required int accountId, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(accountId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 132, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountRemoveAccountConstMeta, + argValues: [accountId, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountRemoveAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRemoveAccountConstMeta => + const TaskConstMeta( debugName: "remove_account", argNames: ["accountId", "c"], ); @override - Future crateApiPluginRemovePlugin({required String id, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 133, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginRemovePluginConstMeta, - argValues: [id, c], - apiImpl: this, + Future crateApiPluginRemovePlugin( + {required String id, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 133, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPluginRemovePluginConstMeta, + argValues: [id, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPluginRemovePluginConstMeta => const TaskConstMeta( @@ -3973,103 +4180,105 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountRenameCategory({required Category category, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_category(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 134, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRenameCategoryConstMeta, - argValues: [category, c], - apiImpl: this, + Future crateApiAccountRenameCategory( + {required Category category, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_category(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 134, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountRenameCategoryConstMeta, + argValues: [category, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountRenameCategoryConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRenameCategoryConstMeta => + const TaskConstMeta( debugName: "rename_category", argNames: ["category", "c"], ); @override - Future crateApiAccountRenameFolder({required int id, required String name, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 135, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRenameFolderConstMeta, - argValues: [id, name, c], - apiImpl: this, + Future crateApiAccountRenameFolder( + {required int id, required String name, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 135, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountRenameFolderConstMeta, + argValues: [id, name, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountRenameFolderConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountRenameFolderConstMeta => + const TaskConstMeta( debugName: "rename_folder", argNames: ["id", "name", "c"], ); @override - Future crateApiAccountReorderAccount({required int oldPosition, required int newPosition, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(oldPosition, serializer); - sse_encode_u_32(newPosition, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 136, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountReorderAccountConstMeta, - argValues: [oldPosition, newPosition, c], - apiImpl: this, + Future crateApiAccountReorderAccount( + {required int oldPosition, required int newPosition, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(oldPosition, serializer); + sse_encode_u_32(newPosition, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 136, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountReorderAccountConstMeta, + argValues: [oldPosition, newPosition, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountReorderAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountReorderAccountConstMeta => + const TaskConstMeta( debugName: "reorder_account", argNames: ["oldPosition", "newPosition", "c"], ); @override Future crateApiFrostResetSign({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 137, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostResetSignConstMeta, - argValues: [c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 137, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostResetSignConstMeta, + argValues: [c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostResetSignConstMeta => const TaskConstMeta( @@ -4079,23 +4288,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountResetSync({required int id, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 138, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountResetSyncConstMeta, - argValues: [id, c], - apiImpl: this, - ), - ); + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 138, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountResetSyncConstMeta, + argValues: [id, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountResetSyncConstMeta => const TaskConstMeta( @@ -4104,101 +4312,104 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiOpenaliasResolveOpenalias({required String alias, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 139, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasConstMeta, - argValues: [alias, c], - apiImpl: this, + Future crateApiOpenaliasResolveOpenalias( + {required String alias, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 139, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiOpenaliasResolveOpenaliasConstMeta, + argValues: [alias, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasConstMeta => + const TaskConstMeta( debugName: "resolve_openalias", argNames: ["alias", "c"], ); @override - Future crateApiOpenaliasResolveOpenaliasAll({required String alias}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 140, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasAllConstMeta, - argValues: [alias], - apiImpl: this, + Future crateApiOpenaliasResolveOpenaliasAll( + {required String alias}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 140, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiOpenaliasResolveOpenaliasAllConstMeta, + argValues: [alias], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasAllConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasAllConstMeta => + const TaskConstMeta( debugName: "resolve_openalias_all", argNames: ["alias"], ); @override - Future crateApiOpenaliasResolveOpenaliasRaw({required String alias}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 141, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_raw_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasRawConstMeta, - argValues: [alias], - apiImpl: this, + Future crateApiOpenaliasResolveOpenaliasRaw( + {required String alias}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 141, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_raw_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiOpenaliasResolveOpenaliasRawConstMeta, + argValues: [alias], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasRawConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasRawConstMeta => + const TaskConstMeta( debugName: "resolve_openalias_raw", argNames: ["alias"], ); @override - Future crateApiSyncRewindSync({required int height, required int account, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 142, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncRewindSyncConstMeta, - argValues: [height, account, c], - apiImpl: this, + Future crateApiSyncRewindSync( + {required int height, required int account, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 142, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiSyncRewindSyncConstMeta, + argValues: [height, account, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiSyncRewindSyncConstMeta => const TaskConstMeta( @@ -4207,25 +4418,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPaySend({required int height, required List data, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(data, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 143, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPaySendConstMeta, - argValues: [height, data, c], - apiImpl: this, + Future crateApiPaySend( + {required int height, required List data, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(data, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 143, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPaySendConstMeta, + argValues: [height, data, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPaySendConstMeta => const TaskConstMeta( @@ -4234,25 +4445,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiZsaSetAssetName({required PlatformInt64 idAsset, required String name, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_i_64(idAsset, serializer); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 144, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiZsaSetAssetNameConstMeta, - argValues: [idAsset, name, c], - apiImpl: this, + Future crateApiZsaSetAssetName( + {required PlatformInt64 idAsset, required String name, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(idAsset, serializer); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 144, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiZsaSetAssetNameConstMeta, + argValues: [idAsset, name, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiZsaSetAssetNameConstMeta => const TaskConstMeta( @@ -4261,25 +4472,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiFrostSetDkgAddress({required int id, required String address, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(id, serializer); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 145, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostSetDkgAddressConstMeta, - argValues: [id, address, c], - apiImpl: this, + Future crateApiFrostSetDkgAddress( + {required int id, required String address, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(id, serializer); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 145, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiFrostSetDkgAddressConstMeta, + argValues: [id, address, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostSetDkgAddressConstMeta => const TaskConstMeta( @@ -4289,28 +4500,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostSetDkgParams( - {required String name, required int id, required int n, required int t, required int fundingAccount, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_u_8(id, serializer); - sse_encode_u_8(n, serializer); - sse_encode_u_8(t, serializer); - sse_encode_u_32(fundingAccount, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 146, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostSetDkgParamsConstMeta, - argValues: [name, id, n, t, fundingAccount, c], - apiImpl: this, - ), - ); + {required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_u_8(id, serializer); + sse_encode_u_8(n, serializer); + sse_encode_u_8(t, serializer); + sse_encode_u_32(fundingAccount, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 146, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostSetDkgParamsConstMeta, + argValues: [name, id, n, t, fundingAccount, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiFrostSetDkgParamsConstMeta => const TaskConstMeta( @@ -4320,22 +4535,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiInitSetExpertMode({required bool enabled}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_bool(enabled, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitSetExpertModeConstMeta, - argValues: [enabled], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_bool(enabled, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitSetExpertModeConstMeta, + argValues: [enabled], + apiImpl: this, + )); } TaskConstMeta get kCrateApiInitSetExpertModeConstMeta => const TaskConstMeta( @@ -4346,22 +4559,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiInitSetLogStream() { final s = RustStreamSink(); - handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_log_message_Sse(s, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitSetLogStreamConstMeta, - argValues: [s], - apiImpl: this, - ), - ); + handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_log_message_Sse(s, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitSetLogStreamConstMeta, + argValues: [s], + apiImpl: this, + )); return s.stream; } @@ -4371,213 +4582,217 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiPluginSetPluginEnabled({required String id, required bool enabled, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(id, serializer); - sse_encode_bool(enabled, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 149, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginSetPluginEnabledConstMeta, - argValues: [id, enabled, c], - apiImpl: this, + Future crateApiPluginSetPluginEnabled( + {required String id, required bool enabled, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(id, serializer); + sse_encode_bool(enabled, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 149, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPluginSetPluginEnabledConstMeta, + argValues: [id, enabled, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiPluginSetPluginEnabledConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiPluginSetPluginEnabledConstMeta => + const TaskConstMeta( debugName: "set_plugin_enabled", argNames: ["id", "enabled", "c"], ); @override - Future crateApiTransactionSetTxCategory({required int id, int? category, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_box_autoadd_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 150, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetTxCategoryConstMeta, - argValues: [id, category, c], - apiImpl: this, + Future crateApiTransactionSetTxCategory( + {required int id, int? category, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_box_autoadd_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 150, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionSetTxCategoryConstMeta, + argValues: [id, category, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionSetTxCategoryConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetTxCategoryConstMeta => + const TaskConstMeta( debugName: "set_tx_category", argNames: ["id", "category", "c"], ); @override - Future crateApiTransactionSetTxPrice({required int id, double? price, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_box_autoadd_f_64(price, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 151, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetTxPriceConstMeta, - argValues: [id, price, c], - apiImpl: this, + Future crateApiTransactionSetTxPrice( + {required int id, double? price, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_box_autoadd_f_64(price, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 151, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionSetTxPriceConstMeta, + argValues: [id, price, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionSetTxPriceConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetTxPriceConstMeta => + const TaskConstMeta( debugName: "set_tx_price", argNames: ["id", "price", "c"], ); @override - Future crateApiTransactionSetUserMemo({required int idTx, String? memo, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(idTx, serializer); - sse_encode_opt_String(memo, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 152, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetUserMemoConstMeta, - argValues: [idTx, memo, c], - apiImpl: this, + Future crateApiTransactionSetUserMemo( + {required int idTx, String? memo, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(idTx, serializer); + sse_encode_opt_String(memo, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 152, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiTransactionSetUserMemoConstMeta, + argValues: [idTx, memo, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiTransactionSetUserMemoConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiTransactionSetUserMemoConstMeta => + const TaskConstMeta( debugName: "set_user_memo", argNames: ["idTx", "memo", "c"], ); @override Future crateApiAccountShowLedgerSaplingAddress({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 153, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountShowLedgerSaplingAddressConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountShowLedgerSaplingAddressConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 153, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountShowLedgerSaplingAddressConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountShowLedgerSaplingAddressConstMeta => + const TaskConstMeta( debugName: "show_ledger_sapling_address", argNames: ["c"], ); @override - Future crateApiAccountShowLedgerTransparentAddress({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 154, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountShowLedgerTransparentAddressConstMeta, - argValues: [c], - apiImpl: this, + Future crateApiAccountShowLedgerTransparentAddress( + {required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 154, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountShowLedgerTransparentAddressConstMeta, + argValues: [c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountShowLedgerTransparentAddressConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountShowLedgerTransparentAddressConstMeta => + const TaskConstMeta( debugName: "show_ledger_transparent_address", argNames: ["c"], ); @override - Stream crateApiAccountSignLedgerTransaction({required PcztPackage package, required Coin c}) { + Stream crateApiAccountSignLedgerTransaction( + {required PcztPackage package, required Coin c}) { final sink = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_signing_event_Sse(sink, serializer); - sse_encode_box_autoadd_pczt_package(package, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 155, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountSignLedgerTransactionConstMeta, - argValues: [sink, package, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_signing_event_Sse(sink, serializer); + sse_encode_box_autoadd_pczt_package(package, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 155, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountSignLedgerTransactionConstMeta, + argValues: [sink, package, c], + apiImpl: this, + ))); return sink.stream; } - TaskConstMeta get kCrateApiAccountSignLedgerTransactionConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountSignLedgerTransactionConstMeta => + const TaskConstMeta( debugName: "sign_ledger_transaction", argNames: ["sink", "package", "c"], ); @override - Future crateApiPaySignTransaction({required PcztPackage pczt, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 156, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPaySignTransactionConstMeta, - argValues: [pczt, c], - apiImpl: this, + Future crateApiPaySignTransaction( + {required PcztPackage pczt, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 156, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiPaySignTransactionConstMeta, + argValues: [pczt, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPaySignTransactionConstMeta => const TaskConstMeta( @@ -4587,51 +4802,55 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMigrateStepMigration({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 157, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_migration_event, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateStepMigrationConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 157, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_migration_event, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateStepMigrationConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => + const TaskConstMeta( debugName: "step_migration", argNames: ["c"], ); @override - Future crateApiPayStorePendingTx({required int height, required List txid, double? price, int? category, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(txid, serializer); - sse_encode_opt_box_autoadd_f_64(price, serializer); - sse_encode_opt_box_autoadd_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 158, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayStorePendingTxConstMeta, - argValues: [height, txid, price, category, c], - apiImpl: this, - ), - ); + Future crateApiPayStorePendingTx( + {required int height, + required List txid, + double? price, + int? category, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(txid, serializer); + sse_encode_opt_box_autoadd_f_64(price, serializer); + sse_encode_opt_box_autoadd_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 158, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayStorePendingTxConstMeta, + argValues: [height, txid, price, category, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayStorePendingTxConstMeta => const TaskConstMeta( @@ -4649,58 +4868,71 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required bool fast, required Coin c}) { final progress = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_sync_progress_Sse(progress, serializer); - sse_encode_list_prim_u_32_loose(accounts, serializer); - sse_encode_u_32(currentHeight, serializer); - sse_encode_u_32(actionsPerSync, serializer); - sse_encode_u_32(transparentLimit, serializer); - sse_encode_u_32(checkpointAge, serializer); - sse_encode_bool(fast, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 159, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncSynchronizeConstMeta, - argValues: [progress, accounts, currentHeight, actionsPerSync, transparentLimit, checkpointAge, fast, c], - apiImpl: this, - ), - ), - ); + unawaited(handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_sync_progress_Sse(progress, serializer); + sse_encode_list_prim_u_32_loose(accounts, serializer); + sse_encode_u_32(currentHeight, serializer); + sse_encode_u_32(actionsPerSync, serializer); + sse_encode_u_32(transparentLimit, serializer); + sse_encode_u_32(checkpointAge, serializer); + sse_encode_bool(fast, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 159, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncSynchronizeConstMeta, + argValues: [ + progress, + accounts, + currentHeight, + actionsPerSync, + transparentLimit, + checkpointAge, + fast, + c + ], + apiImpl: this, + ))); return progress.stream; } TaskConstMeta get kCrateApiSyncSynchronizeConstMeta => const TaskConstMeta( debugName: "synchronize", - argNames: ["progress", "accounts", "currentHeight", "actionsPerSync", "transparentLimit", "checkpointAge", "fast", "c"], + argNames: [ + "progress", + "accounts", + "currentHeight", + "actionsPerSync", + "transparentLimit", + "checkpointAge", + "fast", + "c" + ], ); @override TxPlan crateApiPayToPlan({required PcztPackage package, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(package, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_plan, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayToPlanConstMeta, - argValues: [package, c], - apiImpl: this, - ), - ); + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(package, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_plan, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayToPlanConstMeta, + argValues: [package, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiPayToPlanConstMeta => const TaskConstMeta( @@ -4710,195 +4942,194 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountToggleAllNotes({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 161, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountToggleAllNotesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 161, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountToggleAllNotesConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => + const TaskConstMeta( debugName: "toggle_all_notes", argNames: ["c"], ); @override - void crateApiOpenaliasTryValidateZcashAddress({required String address, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasTryValidateZcashAddressConstMeta, - argValues: [address, c], - apiImpl: this, + void crateApiOpenaliasTryValidateZcashAddress( + {required String address, required Coin c}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiOpenaliasTryValidateZcashAddressConstMeta, + argValues: [address, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiOpenaliasTryValidateZcashAddressConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasTryValidateZcashAddressConstMeta => + const TaskConstMeta( debugName: "try_validate_zcash_address", argNames: ["address", "c"], ); @override Future crateApiAccountTxAccountDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 163, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_account, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxAccountDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 163, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_account, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxAccountDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => + const TaskConstMeta( debugName: "tx_account_default", argNames: [], ); @override Future crateApiAccountTxMemoDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 164, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_memo, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxMemoDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 164, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_memo, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxMemoDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => + const TaskConstMeta( debugName: "tx_memo_default", argNames: [], ); @override Future crateApiAccountTxNoteDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 165, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_note, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxNoteDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 165, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_note, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxNoteDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => + const TaskConstMeta( debugName: "tx_note_default", argNames: [], ); @override Future crateApiAccountTxOutputDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 166, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_output, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxOutputDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 166, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_output, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxOutputDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => + const TaskConstMeta( debugName: "tx_output_default", argNames: [], ); @override Future crateApiAccountTxSpendDefault() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 167, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_spend, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxSpendDefaultConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 167, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_spend, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxSpendDefaultConstMeta, + argValues: [], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => + const TaskConstMeta( debugName: "tx_spend_default", argNames: [], ); @override - String crateApiAccountUaFromUfvk({required String ufvk, int? di, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(ufvk, serializer); - sse_encode_opt_box_autoadd_u_32(di, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUaFromUfvkConstMeta, - argValues: [ufvk, di, c], - apiImpl: this, + String crateApiAccountUaFromUfvk( + {required String ufvk, int? di, required Coin c}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ufvk, serializer); + sse_encode_opt_box_autoadd_u_32(di, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountUaFromUfvkConstMeta, + argValues: [ufvk, di, c], + apiImpl: this, + )); } TaskConstMeta get kCrateApiAccountUaFromUfvkConstMeta => const TaskConstMeta( @@ -4908,188 +5139,198 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountUnlockAllNotes({required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 169, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUnlockAllNotesConstMeta, - argValues: [c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 169, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountUnlockAllNotesConstMeta, + argValues: [c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => + const TaskConstMeta( debugName: "unlock_all_notes", argNames: ["c"], ); @override Future crateApiPayUnpackTransaction({required List bytes}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 170, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayUnpackTransactionConstMeta, - argValues: [bytes], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => const TaskConstMeta( + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(bytes, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 170, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayUnpackTransactionConstMeta, + argValues: [bytes], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => + const TaskConstMeta( debugName: "unpack_transaction", argNames: ["bytes"], ); @override - Future crateApiAccountUpdateAccount({required AccountUpdate update, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_account_update(update, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 171, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUpdateAccountConstMeta, - argValues: [update, c], - apiImpl: this, + Future crateApiAccountUpdateAccount( + {required AccountUpdate update, required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_account_update(update, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 171, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, ), - ); + constMeta: kCrateApiAccountUpdateAccountConstMeta, + argValues: [update, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiAccountUpdateAccountConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiAccountUpdateAccountConstMeta => + const TaskConstMeta( debugName: "update_account", argNames: ["update", "c"], ); @override - Future crateApiContactsUpdateContact({required int id, String? name, List? addresses, String? notes, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_String(name, serializer); - sse_encode_opt_list_String(addresses, serializer); - sse_encode_opt_String(notes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 172, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsUpdateContactConstMeta, - argValues: [id, name, addresses, notes, c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiContactsUpdateContactConstMeta => const TaskConstMeta( + Future crateApiContactsUpdateContact( + {required int id, + String? name, + List? addresses, + String? notes, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_String(name, serializer); + sse_encode_opt_list_String(addresses, serializer); + sse_encode_opt_String(notes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 172, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsUpdateContactConstMeta, + argValues: [id, name, addresses, notes, c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiContactsUpdateContactConstMeta => + const TaskConstMeta( debugName: "update_contact", argNames: ["id", "name", "addresses", "notes", "c"], ); @override - Future crateApiTransactionUpdateHistoricalPrices({required String currency, required double exchangeRate, required Coin c}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(currency, serializer); - sse_encode_f_64(exchangeRate, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 173, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionUpdateHistoricalPricesConstMeta, - argValues: [currency, exchangeRate, c], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiTransactionUpdateHistoricalPricesConstMeta => const TaskConstMeta( + Future crateApiTransactionUpdateHistoricalPrices( + {required String currency, + required double exchangeRate, + required Coin c}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(currency, serializer); + sse_encode_f_64(exchangeRate, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 173, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionUpdateHistoricalPricesConstMeta, + argValues: [currency, exchangeRate, c], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiTransactionUpdateHistoricalPricesConstMeta => + const TaskConstMeta( debugName: "update_historical_prices", argNames: ["currency", "exchangeRate", "c"], ); @override bool crateApiOpenaliasValidateOpenaliasName({required String alias}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiOpenaliasValidateOpenaliasNameConstMeta, - argValues: [alias], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiOpenaliasValidateOpenaliasNameConstMeta => const TaskConstMeta( + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiOpenaliasValidateOpenaliasNameConstMeta, + argValues: [alias], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiOpenaliasValidateOpenaliasNameConstMeta => + const TaskConstMeta( debugName: "validate_openalias_name", argNames: ["alias"], ); @override - bool crateApiOpenaliasValidateZcashAddress({required String address, required Coin c}) { - return handler.executeSync( - SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 175)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiOpenaliasValidateZcashAddressConstMeta, - argValues: [address, c], - apiImpl: this, + bool crateApiOpenaliasValidateZcashAddress( + {required String address, required Coin c}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 175)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, ), - ); + constMeta: kCrateApiOpenaliasValidateZcashAddressConstMeta, + argValues: [address, c], + apiImpl: this, + )); } - TaskConstMeta get kCrateApiOpenaliasValidateZcashAddressConstMeta => const TaskConstMeta( + TaskConstMeta get kCrateApiOpenaliasValidateZcashAddressConstMeta => + const TaskConstMeta( debugName: "validate_zcash_address", argNames: ["address", "c"], ); - Future Function(int, dynamic) encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) raw) { + Future Function(int, dynamic) + encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr Function(Uint8List) raw) { return (callId, rawArg0) async { final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); @@ -5113,37 +5354,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final output = serializer.intoRaw(); generalizedFrbRustBinding.dartFnDeliverOutput( - callId: callId, - ptr: output.ptr, - rustVecLen: output.rustVecLen, - dataLen: output.dataLen, - ); + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen); }; } - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_DartVault => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_DartVault => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_DartVault => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_Mempool => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_Mempool => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_Mempool => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_Mempool => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_NoteMigration => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_NoteMigration => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_NoteMigration => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_NoteMigration => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_TransparentScanner => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_TransparentScanner => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_TransparentScanner => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_TransparentScanner => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw) { @@ -5152,61 +5400,81 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { + DartVault + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { + Mempool + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { + TransparentScanner + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { + Mempool + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { + TransparentScanner + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { + DartVault + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { + TransparentScanner + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @protected - FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw) { + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(''); } @@ -5218,25 +5486,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw) { + DartVault + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List); } @protected - Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw) { + Mempool + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List); } @protected - NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw) { + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List); } @protected - TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw) { + TransparentScanner + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List); } @@ -5254,37 +5530,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - RustStreamSink dco_decode_StreamSink_log_message_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_log_message_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_mempool_msg_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_migration_status_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_signing_event_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_signing_status_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_sync_progress_Sse( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @@ -5299,7 +5581,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Account dco_decode_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 20) throw Exception('unexpected arr length: expect 20 but see ${arr.length}'); + if (arr.length != 20) + throw Exception('unexpected arr length: expect 20 but see ${arr.length}'); return Account( coin: dco_decode_u_8(arr[0]), id: dco_decode_u_32(arr[1]), @@ -5328,7 +5611,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { AccountUpdate dco_decode_account_update(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return AccountUpdate( coin: dco_decode_u_8(arr[0]), id: dco_decode_u_32(arr[1]), @@ -5345,7 +5629,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Addresses dco_decode_addresses(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 5) throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); return Addresses( taddr: dco_decode_opt_String(arr[0]), saddr: dco_decode_opt_String(arr[1]), @@ -5473,7 +5758,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Category dco_decode_category(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Category( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5485,7 +5771,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Coin dco_decode_coin(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) + throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return Coin.raw( coin: dco_decode_u_8(arr[0]), account: dco_decode_u_32(arr[1]), @@ -5501,7 +5788,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Contact dco_decode_contact(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return Contact( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5514,7 +5802,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ContactMatch dco_decode_contact_match(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return ContactMatch( contact: dco_decode_contact(arr[0]), matchedAddress: dco_decode_String(arr[1]), @@ -5525,7 +5814,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { DbAccountPreview dco_decode_db_account_preview(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return DbAccountPreview( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5565,7 +5855,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ExchangeRate dco_decode_exchange_rate(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return ExchangeRate( fromPrice: dco_decode_f_64(arr[0]), toPrice: dco_decode_f_64(arr[1]), @@ -5584,7 +5875,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Folder dco_decode_folder(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return Folder( id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5595,7 +5887,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { FrostParams dco_decode_frost_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return FrostParams( id: dco_decode_u_8(arr[0]), n: dco_decode_u_8(arr[1]), @@ -5607,7 +5900,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { FrostSignParams dco_decode_frost_sign_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return FrostSignParams( account: dco_decode_u_32(arr[0]), coordinator: dco_decode_u_8(arr[1]), @@ -5772,9 +6066,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw) { + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return (raw as List).map(dco_decode_record_string_f_64_bool).toList(); + return (raw as List) + .map(dco_decode_record_string_f_64_bool) + .toList(); } @protected @@ -5847,7 +6144,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { LogMessage dco_decode_log_message(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return LogMessage( level: dco_decode_u_8(arr[0]), message: dco_decode_String(arr[1]), @@ -5859,7 +6157,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { LWDInfo dco_decode_lwd_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) + throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return LWDInfo( url: dco_decode_String(arr[0]), isTor: dco_decode_bool(arr[1]), @@ -5875,7 +6174,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Memo dco_decode_memo(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) + throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return Memo( id: dco_decode_u_32(arr[0]), idTx: dco_decode_u_32(arr[1]), @@ -5894,7 +6194,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoCell dco_decode_memo_cell(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return MemoCell( cellType: dco_decode_String(arr[0]), value: dco_decode_String(arr[1]), @@ -5905,7 +6206,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoRow dco_decode_memo_row(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) + throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return MemoRow( cells: dco_decode_list_memo_cell(arr[0]), ); @@ -5915,7 +6217,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MemoSection dco_decode_memo_section(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return MemoSection( title: dco_decode_String(arr[0]), headers: dco_decode_list_String(arr[1]), @@ -5927,7 +6230,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolAmount dco_decode_mempool_amount(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return MempoolAmount( account: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5956,7 +6260,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolNote dco_decode_mempool_note(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 9) throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + if (arr.length != 9) + throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); return MempoolNote( account: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -5974,7 +6279,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MempoolTx dco_decode_mempool_tx(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return MempoolTx( txid: dco_decode_String(arr[0]), amounts: dco_decode_list_mempool_amount(arr[1]), @@ -6012,7 +6318,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { MigrationStatus dco_decode_migration_status(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) + throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return MigrationStatus( phase: dco_decode_String(arr[0]), splitFees: dco_decode_u_64(arr[1]), @@ -6031,7 +6338,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NewAccount dco_decode_new_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 13) throw Exception('unexpected arr length: expect 13 but see ${arr.length}'); + if (arr.length != 13) + throw Exception('unexpected arr length: expect 13 but see ${arr.length}'); return NewAccount( icon: dco_decode_opt_list_prim_u_8_strict(arr[0]), name: dco_decode_String(arr[1]), @@ -6053,7 +6361,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { OpenAliasResolution dco_decode_open_alias_resolution(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return OpenAliasResolution( recipients: dco_decode_list_recipient(arr[0]), dnssecStatus: dco_decode_String(arr[1]), @@ -6142,7 +6451,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PaymentOptions dco_decode_payment_options(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return PaymentOptions( srcPools: dco_decode_u_8(arr[0]), recipientPaysFee: dco_decode_bool(arr[1]), @@ -6155,7 +6465,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PcztPackage dco_decode_pczt_package(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); + if (arr.length != 10) + throw Exception('unexpected arr length: expect 10 but see ${arr.length}'); return PcztPackage( pczt: dco_decode_list_prim_u_8_strict(arr[0]), nSpends: dco_decode_usize_array_4(arr[1]), @@ -6174,7 +6485,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PluginInfo dco_decode_plugin_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return PluginInfo( id: dco_decode_String(arr[0]), name: dco_decode_String(arr[1]), @@ -6191,7 +6503,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { PoolBalance dco_decode_pool_balance(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) + throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return PoolBalance( field0: dco_decode_list_prim_u_64_strict(arr[0]), ); @@ -6201,7 +6514,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RaptorQParams dco_decode_raptor_q_params(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return RaptorQParams( version: dco_decode_u_16(arr[0]), ecLevel: dco_decode_u_8(arr[1]), @@ -6213,7 +6527,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RawOpenAliasResolution dco_decode_raw_open_alias_resolution(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return RawOpenAliasResolution( records: dco_decode_list_String(arr[0]), dnssecStatus: dco_decode_String(arr[1]), @@ -6224,7 +6539,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Receivers dco_decode_receivers(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Receivers( taddr: dco_decode_opt_String(arr[0]), saddr: dco_decode_opt_String(arr[1]), @@ -6236,7 +6552,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Recipient dco_decode_recipient(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return Recipient( address: dco_decode_String(arr[0]), amount: dco_decode_u_64(arr[1]), @@ -6280,7 +6597,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RestoredAccount dco_decode_restored_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return RestoredAccount( timestamp: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1]), @@ -6295,7 +6613,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SaplingParamsStatus dco_decode_sapling_params_status(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); + if (arr.length != 1) + throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); return SaplingParamsStatus( downloaded: dco_decode_bool(arr[0]), ); @@ -6305,7 +6624,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Seed dco_decode_seed(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return Seed( mnemonic: dco_decode_String(arr[0]), phrase: dco_decode_String(arr[1]), @@ -6365,7 +6685,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncHeight dco_decode_sync_height(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return SyncHeight( pool: dco_decode_u_8(arr[0]), height: dco_decode_u_32(arr[1]), @@ -6377,7 +6698,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncProgress dco_decode_sync_progress(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); return SyncProgress( height: dco_decode_u_32(arr[0]), time: dco_decode_u_32(arr[1]), @@ -6388,7 +6710,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TAddressTxCount dco_decode_t_address_tx_count(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + if (arr.length != 7) + throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); return TAddressTxCount( pool: dco_decode_u_8(arr[0]), address: dco_decode_String(arr[1]), @@ -6404,7 +6727,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Tx dco_decode_tx(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 14) throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); + if (arr.length != 14) + throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); return Tx( id: dco_decode_u_32(arr[0]), txid: dco_decode_list_prim_u_8_strict(arr[1]), @@ -6427,7 +6751,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxAccount dco_decode_tx_account(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 12) throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); + if (arr.length != 12) + throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); return TxAccount( id: dco_decode_u_32(arr[0]), account: dco_decode_u_32(arr[1]), @@ -6448,7 +6773,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxMemo dco_decode_tx_memo(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 5) throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); return TxMemo( note: dco_decode_opt_box_autoadd_u_32(arr[0]), output: dco_decode_opt_box_autoadd_u_32(arr[1]), @@ -6462,7 +6788,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxNote dco_decode_tx_note(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 12) throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); + if (arr.length != 12) + throw Exception('unexpected arr length: expect 12 but see ${arr.length}'); return TxNote( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -6483,7 +6810,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxOutput dco_decode_tx_output(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxOutput( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -6498,7 +6826,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlan dco_decode_tx_plan(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxPlan( height: dco_decode_u_32(arr[0]), inputs: dco_decode_list_tx_plan_in(arr[1]), @@ -6513,7 +6842,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlanIn dco_decode_tx_plan_in(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return TxPlanIn( pool: dco_decode_u_8(arr[0]), amount: dco_decode_opt_box_autoadd_u_64(arr[1]), @@ -6525,7 +6855,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxPlanOut dco_decode_tx_plan_out(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); return TxPlanOut( pool: dco_decode_u_8(arr[0]), amount: dco_decode_u_64(arr[1]), @@ -6538,7 +6869,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { TxSpend dco_decode_tx_spend(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); return TxSpend( id: dco_decode_u_32(arr[0]), pool: dco_decode_u_8(arr[1]), @@ -6595,7 +6927,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ZsaHolding dco_decode_zsa_holding(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); return ZsaHolding( idAsset: dco_decode_i_64(arr[0]), assetDescHash: dco_decode_list_prim_u_8_strict(arr[1]), @@ -6616,57 +6949,84 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { + DartVault + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { + Mempool + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { + TransparentScanner + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { + Mempool + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { + TransparentScanner + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { + DartVault + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { + TransparentScanner + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected @@ -6677,73 +7037,93 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer) { + DartVault + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return DartVaultImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return DartVaultImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer) { + Mempool + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return MempoolImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return MempoolImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer) { + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return NoteMigrationImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return NoteMigrationImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer) { + TransparentScanner + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs - return TransparentScannerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + return TransparentScannerImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } @protected - RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_dkg_status_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_log_message_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_migration_status_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_signing_event_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_signing_status_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_sync_progress_Sse( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @@ -6813,7 +7193,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_hidden = sse_decode_opt_box_autoadd_bool(deserializer); var var_enabled = sse_decode_opt_box_autoadd_bool(deserializer); return AccountUpdate( - coin: var_coin, id: var_id, name: var_name, icon: var_icon, birth: var_birth, folder: var_folder, hidden: var_hidden, enabled: var_enabled); + coin: var_coin, + id: var_id, + name: var_name, + icon: var_icon, + birth: var_birth, + folder: var_folder, + hidden: var_hidden, + enabled: var_enabled); } @protected @@ -6824,7 +7211,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_oaddr = sse_decode_opt_String(deserializer); var var_ua = sse_decode_opt_String(deserializer); var var_diversifierIndex = sse_decode_u_32(deserializer); - return Addresses(taddr: var_taddr, saddr: var_saddr, oaddr: var_oaddr, ua: var_ua, diversifierIndex: var_diversifierIndex); + return Addresses( + taddr: var_taddr, + saddr: var_saddr, + oaddr: var_oaddr, + ua: var_ua, + diversifierIndex: var_diversifierIndex); } @protected @@ -6834,7 +7226,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer) { + AccountUpdate sse_decode_box_autoadd_account_update( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_account_update(deserializer)); } @@ -6864,7 +7257,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - FrostParams sse_decode_box_autoadd_frost_params(SseDeserializer deserializer) { + FrostParams sse_decode_box_autoadd_frost_params( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_frost_params(deserializer)); } @@ -6894,19 +7288,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer) { + PaymentOptions sse_decode_box_autoadd_payment_options( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_payment_options(deserializer)); } @protected - PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer) { + PcztPackage sse_decode_box_autoadd_pczt_package( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_pczt_package(deserializer)); } @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer) { + RaptorQParams sse_decode_box_autoadd_raptor_q_params( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_raptor_q_params(deserializer)); } @@ -6918,7 +7315,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer) { + SigningEvent sse_decode_box_autoadd_signing_event( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_signing_event(deserializer)); } @@ -6961,7 +7359,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_useTor = sse_decode_bool(deserializer); var var_proxy = sse_decode_String(deserializer); return Coin.raw( - coin: var_coin, account: var_account, dbFilepath: var_dbFilepath, url: var_url, serverType: var_serverType, useTor: var_useTor, proxy: var_proxy); + coin: var_coin, + account: var_account, + dbFilepath: var_dbFilepath, + url: var_url, + serverType: var_serverType, + useTor: var_useTor, + proxy: var_proxy); } @protected @@ -6971,7 +7375,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_name = sse_decode_String(deserializer); var var_addresses = sse_decode_list_String(deserializer); var var_notes = sse_decode_String(deserializer); - return Contact(id: var_id, name: var_name, addresses: var_addresses, notes: var_notes); + return Contact( + id: var_id, name: var_name, addresses: var_addresses, notes: var_notes); } @protected @@ -6979,7 +7384,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs var var_contact = sse_decode_contact(deserializer); var var_matchedAddress = sse_decode_String(deserializer); - return ContactMatch(contact: var_contact, matchedAddress: var_matchedAddress); + return ContactMatch( + contact: var_contact, matchedAddress: var_matchedAddress); } @protected @@ -7026,7 +7432,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_toPrice = sse_decode_f_64(deserializer); var var_fromCurrency = sse_decode_String(deserializer); var var_toCurrency = sse_decode_String(deserializer); - return ExchangeRate(fromPrice: var_fromPrice, toPrice: var_toPrice, fromCurrency: var_fromCurrency, toCurrency: var_toCurrency); + return ExchangeRate( + fromPrice: var_fromPrice, + toPrice: var_toPrice, + fromCurrency: var_fromCurrency, + toCurrency: var_toCurrency); } @protected @@ -7058,7 +7468,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_account = sse_decode_u_32(deserializer); var var_coordinator = sse_decode_u_8(deserializer); var var_fundingAccount = sse_decode_u_32(deserializer); - return FrostSignParams(account: var_account, coordinator: var_coordinator, fundingAccount: var_fundingAccount); + return FrostSignParams( + account: var_account, + coordinator: var_coordinator, + fundingAccount: var_fundingAccount); } @protected @@ -7128,7 +7541,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_contact_match(SseDeserializer deserializer) { + List sse_decode_list_contact_match( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7140,7 +7554,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_db_account_preview(SseDeserializer deserializer) { + List sse_decode_list_db_account_preview( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7164,7 +7579,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer) { + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7236,7 +7652,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_mempool_amount(SseDeserializer deserializer) { + List sse_decode_list_mempool_amount( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7326,7 +7743,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer) { + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7338,7 +7756,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer) { + List<(int, double)> sse_decode_list_record_u_32_f_64( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7350,7 +7769,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_restored_account(SseDeserializer deserializer) { + List sse_decode_list_restored_account( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7362,7 +7782,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_t_address_tx_count(SseDeserializer deserializer) { + List sse_decode_list_t_address_tx_count( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -7488,7 +7909,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_uptime = sse_decode_u_32(deserializer); var var_version = sse_decode_String(deserializer); var var_ping = sse_decode_u_32(deserializer); - return LWDInfo(url: var_url, isTor: var_isTor, height: var_height, status: var_status, uptime: var_uptime, version: var_version, ping: var_ping); + return LWDInfo( + url: var_url, + isTor: var_isTor, + height: var_height, + status: var_status, + uptime: var_uptime, + version: var_version, + ping: var_ping); } @protected @@ -7547,7 +7975,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_account = sse_decode_u_32(deserializer); var var_name = sse_decode_String(deserializer); var var_value = sse_decode_i_64(deserializer); - return MempoolAmount(account: var_account, name: var_name, value: var_value); + return MempoolAmount( + account: var_account, name: var_name, value: var_value); } @protected @@ -7598,7 +8027,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_amounts = sse_decode_list_mempool_amount(deserializer); var var_notes = sse_decode_list_mempool_note(deserializer); var var_size = sse_decode_u_32(deserializer); - return MempoolTx(txid: var_txid, amounts: var_amounts, notes: var_notes, size: var_size); + return MempoolTx( + txid: var_txid, amounts: var_amounts, notes: var_notes, size: var_size); } @protected @@ -7684,11 +8114,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer) { + OpenAliasResolution sse_decode_open_alias_resolution( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_recipients = sse_decode_list_recipient(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); - return OpenAliasResolution(recipients: var_recipients, dnssecStatus: var_dnssecStatus); + return OpenAliasResolution( + recipients: var_recipients, dnssecStatus: var_dnssecStatus); } @protected @@ -7725,7 +8157,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer) { + FrostParams? sse_decode_opt_box_autoadd_frost_params( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { @@ -7841,7 +8274,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_recipientPaysFee = sse_decode_bool(deserializer); var var_smartTransparent = sse_decode_bool(deserializer); var var_category = sse_decode_opt_box_autoadd_u_32(deserializer); - return PaymentOptions(srcPools: var_srcPools, recipientPaysFee: var_recipientPaysFee, smartTransparent: var_smartTransparent, category: var_category); + return PaymentOptions( + srcPools: var_srcPools, + recipientPaysFee: var_recipientPaysFee, + smartTransparent: var_smartTransparent, + category: var_category); } @protected @@ -7905,15 +8342,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_version = sse_decode_u_16(deserializer); var var_ecLevel = sse_decode_u_8(deserializer); var var_repair = sse_decode_u_32(deserializer); - return RaptorQParams(version: var_version, ecLevel: var_ecLevel, repair: var_repair); + return RaptorQParams( + version: var_version, ecLevel: var_ecLevel, repair: var_repair); } @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer) { + RawOpenAliasResolution sse_decode_raw_open_alias_resolution( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_records = sse_decode_list_String(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); - return RawOpenAliasResolution(records: var_records, dnssecStatus: var_dnssecStatus); + return RawOpenAliasResolution( + records: var_records, dnssecStatus: var_dnssecStatus); } @protected @@ -7948,7 +8388,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer) { + (String, double, bool) sse_decode_record_string_f_64_bool( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_field0 = sse_decode_String(deserializer); var var_field1 = sse_decode_f_64(deserializer); @@ -7974,11 +8415,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_useInternal = sse_decode_bool(deserializer); var var_birthHeight = sse_decode_u_32(deserializer); return RestoredAccount( - timestamp: var_timestamp, name: var_name, seed: var_seed, aindex: var_aindex, useInternal: var_useInternal, birthHeight: var_birthHeight); + timestamp: var_timestamp, + name: var_name, + seed: var_seed, + aindex: var_aindex, + useInternal: var_useInternal, + birthHeight: var_birthHeight); } @protected - SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer) { + SaplingParamsStatus sse_decode_sapling_params_status( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_downloaded = sse_decode_bool(deserializer); return SaplingParamsStatus(downloaded: var_downloaded); @@ -8070,7 +8517,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_txCount = sse_decode_u_32(deserializer); var var_time = sse_decode_u_32(deserializer); return TAddressTxCount( - pool: var_pool, address: var_address, scope: var_scope, dindex: var_dindex, amount: var_amount, txCount: var_txCount, time: var_time); + pool: var_pool, + address: var_address, + scope: var_scope, + dindex: var_dindex, + amount: var_amount, + txCount: var_txCount, + time: var_time); } @protected @@ -8145,7 +8598,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_pool = sse_decode_u_8(deserializer); var var_memo = sse_decode_opt_String(deserializer); var var_memoBytes = sse_decode_list_prim_u_8_strict(deserializer); - return TxMemo(note: var_note, output: var_output, pool: var_pool, memo: var_memo, memoBytes: var_memoBytes); + return TxMemo( + note: var_note, + output: var_output, + pool: var_pool, + memo: var_memo, + memoBytes: var_memoBytes); } @protected @@ -8187,7 +8645,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_value = sse_decode_u_64(deserializer); var var_address = sse_decode_String(deserializer); var var_contactName = sse_decode_opt_String(deserializer); - return TxOutput(id: var_id, pool: var_pool, height: var_height, value: var_value, address: var_address, contactName: var_contactName); + return TxOutput( + id: var_id, + pool: var_pool, + height: var_height, + value: var_value, + address: var_address, + contactName: var_contactName); } @protected @@ -8199,7 +8663,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_fee = sse_decode_u_64(deserializer); var var_canSign = sse_decode_bool(deserializer); var var_canBroadcast = sse_decode_bool(deserializer); - return TxPlan(height: var_height, inputs: var_inputs, outputs: var_outputs, fee: var_fee, canSign: var_canSign, canBroadcast: var_canBroadcast); + return TxPlan( + height: var_height, + inputs: var_inputs, + outputs: var_outputs, + fee: var_fee, + canSign: var_canSign, + canBroadcast: var_canBroadcast); } @protected @@ -8208,7 +8678,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_pool = sse_decode_u_8(deserializer); var var_amount = sse_decode_opt_box_autoadd_u_64(deserializer); var var_assetName = sse_decode_String(deserializer); - return TxPlanIn(pool: var_pool, amount: var_amount, assetName: var_assetName); + return TxPlanIn( + pool: var_pool, amount: var_amount, assetName: var_assetName); } @protected @@ -8218,7 +8689,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_amount = sse_decode_u_64(deserializer); var var_address = sse_decode_String(deserializer); var var_assetName = sse_decode_String(deserializer); - return TxPlanOut(pool: var_pool, amount: var_amount, address: var_address, assetName: var_assetName); + return TxPlanOut( + pool: var_pool, + amount: var_amount, + address: var_address, + assetName: var_assetName); } @protected @@ -8230,7 +8705,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_value = sse_decode_u_64(deserializer); var var_idAsset = sse_decode_opt_box_autoadd_u_32(deserializer); var var_assetDisplay = sse_decode_String(deserializer); - return TxSpend(id: var_id, pool: var_pool, height: var_height, value: var_value, idAsset: var_idAsset, assetDisplay: var_assetDisplay); + return TxSpend( + id: var_id, + pool: var_pool, + height: var_height, + value: var_value, + idAsset: var_idAsset, + assetDisplay: var_assetDisplay); } @protected @@ -8298,213 +8779,258 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer) { + void sse_encode_AnyhowException( + AnyhowException self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.message, serializer); } @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize( + (self as DartVaultImpl).frbInternalSseEncode(move: true), serializer); } @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize( + (self as MempoolImpl).frbInternalSseEncode(move: true), serializer); } @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: true), + serializer); } @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: true), serializer); + sse_encode_usize( + (self as TransparentScannerImpl).frbInternalSseEncode(move: true), + serializer); } @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize( + (self as MempoolImpl).frbInternalSseEncode(move: false), serializer); } @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize( + (self as TransparentScannerImpl).frbInternalSseEncode(move: false), + serializer); } @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize( + (self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); } @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: false), + serializer); } @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer) { + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: false), serializer); + sse_encode_usize( + (self as TransparentScannerImpl).frbInternalSseEncode(move: false), + serializer); } @protected - void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer) { + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr Function(Uint8List) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_DartOpaque(encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(self), serializer); + sse_encode_DartOpaque( + encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + self), + serializer); } @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_isize(PlatformPointerUtil.ptrToPlatformInt64(encodeDartOpaque(self, portManager.dartHandlerPort, generalizedFrbRustBinding)), serializer); + sse_encode_isize( + PlatformPointerUtil.ptrToPlatformInt64(encodeDartOpaque( + self, portManager.dartHandlerPort, generalizedFrbRustBinding)), + serializer); } @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer) { + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as DartVaultImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize( + (self as DartVaultImpl).frbInternalSseEncode(move: null), serializer); } @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer) { + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as MempoolImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize( + (self as MempoolImpl).frbInternalSseEncode(move: null), serializer); } @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer) { + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as NoteMigrationImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize( + (self as NoteMigrationImpl).frbInternalSseEncode(move: null), + serializer); } @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer) { + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as TransparentScannerImpl).frbInternalSseEncode(move: null), serializer); + sse_encode_usize( + (self as TransparentScannerImpl).frbInternalSseEncode(move: null), + serializer); } @protected - void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_String, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_dkg_status_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_dkg_status, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_log_message_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_log_message, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_mempool_msg_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_mempool_msg, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_migration_status_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_migration_status, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_signing_event_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_signing_event, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_signing_status_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_signing_status, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected - void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_sync_progress_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_sync_progress, decodeErrorData: sse_decode_AnyhowException, - ), - ), - serializer, - ); + )), + serializer); } @protected @@ -8568,7 +9094,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer) { + void sse_encode_box_autoadd_account_update( + AccountUpdate self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_account_update(self, serializer); } @@ -8580,7 +9107,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_category(Category self, SseSerializer serializer) { + void sse_encode_box_autoadd_category( + Category self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_category(self, serializer); } @@ -8598,7 +9126,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer) { + void sse_encode_box_autoadd_frost_params( + FrostParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_frost_params(self, serializer); } @@ -8610,37 +9139,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer) { + void sse_encode_box_autoadd_i_64( + PlatformInt64 self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_64(self, serializer); } @protected - void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer) { + void sse_encode_box_autoadd_mempool_tx( + MempoolTx self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_mempool_tx(self, serializer); } @protected - void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer) { + void sse_encode_box_autoadd_new_account( + NewAccount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_new_account(self, serializer); } @protected - void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer) { + void sse_encode_box_autoadd_payment_options( + PaymentOptions self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_payment_options(self, serializer); } @protected - void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer) { + void sse_encode_box_autoadd_pczt_package( + PcztPackage self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_pczt_package(self, serializer); } @protected - void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer) { + void sse_encode_box_autoadd_raptor_q_params( + RaptorQParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_raptor_q_params(self, serializer); } @@ -8652,7 +9187,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer) { + void sse_encode_box_autoadd_signing_event( + SigningEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_signing_event(self, serializer); } @@ -8712,7 +9248,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer) { + void sse_encode_db_account_preview( + DbAccountPreview self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.id, serializer); sse_encode_String(self.name, serializer); @@ -8774,7 +9311,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer) { + void sse_encode_frost_sign_params( + FrostSignParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.account, serializer); sse_encode_u_8(self.coordinator, serializer); @@ -8836,7 +9374,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_contact_match(List self, SseSerializer serializer) { + void sse_encode_list_contact_match( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8845,7 +9384,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_db_account_preview(List self, SseSerializer serializer) { + void sse_encode_list_db_account_preview( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8863,7 +9403,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer) { + void sse_encode_list_list_prim_u_8_strict( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8890,7 +9431,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_memo_cell(List self, SseSerializer serializer) { + void sse_encode_list_memo_cell( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8908,7 +9450,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_memo_section(List self, SseSerializer serializer) { + void sse_encode_list_memo_section( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8917,7 +9460,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_mempool_amount(List self, SseSerializer serializer) { + void sse_encode_list_mempool_amount( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8926,7 +9470,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_mempool_note(List self, SseSerializer serializer) { + void sse_encode_list_mempool_note( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8935,7 +9480,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_plugin_info(List self, SseSerializer serializer) { + void sse_encode_list_plugin_info( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8944,49 +9490,58 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer) { + void sse_encode_list_prim_u_32_loose( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer.putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); + serializer.buffer + .putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); } @protected - void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer) { + void sse_encode_list_prim_u_32_strict( + Uint32List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint32List(self); } @protected - void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer) { + void sse_encode_list_prim_u_64_strict( + Uint64List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); } @protected - void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer) { + void sse_encode_list_prim_u_8_loose( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer.putUint8List(self is Uint8List ? self : Uint8List.fromList(self)); + serializer.buffer + .putUint8List(self is Uint8List ? self : Uint8List.fromList(self)); } @protected - void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer) { + void sse_encode_list_prim_u_8_strict( + Uint8List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint8List(self); } @protected - void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer) { + void sse_encode_list_prim_usize_strict( + Uint64List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); } @protected - void sse_encode_list_recipient(List self, SseSerializer serializer) { + void sse_encode_list_recipient( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -8995,7 +9550,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer) { + void sse_encode_list_record_string_f_64_bool( + List<(String, double, bool)> self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9004,7 +9560,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer) { + void sse_encode_list_record_u_32_f_64( + List<(int, double)> self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9013,7 +9570,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_restored_account(List self, SseSerializer serializer) { + void sse_encode_list_restored_account( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9022,7 +9580,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer) { + void sse_encode_list_t_address_tx_count( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9058,7 +9617,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_output(List self, SseSerializer serializer) { + void sse_encode_list_tx_output( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9067,7 +9627,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_plan_in(List self, SseSerializer serializer) { + void sse_encode_list_tx_plan_in( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9076,7 +9637,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_tx_plan_out(List self, SseSerializer serializer) { + void sse_encode_list_tx_plan_out( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9094,7 +9656,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_list_zsa_holding(List self, SseSerializer serializer) { + void sse_encode_list_zsa_holding( + List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -9203,7 +9766,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer) { + void sse_encode_migration_event( + MigrationEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs switch (self) { case MigrationEvent_SplitComplete(fee: final fee): @@ -9223,7 +9787,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer) { + void sse_encode_migration_status( + MigrationStatus self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.phase, serializer); sse_encode_u_64(self.splitFees, serializer); @@ -9256,7 +9821,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer) { + void sse_encode_open_alias_resolution( + OpenAliasResolution self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_recipient(self.recipients, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -9293,7 +9859,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer) { + void sse_encode_opt_box_autoadd_frost_params( + FrostParams? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -9313,7 +9880,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer) { + void sse_encode_opt_box_autoadd_i_64( + PlatformInt64? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -9363,7 +9931,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_String(List? self, SseSerializer serializer) { + void sse_encode_opt_list_String( + List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -9373,7 +9942,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer) { + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -9383,7 +9953,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_opt_list_recipient(List? self, SseSerializer serializer) { + void sse_encode_opt_list_recipient( + List? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -9393,7 +9964,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer) { + void sse_encode_payment_options( + PaymentOptions self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.srcPools, serializer); sse_encode_bool(self.recipientPaysFee, serializer); @@ -9436,7 +10008,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer) { + void sse_encode_raptor_q_params( + RaptorQParams self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.version, serializer); sse_encode_u_8(self.ecLevel, serializer); @@ -9444,7 +10017,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer) { + void sse_encode_raw_open_alias_resolution( + RawOpenAliasResolution self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_String(self.records, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -9472,7 +10046,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer) { + void sse_encode_record_string_f_64_bool( + (String, double, bool) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.$1, serializer); sse_encode_f_64(self.$2, serializer); @@ -9480,14 +10055,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer) { + void sse_encode_record_u_32_f_64( + (int, double) self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.$1, serializer); sse_encode_f_64(self.$2, serializer); } @protected - void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer) { + void sse_encode_restored_account( + RestoredAccount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.timestamp, serializer); sse_encode_String(self.name, serializer); @@ -9498,7 +10075,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer) { + void sse_encode_sapling_params_status( + SaplingParamsStatus self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self.downloaded, serializer); } @@ -9568,7 +10146,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer) { + void sse_encode_t_address_tx_count( + TAddressTxCount self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.pool, serializer); sse_encode_String(self.address, serializer); @@ -9750,29 +10329,58 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @sealed class DartVaultImpl extends RustOpaque implements DartVault { // Not to be used by end users - DartVaultImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + DartVaultImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - DartVaultImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + DartVaultImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_DartVault, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_DartVault, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_DartVaultPtr, + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_DartVault, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_DartVault, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_DartVaultPtr, ); - Future> recover({required List vaultBytes, required String masterPassword}) => - RustLib.instance.api.crateApiVaultDartVaultRecover(that: this, vaultBytes: vaultBytes, masterPassword: masterPassword); - - Future> recoverWithPrf({required List vaultBytes, required String deviceIdStr, required List prfOutput}) => - RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf(that: this, vaultBytes: vaultBytes, deviceIdStr: deviceIdStr, prfOutput: prfOutput); - - Future registerDevice({required List initBytes, required String masterPassword, required String deviceIdStr, required List prfOutput}) => + Future> recover( + {required List vaultBytes, required String masterPassword}) => + RustLib.instance.api.crateApiVaultDartVaultRecover( + that: this, vaultBytes: vaultBytes, masterPassword: masterPassword); + + Future> recoverWithPrf( + {required List vaultBytes, + required String deviceIdStr, + required List prfOutput}) => + RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf( + that: this, + vaultBytes: vaultBytes, + deviceIdStr: deviceIdStr, + prfOutput: prfOutput); + + Future registerDevice( + {required List initBytes, + required String masterPassword, + required String deviceIdStr, + required List prfOutput}) => RustLib.instance.api.crateApiVaultDartVaultRegisterDevice( - that: this, initBytes: initBytes, masterPassword: masterPassword, deviceIdStr: deviceIdStr, prfOutput: prfOutput); - - Future setMasterPassword({String? oldPassword, required String newPassword, Uint8List? oldBytes}) => - RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword(that: this, oldPassword: oldPassword, newPassword: newPassword, oldBytes: oldBytes); + that: this, + initBytes: initBytes, + masterPassword: masterPassword, + deviceIdStr: deviceIdStr, + prfOutput: prfOutput); + + Future setMasterPassword( + {String? oldPassword, + required String newPassword, + Uint8List? oldBytes}) => + RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword( + that: this, + oldPassword: oldPassword, + newPassword: newPassword, + oldBytes: oldBytes); Future storeAccount( {required int timestamp, @@ -9783,7 +10391,14 @@ class DartVaultImpl extends RustOpaque implements DartVault { required int birthHeight, required List pk}) => RustLib.instance.api.crateApiVaultDartVaultStoreAccount( - that: this, timestamp: timestamp, name: name, seed: seed, aindex: aindex, useInternal: useInternal, birthHeight: birthHeight, pk: pk); + that: this, + timestamp: timestamp, + name: name, + seed: seed, + aindex: aindex, + useInternal: useInternal, + birthHeight: birthHeight, + pk: pk); Future test() => RustLib.instance.api.crateApiVaultDartVaultTest( that: this, @@ -9793,67 +10408,90 @@ class DartVaultImpl extends RustOpaque implements DartVault { @sealed class MempoolImpl extends RustOpaque implements Mempool { // Not to be used by end users - MempoolImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + MempoolImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - MempoolImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + MempoolImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_Mempool, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_Mempool, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_MempoolPtr, + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_Mempool, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_Mempool, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_MempoolPtr, ); Future cancel() => RustLib.instance.api.crateApiMempoolMempoolCancel( that: this, ); - Stream run({required Coin c}) => RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); + Stream run({required Coin c}) => + RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); } @sealed class NoteMigrationImpl extends RustOpaque implements NoteMigration { // Not to be used by end users - NoteMigrationImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + NoteMigrationImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_NoteMigration, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigration, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigrationPtr, + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_NoteMigration, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigration, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_NoteMigrationPtr, ); - Future cancel() => RustLib.instance.api.crateApiMigrateNoteMigrationCancel( + Future cancel() => + RustLib.instance.api.crateApiMigrateNoteMigrationCancel( that: this, ); Stream run({required Coin c, required BigInt meanDelayMs}) => - RustLib.instance.api.crateApiMigrateNoteMigrationRun(that: this, c: c, meanDelayMs: meanDelayMs); + RustLib.instance.api.crateApiMigrateNoteMigrationRun( + that: this, c: c, meanDelayMs: meanDelayMs); /// Supplies a height observed by the shared Dart block-height service. - void updateHeight({required int height}) => RustLib.instance.api.crateApiMigrateNoteMigrationUpdateHeight(that: this, height: height); + void updateHeight({required int height}) => RustLib.instance.api + .crateApiMigrateNoteMigrationUpdateHeight(that: this, height: height); } @sealed class TransparentScannerImpl extends RustOpaque implements TransparentScanner { // Not to be used by end users - TransparentScannerImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + TransparentScannerImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users - TransparentScannerImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + TransparentScannerImpl.frbInternalSseDecode( + BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_TransparentScanner, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScanner, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScannerPtr, + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_TransparentScanner, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScanner, + rustArcDecrementStrongCountPtr: RustLib + .instance.api.rust_arc_decrement_strong_count_TransparentScannerPtr, ); - Future cancel() => RustLib.instance.api.crateApiSweepTransparentScannerCancel( + Future cancel() => + RustLib.instance.api.crateApiSweepTransparentScannerCancel( that: this, ); - Stream run({required int endHeight, required int gapLimit, required Coin c}) => - RustLib.instance.api.crateApiSweepTransparentScannerRun(that: this, endHeight: endHeight, gapLimit: gapLimit, c: c); + Stream run( + {required int endHeight, required int gapLimit, required Coin c}) => + RustLib.instance.api.crateApiSweepTransparentScannerRun( + that: this, endHeight: endHeight, gapLimit: gapLimit, c: c); } diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index cc41236b5..54fd0b567 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -44,62 +44,92 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_TransparentScannerPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected - DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw); + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw); @protected Object dco_decode_DartOpaque(dynamic raw); @protected - DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); @@ -114,16 +144,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_migration_status_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_event_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_status_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_sync_progress_Sse( + dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -306,7 +340,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List dco_decode_list_recipient(dynamic raw); @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw); + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( + dynamic raw); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -531,70 +566,104 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); @protected - DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected - DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_dkg_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_log_message_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_migration_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_event_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_sync_progress_Sse( + SseDeserializer deserializer); @protected String sse_decode_String(SseDeserializer deserializer); @@ -612,7 +681,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { bool sse_decode_bool(SseDeserializer deserializer); @protected - AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer); + AccountUpdate sse_decode_box_autoadd_account_update( + SseDeserializer deserializer); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -642,19 +712,22 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_box_autoadd_new_account(SseDeserializer deserializer); @protected - PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer); + PaymentOptions sse_decode_box_autoadd_payment_options( + SseDeserializer deserializer); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer); + RaptorQParams sse_decode_box_autoadd_raptor_q_params( + SseDeserializer deserializer); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected - SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer); + SigningEvent sse_decode_box_autoadd_signing_event( + SseDeserializer deserializer); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -720,16 +793,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_contact(SseDeserializer deserializer); @protected - List sse_decode_list_contact_match(SseDeserializer deserializer); + List sse_decode_list_contact_match( + SseDeserializer deserializer); @protected - List sse_decode_list_db_account_preview(SseDeserializer deserializer); + List sse_decode_list_db_account_preview( + SseDeserializer deserializer); @protected List sse_decode_list_folder(SseDeserializer deserializer); @protected - List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer); + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer); @protected List sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -747,7 +823,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_memo_section(SseDeserializer deserializer); @protected - List sse_decode_list_mempool_amount(SseDeserializer deserializer); + List sse_decode_list_mempool_amount( + SseDeserializer deserializer); @protected List sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -777,16 +854,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_recipient(SseDeserializer deserializer); @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer); + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( + SseDeserializer deserializer); @protected - List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer); + List<(int, double)> sse_decode_list_record_u_32_f_64( + SseDeserializer deserializer); @protected - List sse_decode_list_restored_account(SseDeserializer deserializer); + List sse_decode_list_restored_account( + SseDeserializer deserializer); @protected - List sse_decode_list_t_address_tx_count(SseDeserializer deserializer); + List sse_decode_list_t_address_tx_count( + SseDeserializer deserializer); @protected List sse_decode_list_tx(SseDeserializer deserializer); @@ -852,7 +933,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_new_account(SseDeserializer deserializer); @protected - OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer); + OpenAliasResolution sse_decode_open_alias_resolution( + SseDeserializer deserializer); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -864,7 +946,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { double? sse_decode_opt_box_autoadd_f_64(SseDeserializer deserializer); @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer); + FrostParams? sse_decode_opt_box_autoadd_frost_params( + SseDeserializer deserializer); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -909,7 +992,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RaptorQParams sse_decode_raptor_q_params(SseDeserializer deserializer); @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer); + RawOpenAliasResolution sse_decode_raw_open_alias_resolution( + SseDeserializer deserializer); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -918,7 +1002,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { Recipient sse_decode_recipient(SseDeserializer deserializer); @protected - (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer); + (String, double, bool) sse_decode_record_string_f_64_bool( + SseDeserializer deserializer); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -927,7 +1012,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RestoredAccount sse_decode_restored_account(SseDeserializer deserializer); @protected - SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer); + SaplingParamsStatus sse_decode_sapling_params_status( + SseDeserializer deserializer); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -999,78 +1085,113 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected - void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); + void sse_encode_AnyhowException( + AnyhowException self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer); + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr Function(Uint8List) self, SseSerializer serializer); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_dkg_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_log_message_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_mempool_msg_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_migration_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_event_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_sync_progress_Sse( + RustStreamSink self, SseSerializer serializer); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1088,7 +1209,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_bool(bool self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer); + void sse_encode_box_autoadd_account_update( + AccountUpdate self, SseSerializer serializer); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1103,34 +1225,42 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_box_autoadd_f_64(double self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer); + void sse_encode_box_autoadd_frost_params( + FrostParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer); + void sse_encode_box_autoadd_i_64( + PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer); + void sse_encode_box_autoadd_mempool_tx( + MempoolTx self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer); + void sse_encode_box_autoadd_new_account( + NewAccount self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer); + void sse_encode_box_autoadd_payment_options( + PaymentOptions self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer); + void sse_encode_box_autoadd_pczt_package( + PcztPackage self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer); + void sse_encode_box_autoadd_raptor_q_params( + RaptorQParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer); + void sse_encode_box_autoadd_signing_event( + SigningEvent self, SseSerializer serializer); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1154,7 +1284,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_contact_match(ContactMatch self, SseSerializer serializer); @protected - void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer); + void sse_encode_db_account_preview( + DbAccountPreview self, SseSerializer serializer); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1172,7 +1303,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_frost_params(FrostParams self, SseSerializer serializer); @protected - void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer); + void sse_encode_frost_sign_params( + FrostSignParams self, SseSerializer serializer); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1196,16 +1328,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_contact(List self, SseSerializer serializer); @protected - void sse_encode_list_contact_match(List self, SseSerializer serializer); + void sse_encode_list_contact_match( + List self, SseSerializer serializer); @protected - void sse_encode_list_db_account_preview(List self, SseSerializer serializer); + void sse_encode_list_db_account_preview( + List self, SseSerializer serializer); @protected void sse_encode_list_folder(List self, SseSerializer serializer); @protected - void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer); + void sse_encode_list_list_prim_u_8_strict( + List self, SseSerializer serializer); @protected void sse_encode_list_lwd_info(List self, SseSerializer serializer); @@ -1220,49 +1355,63 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_memo_row(List self, SseSerializer serializer); @protected - void sse_encode_list_memo_section(List self, SseSerializer serializer); + void sse_encode_list_memo_section( + List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_amount(List self, SseSerializer serializer); + void sse_encode_list_mempool_amount( + List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_note(List self, SseSerializer serializer); + void sse_encode_list_mempool_note( + List self, SseSerializer serializer); @protected - void sse_encode_list_plugin_info(List self, SseSerializer serializer); + void sse_encode_list_plugin_info( + List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_loose( + List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_strict( + Uint32List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_u_64_strict( + Uint64List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer); + void sse_encode_list_prim_u_8_strict( + Uint8List self, SseSerializer serializer); @protected - void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_usize_strict( + Uint64List self, SseSerializer serializer); @protected - void sse_encode_list_recipient(List self, SseSerializer serializer); + void sse_encode_list_recipient( + List self, SseSerializer serializer); @protected - void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer); + void sse_encode_list_record_string_f_64_bool( + List<(String, double, bool)> self, SseSerializer serializer); @protected - void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer); + void sse_encode_list_record_u_32_f_64( + List<(int, double)> self, SseSerializer serializer); @protected - void sse_encode_list_restored_account(List self, SseSerializer serializer); + void sse_encode_list_restored_account( + List self, SseSerializer serializer); @protected - void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer); + void sse_encode_list_t_address_tx_count( + List self, SseSerializer serializer); @protected void sse_encode_list_tx(List self, SseSerializer serializer); @@ -1277,16 +1426,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_tx_output(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_in(List self, SseSerializer serializer); + void sse_encode_list_tx_plan_in( + List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_out(List self, SseSerializer serializer); + void sse_encode_list_tx_plan_out( + List self, SseSerializer serializer); @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); @protected - void sse_encode_list_zsa_holding(List self, SseSerializer serializer); + void sse_encode_list_zsa_holding( + List self, SseSerializer serializer); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -1319,16 +1471,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer); + void sse_encode_migration_event( + MigrationEvent self, SseSerializer serializer); @protected - void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer); + void sse_encode_migration_status( + MigrationStatus self, SseSerializer serializer); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer); + void sse_encode_open_alias_resolution( + OpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1340,13 +1495,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_box_autoadd_f_64(double? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_frost_params( + FrostParams? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_i_64( + PlatformInt64? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -1364,13 +1521,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_list_String(List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer); + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_recipient(List? self, SseSerializer serializer); + void sse_encode_opt_list_recipient( + List? self, SseSerializer serializer); @protected - void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer); + void sse_encode_payment_options( + PaymentOptions self, SseSerializer serializer); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -1385,7 +1545,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected - void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer); + void sse_encode_raw_open_alias_resolution( + RawOpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -1394,16 +1555,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_recipient(Recipient self, SseSerializer serializer); @protected - void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer); + void sse_encode_record_string_f_64_bool( + (String, double, bool) self, SseSerializer serializer); @protected - void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer); + void sse_encode_record_u_32_f_64( + (int, double) self, SseSerializer serializer); @protected - void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer); + void sse_encode_restored_account( + RestoredAccount self, SseSerializer serializer); @protected - void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer); + void sse_encode_sapling_params_status( + SaplingParamsStatus self, SseSerializer serializer); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -1421,7 +1586,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_sync_progress(SyncProgress self, SseSerializer serializer); @protected - void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer); + void sse_encode_t_address_tx_count( + TAddressTxCount self, SseSerializer serializer); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -1478,15 +1644,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { // Section: wire_class class RustLibWire implements BaseWire { - factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => RustLibWire(lib.ffiDynamicLibrary); + factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => + RustLibWire(lib.ffiDynamicLibrary); /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) _lookup; + final ffi.Pointer Function(String symbolName) + _lookup; /// The symbols are looked up in [dynamicLibrary]. - RustLibWire(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; + RustLibWire(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -1501,7 +1671,8 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction)>(); - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -1516,7 +1687,8 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction)>(); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -1531,7 +1703,8 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction)>(); - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -1546,7 +1719,8 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction)>(); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -1561,7 +1735,8 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction)>(); - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -1576,7 +1751,8 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction)>(); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -1591,7 +1767,8 @@ class RustLibWire implements BaseWire { _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr .asFunction)>(); - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 8d88cb206..85135bd8a 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -46,62 +46,92 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_NoteMigrationPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_TransparentScannerPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_TransparentScannerPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected - DartVault dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - Mempool dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - NoteMigration dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - Mempool dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - DartVault dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - NoteMigration dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected - FutureOr Function(Uint8List) dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(dynamic raw); + FutureOr Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw); @protected Object dco_decode_DartOpaque(dynamic raw); @protected - DartVault dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(dynamic raw); + DartVault + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw); @protected - Mempool dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(dynamic raw); + Mempool + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw); @protected - NoteMigration dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(dynamic raw); + NoteMigration + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw); @protected - TransparentScanner dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(dynamic raw); + TransparentScanner + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw); @protected RustStreamSink dco_decode_StreamSink_String_Sse(dynamic raw); @@ -116,16 +146,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_mempool_msg_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_migration_status_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_migration_status_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_event_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_event_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_signing_status_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_signing_status_Sse( + dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_sync_progress_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_sync_progress_Sse( + dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -308,7 +342,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List dco_decode_list_recipient(dynamic raw); @protected - List<(String, double, bool)> dco_decode_list_record_string_f_64_bool(dynamic raw); + List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( + dynamic raw); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -533,70 +568,104 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); @protected - DartVault sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - Mempool sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - Mempool sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - DartVault sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected - DartVault sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(SseDeserializer deserializer); + DartVault + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer); @protected - Mempool sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(SseDeserializer deserializer); + Mempool + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer); @protected - NoteMigration sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(SseDeserializer deserializer); + NoteMigration + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer); @protected - TransparentScanner sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(SseDeserializer deserializer); + TransparentScanner + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_String_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_String_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_dkg_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_dkg_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_log_message_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_log_message_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_mempool_msg_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_mempool_msg_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_migration_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_migration_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_event_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_event_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_signing_status_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_signing_status_Sse( + SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_sync_progress_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_sync_progress_Sse( + SseDeserializer deserializer); @protected String sse_decode_String(SseDeserializer deserializer); @@ -614,7 +683,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { bool sse_decode_bool(SseDeserializer deserializer); @protected - AccountUpdate sse_decode_box_autoadd_account_update(SseDeserializer deserializer); + AccountUpdate sse_decode_box_autoadd_account_update( + SseDeserializer deserializer); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -644,19 +714,22 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_box_autoadd_new_account(SseDeserializer deserializer); @protected - PaymentOptions sse_decode_box_autoadd_payment_options(SseDeserializer deserializer); + PaymentOptions sse_decode_box_autoadd_payment_options( + SseDeserializer deserializer); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected - RaptorQParams sse_decode_box_autoadd_raptor_q_params(SseDeserializer deserializer); + RaptorQParams sse_decode_box_autoadd_raptor_q_params( + SseDeserializer deserializer); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected - SigningEvent sse_decode_box_autoadd_signing_event(SseDeserializer deserializer); + SigningEvent sse_decode_box_autoadd_signing_event( + SseDeserializer deserializer); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -722,16 +795,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_contact(SseDeserializer deserializer); @protected - List sse_decode_list_contact_match(SseDeserializer deserializer); + List sse_decode_list_contact_match( + SseDeserializer deserializer); @protected - List sse_decode_list_db_account_preview(SseDeserializer deserializer); + List sse_decode_list_db_account_preview( + SseDeserializer deserializer); @protected List sse_decode_list_folder(SseDeserializer deserializer); @protected - List sse_decode_list_list_prim_u_8_strict(SseDeserializer deserializer); + List sse_decode_list_list_prim_u_8_strict( + SseDeserializer deserializer); @protected List sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -749,7 +825,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_memo_section(SseDeserializer deserializer); @protected - List sse_decode_list_mempool_amount(SseDeserializer deserializer); + List sse_decode_list_mempool_amount( + SseDeserializer deserializer); @protected List sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -779,16 +856,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { List sse_decode_list_recipient(SseDeserializer deserializer); @protected - List<(String, double, bool)> sse_decode_list_record_string_f_64_bool(SseDeserializer deserializer); + List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( + SseDeserializer deserializer); @protected - List<(int, double)> sse_decode_list_record_u_32_f_64(SseDeserializer deserializer); + List<(int, double)> sse_decode_list_record_u_32_f_64( + SseDeserializer deserializer); @protected - List sse_decode_list_restored_account(SseDeserializer deserializer); + List sse_decode_list_restored_account( + SseDeserializer deserializer); @protected - List sse_decode_list_t_address_tx_count(SseDeserializer deserializer); + List sse_decode_list_t_address_tx_count( + SseDeserializer deserializer); @protected List sse_decode_list_tx(SseDeserializer deserializer); @@ -854,7 +935,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NewAccount sse_decode_new_account(SseDeserializer deserializer); @protected - OpenAliasResolution sse_decode_open_alias_resolution(SseDeserializer deserializer); + OpenAliasResolution sse_decode_open_alias_resolution( + SseDeserializer deserializer); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -866,7 +948,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { double? sse_decode_opt_box_autoadd_f_64(SseDeserializer deserializer); @protected - FrostParams? sse_decode_opt_box_autoadd_frost_params(SseDeserializer deserializer); + FrostParams? sse_decode_opt_box_autoadd_frost_params( + SseDeserializer deserializer); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -911,7 +994,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RaptorQParams sse_decode_raptor_q_params(SseDeserializer deserializer); @protected - RawOpenAliasResolution sse_decode_raw_open_alias_resolution(SseDeserializer deserializer); + RawOpenAliasResolution sse_decode_raw_open_alias_resolution( + SseDeserializer deserializer); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -920,7 +1004,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { Recipient sse_decode_recipient(SseDeserializer deserializer); @protected - (String, double, bool) sse_decode_record_string_f_64_bool(SseDeserializer deserializer); + (String, double, bool) sse_decode_record_string_f_64_bool( + SseDeserializer deserializer); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -929,7 +1014,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RestoredAccount sse_decode_restored_account(SseDeserializer deserializer); @protected - SaplingParamsStatus sse_decode_sapling_params_status(SseDeserializer deserializer); + SaplingParamsStatus sse_decode_sapling_params_status( + SseDeserializer deserializer); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -1001,78 +1087,113 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected - void sse_encode_AnyhowException(AnyhowException self, SseSerializer serializer); + void sse_encode_AnyhowException( + AnyhowException self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException(FutureOr Function(Uint8List) self, SseSerializer serializer); + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr Function(Uint8List) self, SseSerializer serializer); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(DartVault self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(Mempool self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(NoteMigration self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, SseSerializer serializer); @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(TransparentScanner self, SseSerializer serializer); + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, SseSerializer serializer); @protected - void sse_encode_StreamSink_String_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_String_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_dkg_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_dkg_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_log_message_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_log_message_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_mempool_msg_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_mempool_msg_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_migration_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_migration_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_event_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_event_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_signing_status_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_signing_status_Sse( + RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_sync_progress_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_sync_progress_Sse( + RustStreamSink self, SseSerializer serializer); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1090,7 +1211,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_bool(bool self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_account_update(AccountUpdate self, SseSerializer serializer); + void sse_encode_box_autoadd_account_update( + AccountUpdate self, SseSerializer serializer); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1105,34 +1227,42 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_box_autoadd_f_64(double self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_frost_params(FrostParams self, SseSerializer serializer); + void sse_encode_box_autoadd_frost_params( + FrostParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_i_64(PlatformInt64 self, SseSerializer serializer); + void sse_encode_box_autoadd_i_64( + PlatformInt64 self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_mempool_tx(MempoolTx self, SseSerializer serializer); + void sse_encode_box_autoadd_mempool_tx( + MempoolTx self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_new_account(NewAccount self, SseSerializer serializer); + void sse_encode_box_autoadd_new_account( + NewAccount self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_payment_options(PaymentOptions self, SseSerializer serializer); + void sse_encode_box_autoadd_payment_options( + PaymentOptions self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_pczt_package(PcztPackage self, SseSerializer serializer); + void sse_encode_box_autoadd_pczt_package( + PcztPackage self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_raptor_q_params(RaptorQParams self, SseSerializer serializer); + void sse_encode_box_autoadd_raptor_q_params( + RaptorQParams self, SseSerializer serializer); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected - void sse_encode_box_autoadd_signing_event(SigningEvent self, SseSerializer serializer); + void sse_encode_box_autoadd_signing_event( + SigningEvent self, SseSerializer serializer); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1156,7 +1286,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_contact_match(ContactMatch self, SseSerializer serializer); @protected - void sse_encode_db_account_preview(DbAccountPreview self, SseSerializer serializer); + void sse_encode_db_account_preview( + DbAccountPreview self, SseSerializer serializer); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1174,7 +1305,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_frost_params(FrostParams self, SseSerializer serializer); @protected - void sse_encode_frost_sign_params(FrostSignParams self, SseSerializer serializer); + void sse_encode_frost_sign_params( + FrostSignParams self, SseSerializer serializer); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1198,16 +1330,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_contact(List self, SseSerializer serializer); @protected - void sse_encode_list_contact_match(List self, SseSerializer serializer); + void sse_encode_list_contact_match( + List self, SseSerializer serializer); @protected - void sse_encode_list_db_account_preview(List self, SseSerializer serializer); + void sse_encode_list_db_account_preview( + List self, SseSerializer serializer); @protected void sse_encode_list_folder(List self, SseSerializer serializer); @protected - void sse_encode_list_list_prim_u_8_strict(List self, SseSerializer serializer); + void sse_encode_list_list_prim_u_8_strict( + List self, SseSerializer serializer); @protected void sse_encode_list_lwd_info(List self, SseSerializer serializer); @@ -1222,49 +1357,63 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_memo_row(List self, SseSerializer serializer); @protected - void sse_encode_list_memo_section(List self, SseSerializer serializer); + void sse_encode_list_memo_section( + List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_amount(List self, SseSerializer serializer); + void sse_encode_list_mempool_amount( + List self, SseSerializer serializer); @protected - void sse_encode_list_mempool_note(List self, SseSerializer serializer); + void sse_encode_list_mempool_note( + List self, SseSerializer serializer); @protected - void sse_encode_list_plugin_info(List self, SseSerializer serializer); + void sse_encode_list_plugin_info( + List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_loose(List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_loose( + List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_32_strict(Uint32List self, SseSerializer serializer); + void sse_encode_list_prim_u_32_strict( + Uint32List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_64_strict(Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_u_64_strict( + Uint64List self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); @protected - void sse_encode_list_prim_u_8_strict(Uint8List self, SseSerializer serializer); + void sse_encode_list_prim_u_8_strict( + Uint8List self, SseSerializer serializer); @protected - void sse_encode_list_prim_usize_strict(Uint64List self, SseSerializer serializer); + void sse_encode_list_prim_usize_strict( + Uint64List self, SseSerializer serializer); @protected - void sse_encode_list_recipient(List self, SseSerializer serializer); + void sse_encode_list_recipient( + List self, SseSerializer serializer); @protected - void sse_encode_list_record_string_f_64_bool(List<(String, double, bool)> self, SseSerializer serializer); + void sse_encode_list_record_string_f_64_bool( + List<(String, double, bool)> self, SseSerializer serializer); @protected - void sse_encode_list_record_u_32_f_64(List<(int, double)> self, SseSerializer serializer); + void sse_encode_list_record_u_32_f_64( + List<(int, double)> self, SseSerializer serializer); @protected - void sse_encode_list_restored_account(List self, SseSerializer serializer); + void sse_encode_list_restored_account( + List self, SseSerializer serializer); @protected - void sse_encode_list_t_address_tx_count(List self, SseSerializer serializer); + void sse_encode_list_t_address_tx_count( + List self, SseSerializer serializer); @protected void sse_encode_list_tx(List self, SseSerializer serializer); @@ -1279,16 +1428,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_tx_output(List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_in(List self, SseSerializer serializer); + void sse_encode_list_tx_plan_in( + List self, SseSerializer serializer); @protected - void sse_encode_list_tx_plan_out(List self, SseSerializer serializer); + void sse_encode_list_tx_plan_out( + List self, SseSerializer serializer); @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); @protected - void sse_encode_list_zsa_holding(List self, SseSerializer serializer); + void sse_encode_list_zsa_holding( + List self, SseSerializer serializer); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -1321,16 +1473,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_mempool_tx(MempoolTx self, SseSerializer serializer); @protected - void sse_encode_migration_event(MigrationEvent self, SseSerializer serializer); + void sse_encode_migration_event( + MigrationEvent self, SseSerializer serializer); @protected - void sse_encode_migration_status(MigrationStatus self, SseSerializer serializer); + void sse_encode_migration_status( + MigrationStatus self, SseSerializer serializer); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected - void sse_encode_open_alias_resolution(OpenAliasResolution self, SseSerializer serializer); + void sse_encode_open_alias_resolution( + OpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1342,13 +1497,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_box_autoadd_f_64(double? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_frost_params(FrostParams? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_frost_params( + FrostParams? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected - void sse_encode_opt_box_autoadd_i_64(PlatformInt64? self, SseSerializer serializer); + void sse_encode_opt_box_autoadd_i_64( + PlatformInt64? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -1366,13 +1523,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_opt_list_String(List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_prim_u_8_strict(Uint8List? self, SseSerializer serializer); + void sse_encode_opt_list_prim_u_8_strict( + Uint8List? self, SseSerializer serializer); @protected - void sse_encode_opt_list_recipient(List? self, SseSerializer serializer); + void sse_encode_opt_list_recipient( + List? self, SseSerializer serializer); @protected - void sse_encode_payment_options(PaymentOptions self, SseSerializer serializer); + void sse_encode_payment_options( + PaymentOptions self, SseSerializer serializer); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -1387,7 +1547,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_raptor_q_params(RaptorQParams self, SseSerializer serializer); @protected - void sse_encode_raw_open_alias_resolution(RawOpenAliasResolution self, SseSerializer serializer); + void sse_encode_raw_open_alias_resolution( + RawOpenAliasResolution self, SseSerializer serializer); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -1396,16 +1557,20 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_recipient(Recipient self, SseSerializer serializer); @protected - void sse_encode_record_string_f_64_bool((String, double, bool) self, SseSerializer serializer); + void sse_encode_record_string_f_64_bool( + (String, double, bool) self, SseSerializer serializer); @protected - void sse_encode_record_u_32_f_64((int, double) self, SseSerializer serializer); + void sse_encode_record_u_32_f_64( + (int, double) self, SseSerializer serializer); @protected - void sse_encode_restored_account(RestoredAccount self, SseSerializer serializer); + void sse_encode_restored_account( + RestoredAccount self, SseSerializer serializer); @protected - void sse_encode_sapling_params_status(SaplingParamsStatus self, SseSerializer serializer); + void sse_encode_sapling_params_status( + SaplingParamsStatus self, SseSerializer serializer); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -1423,7 +1588,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_sync_progress(SyncProgress self, SseSerializer serializer); @protected - void sse_encode_t_address_tx_count(TAddressTxCount self, SseSerializer serializer); + void sse_encode_t_address_tx_count( + TAddressTxCount self, SseSerializer serializer); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -1482,29 +1648,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { class RustLibWire implements BaseWire { RustLibWire.fromExternalLibrary(ExternalLibrary lib); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr) => - wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr) => - wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr) => - wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr) => - wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr) => - wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr) => - wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr) => - wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr) => - wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr); + + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr) => + wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr) => + wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + ptr); } @JS('wasm_bindgen') @@ -1513,19 +1703,35 @@ external RustLibWasmModule get wasmModule; @JS() @anonymous extension type RustLibWasmModule._(JSObject _) implements JSObject { - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr); - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault(int ptr); + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr); - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr); - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool(int ptr); + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr); - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr); - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration(int ptr); + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr); - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr); - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner(int ptr); + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr); } diff --git a/lib/src/rust/io.dart b/lib/src/rust/io.dart index c130d0c3d..0d15c9d3e 100644 --- a/lib/src/rust/io.dart +++ b/lib/src/rust/io.dart @@ -22,5 +22,10 @@ class SyncHeight { @override bool operator ==(Object other) => - identical(this, other) || other is SyncHeight && runtimeType == other.runtimeType && pool == other.pool && height == other.height && time == other.time; + identical(this, other) || + other is SyncHeight && + runtimeType == other.runtimeType && + pool == other.pool && + height == other.height && + time == other.time; } diff --git a/lib/src/rust/pay.dart b/lib/src/rust/pay.dart index 54f62655c..4c52e5bf3 100644 --- a/lib/src/rust/pay.dart +++ b/lib/src/rust/pay.dart @@ -29,7 +29,14 @@ class Recipient { @override int get hashCode => - address.hashCode ^ amount.hashCode ^ pools.hashCode ^ userMemo.hashCode ^ memoBytes.hashCode ^ price.hashCode ^ assetBase.hashCode ^ assetName.hashCode; + address.hashCode ^ + amount.hashCode ^ + pools.hashCode ^ + userMemo.hashCode ^ + memoBytes.hashCode ^ + price.hashCode ^ + assetBase.hashCode ^ + assetName.hashCode; @override bool operator ==(Object other) => @@ -64,7 +71,13 @@ class TxPlan { }); @override - int get hashCode => height.hashCode ^ inputs.hashCode ^ outputs.hashCode ^ fee.hashCode ^ canSign.hashCode ^ canBroadcast.hashCode; + int get hashCode => + height.hashCode ^ + inputs.hashCode ^ + outputs.hashCode ^ + fee.hashCode ^ + canSign.hashCode ^ + canBroadcast.hashCode; @override bool operator ==(Object other) => @@ -96,7 +109,11 @@ class TxPlanIn { @override bool operator ==(Object other) => identical(this, other) || - other is TxPlanIn && runtimeType == other.runtimeType && pool == other.pool && amount == other.amount && assetName == other.assetName; + other is TxPlanIn && + runtimeType == other.runtimeType && + pool == other.pool && + amount == other.amount && + assetName == other.assetName; } class TxPlanOut { @@ -113,7 +130,8 @@ class TxPlanOut { }); @override - int get hashCode => pool.hashCode ^ amount.hashCode ^ address.hashCode ^ assetName.hashCode; + int get hashCode => + pool.hashCode ^ amount.hashCode ^ address.hashCode ^ assetName.hashCode; @override bool operator ==(Object other) => diff --git a/lib/src/rust/pay/error.freezed.dart b/lib/src/rust/pay/error.freezed.dart index 77ae697d0..8be139e33 100644 --- a/lib/src/rust/pay/error.freezed.dart +++ b/lib/src/rust/pay/error.freezed.dart @@ -16,7 +16,8 @@ T _$identity(T value) => value; mixin _$Error { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is Error); + return identical(this, other) || + (other.runtimeType == runtimeType && other is Error); } @override @@ -265,7 +266,8 @@ class Error_InvalidPoolMask extends Error { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is Error_InvalidPoolMask); + return identical(this, other) || + (other.runtimeType == runtimeType && other is Error_InvalidPoolMask); } @override @@ -288,12 +290,16 @@ class Error_NotEnoughFunds extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_NotEnoughFundsCopyWith get copyWith => _$Error_NotEnoughFundsCopyWithImpl(this, _$identity); + $Error_NotEnoughFundsCopyWith get copyWith => + _$Error_NotEnoughFundsCopyWithImpl( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && other is Error_NotEnoughFunds && (identical(other.field0, field0) || other.field0 == field0)); + (other.runtimeType == runtimeType && + other is Error_NotEnoughFunds && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -306,14 +312,18 @@ class Error_NotEnoughFunds extends Error { } /// @nodoc -abstract mixin class $Error_NotEnoughFundsCopyWith<$Res> implements $ErrorCopyWith<$Res> { - factory $Error_NotEnoughFundsCopyWith(Error_NotEnoughFunds value, $Res Function(Error_NotEnoughFunds) _then) = _$Error_NotEnoughFundsCopyWithImpl; +abstract mixin class $Error_NotEnoughFundsCopyWith<$Res> + implements $ErrorCopyWith<$Res> { + factory $Error_NotEnoughFundsCopyWith(Error_NotEnoughFunds value, + $Res Function(Error_NotEnoughFunds) _then) = + _$Error_NotEnoughFundsCopyWithImpl; @useResult $Res call({String field0}); } /// @nodoc -class _$Error_NotEnoughFundsCopyWithImpl<$Res> implements $Error_NotEnoughFundsCopyWith<$Res> { +class _$Error_NotEnoughFundsCopyWithImpl<$Res> + implements $Error_NotEnoughFundsCopyWith<$Res> { _$Error_NotEnoughFundsCopyWithImpl(this._self, this._then); final Error_NotEnoughFunds _self; @@ -341,7 +351,8 @@ class Error_NoSigningKey extends Error { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is Error_NoSigningKey); + return identical(this, other) || + (other.runtimeType == runtimeType && other is Error_NoSigningKey); } @override @@ -364,11 +375,15 @@ class Error_Sqlx extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_SqlxCopyWith get copyWith => _$Error_SqlxCopyWithImpl(this, _$identity); + $Error_SqlxCopyWith get copyWith => + _$Error_SqlxCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is Error_Sqlx && (identical(other.field0, field0) || other.field0 == field0)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is Error_Sqlx && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -382,7 +397,9 @@ class Error_Sqlx extends Error { /// @nodoc abstract mixin class $Error_SqlxCopyWith<$Res> implements $ErrorCopyWith<$Res> { - factory $Error_SqlxCopyWith(Error_Sqlx value, $Res Function(Error_Sqlx) _then) = _$Error_SqlxCopyWithImpl; + factory $Error_SqlxCopyWith( + Error_Sqlx value, $Res Function(Error_Sqlx) _then) = + _$Error_SqlxCopyWithImpl; @useResult $Res call({Error field0}); @@ -432,11 +449,15 @@ class Error_Other extends Error { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $Error_OtherCopyWith get copyWith => _$Error_OtherCopyWithImpl(this, _$identity); + $Error_OtherCopyWith get copyWith => + _$Error_OtherCopyWithImpl(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType && other is Error_Other && (identical(other.field0, field0) || other.field0 == field0)); + return identical(this, other) || + (other.runtimeType == runtimeType && + other is Error_Other && + (identical(other.field0, field0) || other.field0 == field0)); } @override @@ -449,8 +470,11 @@ class Error_Other extends Error { } /// @nodoc -abstract mixin class $Error_OtherCopyWith<$Res> implements $ErrorCopyWith<$Res> { - factory $Error_OtherCopyWith(Error_Other value, $Res Function(Error_Other) _then) = _$Error_OtherCopyWithImpl; +abstract mixin class $Error_OtherCopyWith<$Res> + implements $ErrorCopyWith<$Res> { + factory $Error_OtherCopyWith( + Error_Other value, $Res Function(Error_Other) _then) = + _$Error_OtherCopyWithImpl; @useResult $Res call({Error field0}); From d4aae4d227ecf4ba98ecca683786855409d4cda2 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Fri, 31 Jul 2026 09:56:17 +0200 Subject: [PATCH 052/189] feat: add one-shot Orchard migration --- build_number.txt | 2 +- lib/pages/migrate.dart | 66 +++++++++++++++++++++++++++++++++++++----- lib/pages/send.dart | 32 +++++--------------- lib/transfer.dart | 51 ++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 33 deletions(-) create mode 100644 lib/transfer.dart diff --git a/build_number.txt b/build_number.txt index ec6cab011..f59a90f39 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -331 +337 diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index 27aad4f3e..c9ed63069 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -6,8 +6,10 @@ import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart' show logger; +import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/migrate.dart'; import 'package:zkool/store.dart'; +import 'package:zkool/transfer.dart'; import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; @@ -167,7 +169,37 @@ class _MigratePageState extends State with WidgetsBindingObserver { ); } on AnyhowException catch (e) { if (!context.mounted) return; - showException(context, e.message); + unawaited(showException(context, e.message)); + } + } + + Future _startOneShotMigration() async { + final confirmed = await confirmDialog( + context, + title: "One-Shot Migration", + message: "This will spend every unlocked Orchard ZEC note worth at least " + "0.00005000 ZEC in one transaction and send their total, minus the " + "network fee, to Ironwood. Smaller notes will remain in Orchard.\n\n" + "This bypasses the privacy-preserving migration workflow. Continue?", + ); + if (!confirmed || !mounted) return; + + try { + final c = coinContext.coin; + final addresses = await getAddresses(uaPools: 4, c: c); + if (!mounted) return; + final pczt = await transferAllBetweenPools( + c: c, + sourcePools: 4, + destinationAddress: addresses.oaddr ?? "", + destinationPools: 8, + ); + if (!mounted) return; + + await GoRouter.of(context).push("/tx", extra: pczt); + } on AnyhowException catch (e) { + if (!mounted) return; + await showException(context, e.message); } } @@ -342,13 +374,31 @@ class _MigratePageState extends State with WidgetsBindingObserver { ), ), const Gap(16), - FilledButton.icon( - onPressed: () { - setState(() => _started = true); - _startMigration(); - }, - icon: const Icon(Icons.play_arrow), - label: const Text("Start Migration"), + Row( + children: [ + Expanded( + child: FilledButton.icon( + onPressed: () { + setState(() => _started = true); + _startMigration(); + }, + icon: const Icon(Icons.play_arrow), + label: const Text("Start Migration"), + ), + ), + const Gap(12), + Expanded( + child: FilledButton.icon( + style: FilledButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.error, + foregroundColor: Theme.of(context).colorScheme.onError, + ), + onPressed: _startOneShotMigration, + icon: const Icon(Icons.warning_amber_rounded), + label: const Text("One Shot"), + ), + ), + ], ), ], ), diff --git a/lib/pages/send.dart b/lib/pages/send.dart index 87a32eb11..75672bca4 100644 --- a/lib/pages/send.dart +++ b/lib/pages/send.dart @@ -22,6 +22,7 @@ import 'package:zkool/src/rust/api/sync.dart'; import 'package:zkool/src/rust/api/zsa.dart'; import 'package:zkool/src/rust/pay.dart'; import 'package:zkool/store.dart'; +import 'package:zkool/transfer.dart'; import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; import 'package:zkool/address_resolver.dart'; @@ -308,21 +309,11 @@ class SendPageState extends ConsumerState { if (!confirmed) return; } try { - final options = PaymentOptions( - srcPools: 1, // Only the transparent pool (mask) - recipientPaysFee: true, - smartTransparent: smartTransparent, - ); - final pczt = await prepare( - recipients: [ - Recipient( - address: addresses?.oaddr ?? addresses?.saddr ?? "", // Shield to Orchard or Sapling address - amount: pbalance?.field0[0] ?? BigInt.zero, - assetBase: zecBase, - ), - ], - options: options, + final pczt = await transferAllBetweenPools( c: c, + sourcePools: 1, + destinationAddress: addresses?.oaddr ?? addresses?.saddr ?? "", + smartTransparent: smartTransparent, ); GoRouter.of(navigatorKey.currentContext!).go("/tx", extra: pczt); @@ -333,17 +324,10 @@ class SendPageState extends ConsumerState { void onUnshield() async { try { - final options = PaymentOptions( - srcPools: 6, // Only the sapling and orchard pool (mask) - recipientPaysFee: true, - smartTransparent: false, - ); - final pczt = await prepare( - recipients: [ - Recipient(address: addresses?.taddr ?? "", amount: (pbalance?.field0[1] ?? BigInt.zero) + (pbalance?.field0[2] ?? BigInt.zero), assetBase: zecBase) - ], - options: options, + final pczt = await transferAllBetweenPools( c: c, + sourcePools: 6, + destinationAddress: addresses?.taddr ?? "", ); GoRouter.of(navigatorKey.currentContext!).go("/tx", extra: pczt); diff --git a/lib/transfer.dart b/lib/transfer.dart new file mode 100644 index 000000000..eb6c1eaeb --- /dev/null +++ b/lib/transfer.dart @@ -0,0 +1,51 @@ +import 'dart:typed_data'; + +import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; + +import 'package:zkool/src/rust/api/account.dart'; +import 'package:zkool/src/rust/api/coin.dart'; +import 'package:zkool/src/rust/api/pay.dart'; +import 'package:zkool/src/rust/pay.dart'; + +Future transferAllBetweenPools({ + required Coin c, + required int sourcePools, + required String destinationAddress, + int? destinationPools, + bool smartTransparent = false, +}) async { + if (destinationAddress.isEmpty) { + throw AnyhowException("Destination address is unavailable."); + } + + final notes = await listNotes(c: c); + final amount = notes + .where( + (note) => + (sourcePools & (1 << note.pool)) != 0 && + !note.locked && + note.idAsset == null && + note.value >= BigInt.from(5000), + ) + .fold(BigInt.zero, (total, note) => total + note.value); + if (amount == BigInt.zero) { + throw AnyhowException("No economically spendable ZEC notes are available."); + } + + return prepare( + recipients: [ + Recipient( + address: destinationAddress, + amount: amount, + pools: destinationPools, + assetBase: Uint8List(32), + ), + ], + options: PaymentOptions( + srcPools: sourcePools, + recipientPaysFee: true, + smartTransparent: smartTransparent, + ), + c: c, + ); +} From b004567fd7cabb826b820259905951f21a433e64 Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Fri, 31 Jul 2026 11:33:02 +0200 Subject: [PATCH 053/189] chore(main): release zkool 6.26.0 (#1186) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 23 +++++++++++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c8e2ff80b..dc998f68e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.25.1" + ".": "6.26.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 94b1a2db1..f37b9b4b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [6.26.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.25.1...zkool-v6.26.0) (2026-07-31) + + +### Features + +* add dust filter toggle for notes (hide ZEC notes <= 5000 zats) ([531e4d8](https://github.com/hhanh00/zkool2/commit/531e4d8d77a9736eaebed9cb404c31db0673ce7d)) +* add group by pool toggle for notes view ([b785872](https://github.com/hhanh00/zkool2/commit/b785872644a2c683ff0c1260cba122dcd87c7d6c)) +* add lock/unlock all button per pool section header ([3e63ea7](https://github.com/hhanh00/zkool2/commit/3e63ea7d022c401a762e456020a854a2944b1aa1)) +* add one-shot Orchard migration ([d4aae4d](https://github.com/hhanh00/zkool2/commit/d4aae4d227ecf4ba98ecca683786855409d4cda2)) +* add toggle all notes button to invert lock state of every note ([ecb0a61](https://github.com/hhanh00/zkool2/commit/ecb0a6116889b4fdc9c057d24d9e98e33fdb35fb)) +* enhance migration with streaming and progress tracking ([71bab2b](https://github.com/hhanh00/zkool2/commit/71bab2b46676d08df269802015fc1d4f37c76832)) +* identify migration txs in history ([b28998e](https://github.com/hhanh00/zkool2/commit/b28998e7ee91cfa435bf99b70e7f90762877022c)) +* improve migration flow ([e448ff4](https://github.com/hhanh00/zkool2/commit/e448ff4c02886559bdb9fefb62a3ebae6888237b)) +* skip migration step when no new blocks since last broadcast ([d025a94](https://github.com/hhanh00/zkool2/commit/d025a9459f11c7d5808807ac1f9e99f5e96f0413)) + + +### Bug Fixes + +* add cancellation support for note migration ([11fe166](https://github.com/hhanh00/zkool2/commit/11fe1665bb30410e003b4be890dbd3505cbb8e78)) +* add error log printer utility ([85d17a1](https://github.com/hhanh00/zkool2/commit/85d17a1118f84c834839a6867f4130d0f30608b6)) +* address review comments ([09ac425](https://github.com/hhanh00/zkool2/commit/09ac4256ed26ef836177e5535a8f1763c667bbd1)) +* confirm before leaving active migration ([961a8a8](https://github.com/hhanh00/zkool2/commit/961a8a8bd905d8d0051bffffe90c5655f504ff56)) + ## [6.25.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.25.0...zkool-v6.25.1) (2026-07-28) diff --git a/build_number.txt b/build_number.txt index f59a90f39..87537f492 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -337 +338 diff --git a/pubspec.yaml b/pubspec.yaml index 683a67993..c7f6cee00 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.25.1 # x-release-please-version +version: 6.26.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 41ce415f3..4c6a35fb6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.25.1 +6.26.0 From cef5160c39f6354f60d40f0c04df8e2a585f1a8b Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 2 Aug 2026 00:50:02 +0200 Subject: [PATCH 054/189] fix: ironwood tx detection in mempool --- rust/src/mempool.rs | 13 +++++++------ tests/tests/test_subscriptions.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/rust/src/mempool.rs b/rust/src/mempool.rs index f9d7589a8..bcc398492 100644 --- a/rust/src/mempool.rs +++ b/rust/src/mempool.rs @@ -3,7 +3,7 @@ use crate::api::mempool::{MempoolAmount, MempoolMsg, MempoolNote, MempoolTx}; use crate::keys::{orchard_scope_to_u8, scope_to_u8}; use anyhow::{Context as _, Result}; use itertools::Itertools; -use orchard::{keys::Scope, note_encryption::OrchardDomain}; +use orchard::{keys::Scope, note_encryption::{IronwoodDomain, OrchardDomain}}; use sapling_crypto::{ keys::PreparedIncomingViewingKey, note_encryption::SaplingDomain, zip32::DiversifiableFullViewingKey, @@ -273,8 +273,9 @@ pub async fn decode_raw_transaction( } macro_rules! process_orchard_bundle { - ($bundle:expr, $flavor:ty) => {{ + ($bundle:expr, $pool:expr, $domain:ident) => {{ let bundle = $bundle; + let pool: u8 = $pool; for v in bundle.actions().iter() { let nf = v.nullifier().to_bytes().to_vec(); let spent_amount = sqlx::query( @@ -300,7 +301,7 @@ pub async fn decode_raw_transaction( .await?; notes.extend(spent_amount); - let domain = OrchardDomain::for_action(v); + let domain = $domain::for_action(v); for (account, name, fvk) in okeys.iter() { for scope in [Scope::External, Scope::Internal] { let ivk = fvk.to_ivk(scope); @@ -320,7 +321,7 @@ pub async fn decode_raw_transaction( account: *account, name: name.clone(), value: note.value().inner() as i64, - pool: 2, + pool, scope: orchard_scope_to_u8(scope), diversifier: Some(diversifier), diversifier_index, @@ -338,7 +339,7 @@ pub async fn decode_raw_transaction( if let Some(obundle) = tx_data.orchard_bundle() { match obundle { OrchardBundle::OrchardVanilla(b) => { - process_orchard_bundle!(b, OrchardVanilla); + process_orchard_bundle!(b, 2, OrchardDomain); } OrchardBundle::OrchardZSA(_b) => { // TODO: ZSA mempool processing @@ -346,7 +347,7 @@ pub async fn decode_raw_transaction( } } if let Some(iwbundle) = tx_data.ironwood_bundle() { - process_orchard_bundle!(iwbundle, OrchardVanilla); + process_orchard_bundle!(iwbundle, 3, IronwoodDomain); } Ok(notes) } diff --git a/tests/tests/test_subscriptions.py b/tests/tests/test_subscriptions.py index 1a5686605..265cd5247 100644 --- a/tests/tests/test_subscriptions.py +++ b/tests/tests/test_subscriptions.py @@ -286,6 +286,37 @@ async def collect_all_events(): print("✓ unconfirmedByAccount API structure is correct") + # Test 1c: the receiver's incoming Ironwood note must be visible + # in the mempool before the transaction is mined + print("\n=== Test 1c: Incoming Ironwood note in unconfirmed API ===") + + result = await client.execute_async( + GraphQLRequest(unconfirmed_query, variable_values={"account": receiver_id}) + ) + receiver_unconfirmed = result["unconfirmedByAccount"] + print(f"Receiver unconfirmed transactions: {len(receiver_unconfirmed)}") + + receiver_notes = [ + note + for tx in receiver_unconfirmed + if tx["txid"].lower() == txid.lower() + for note in tx["notes"] + ] + print(f"Receiver notes for {txid}: {receiver_notes}") + + assert receiver_notes, ( + f"Receiver should see the incoming Ironwood note in unconfirmed, " + f"got {receiver_unconfirmed}" + ) + ironwood_notes = [n for n in receiver_notes if n["pool"] == 3] + assert ironwood_notes, ( + f"Incoming note should be Ironwood (pool 3), got {receiver_notes}" + ) + assert any(n["value"] == "0.01" for n in ironwood_notes), ( + f"Ironwood note should be 0.01, got {ironwood_notes}" + ) + print("✓ Receiver sees the incoming Ironwood note (pool 3, value 0.01)") + # Mine a block height_before = await get_current_height(client) await mine_blocks(rpc_url, 1) From ce74c2fd1e86f1851fe9cfa57ba85357eed4bf14 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sun, 2 Aug 2026 01:41:06 +0200 Subject: [PATCH 055/189] fix: refresh mempool keys after new blocks --- rust/src/mempool.rs | 88 +++++++++++++++---------------- tests/tests/test_jwt.py | 20 +++---- tests/tests/test_subscriptions.py | 11 +++- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/rust/src/mempool.rs b/rust/src/mempool.rs index bcc398492..fb8800266 100644 --- a/rust/src/mempool.rs +++ b/rust/src/mempool.rs @@ -43,53 +43,53 @@ pub async fn run_mempool_impl + Send + 'static>( client: &mut Client, cancel_token: CancellationToken, ) -> Result<()> { - let transparent_accounts = sqlx::query( - r#"SELECT a.id_account, a.name, ta.address FROM accounts a - JOIN transparent_address_accounts ta - ON a.id_account = ta.account"#, - ) - .map(|row: SqliteRow| { - let account: u32 = row.get(0); - let name: String = row.get(1); - let address: String = row.get(2); - let address = TransparentAddress::decode(network, &address).unwrap(); - (account, name, address) - }) - .fetch_all(&mut *connection) - .await - .context("transparent_accounts")?; + 'outer: loop { + let transparent_accounts = sqlx::query( + r#"SELECT a.id_account, a.name, ta.address FROM accounts a + JOIN transparent_address_accounts ta + ON a.id_account = ta.account"#, + ) + .map(|row: SqliteRow| { + let account: u32 = row.get(0); + let name: String = row.get(1); + let address: String = row.get(2); + let address = TransparentAddress::decode(network, &address).unwrap(); + (account, name, address) + }) + .fetch_all(&mut *connection) + .await + .context("transparent_accounts")?; - let sapling_accounts = sqlx::query( - r#"SELECT account, name, xvk FROM accounts a JOIN sapling_accounts s - ON a.id_account = s.account"#, - ) - .map(|row: SqliteRow| { - let account: u32 = row.get(0); - let name: String = row.get(1); - let xvk: Vec = row.get(2); - let fvk = DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap(); - (account, name, fvk) - }) - .fetch_all(&mut *connection) - .await - .context("sapling_accounts")?; + let sapling_accounts = sqlx::query( + r#"SELECT account, name, xvk FROM accounts a JOIN sapling_accounts s + ON a.id_account = s.account"#, + ) + .map(|row: SqliteRow| { + let account: u32 = row.get(0); + let name: String = row.get(1); + let xvk: Vec = row.get(2); + let fvk = DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap(); + (account, name, fvk) + }) + .fetch_all(&mut *connection) + .await + .context("sapling_accounts")?; - let orchard_accounts = sqlx::query( - r#"SELECT account, name, xvk FROM accounts a JOIN orchard_accounts o - ON a.id_account = o.account"#, - ) - .map(|row: SqliteRow| { - let account: u32 = row.get(0); - let name: String = row.get(1); - let xvk: Vec = row.get(2); - let fvk = orchard::keys::FullViewingKey::read(&*xvk).unwrap(); - (account, name, fvk) - }) - .fetch_all(&mut *connection) - .await - .context("orchard_accounts")?; + let orchard_accounts = sqlx::query( + r#"SELECT account, name, xvk FROM accounts a JOIN orchard_accounts o + ON a.id_account = o.account"#, + ) + .map(|row: SqliteRow| { + let account: u32 = row.get(0); + let name: String = row.get(1); + let xvk: Vec = row.get(2); + let fvk = orchard::keys::FullViewingKey::read(&*xvk).unwrap(); + (account, name, fvk) + }) + .fetch_all(&mut *connection) + .await + .context("orchard_accounts")?; - 'outer: loop { let height = client.latest_height().await?; mempool_tx.send(MempoolMsg::BlockHeight(height)).await; diff --git a/tests/tests/test_jwt.py b/tests/tests/test_jwt.py index 29d53713c..c19dde28d 100644 --- a/tests/tests/test_jwt.py +++ b/tests/tests/test_jwt.py @@ -680,7 +680,7 @@ async def stop(self): print(f"Generated new address for account 2") # Test 1: Set up subscriptions for BOTH accounts BEFORE transaction - print("\n--- Test 1: TX events sent to sender only, not receiver ---") + print("\n--- Test 1: TX events sent to sender and receiver ---") # Create subscriptions for both accounts account1_sub = EventSubscription(jwt1_token, account1_id) @@ -742,20 +742,16 @@ async def stop(self): print(f" All events: {account1_sub.events}") assert False, "Account 1 JWT should receive their own account TX events!" - # Check if Account 2 (receiver) received the TX event + # Check if Account 2 (receiver) received the incoming TX event account2_tx_events = [e for e in account2_sub.events if e["type"] == "TX"] print(f"Account 2 (receiver) JWT received {len(account2_tx_events)} TX events") - if account2_tx_events: - print( - f" ERROR: Account 2 should NOT receive TX events for transactions sent TO them!" - ) - for e in account2_tx_events: - print(f" - txid: {e.get('txid')}, value: {e.get('value')}") - assert False, "Account 2 should not receive TX events for incoming transactions!" - else: - print(f" ✓ Account 2 (receiver) correctly did NOT receive the TX event") - print(f" This confirms TX events are sent to the SENDER only") + assert account2_tx_events, "Account 2 should receive incoming TX events!" + assert any( + e.get("txid", "").lower() == txid_from_account1.lower() + for e in account2_tx_events + ), "Account 2 should receive the transaction sent to it" + print(" ✓ Account 2 (receiver) correctly received the incoming TX event") # Stop both subscriptions await account1_sub.stop() diff --git a/tests/tests/test_subscriptions.py b/tests/tests/test_subscriptions.py index 265cd5247..1e1f45e2d 100644 --- a/tests/tests/test_subscriptions.py +++ b/tests/tests/test_subscriptions.py @@ -3,6 +3,7 @@ import asyncio import json import os +from decimal import Decimal import pytest from gql import GraphQLRequest, gql @@ -129,6 +130,14 @@ async def test_websocket_subscriptions( receiver_address = result["addressByAccount"]["ironwood"] print(f"Receiver address: {receiver_address}") + # The mempool monitor reloads account viewing keys when it restarts + # after a new block. Mine a setup block so it sees the receiver + # account before testing the pending transaction. + setup_height = await get_current_height(client) + await mine_blocks(rpc_url, 1) + await wait_for_blocks(client, setup_height, 1) + await asyncio.sleep(3) + print("\n=== Setting up WebSocket subscription ===") import websockets @@ -312,7 +321,7 @@ async def collect_all_events(): assert ironwood_notes, ( f"Incoming note should be Ironwood (pool 3), got {receiver_notes}" ) - assert any(n["value"] == "0.01" for n in ironwood_notes), ( + assert any(Decimal(n["value"]) == Decimal("0.01") for n in ironwood_notes), ( f"Ironwood note should be 0.01, got {ironwood_notes}" ) print("✓ Receiver sees the incoming Ironwood note (pool 3, value 0.01)") From 2d6bdbe4cc76d9b678a6f5815c0b7a1fd0125d1f Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Sun, 2 Aug 2026 05:39:19 +0200 Subject: [PATCH 056/189] chore(main): release zkool 6.26.1 (#1187) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index dc998f68e..1d9a80f42 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.26.0" + ".": "6.26.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index f37b9b4b7..6d275f71b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [6.26.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.26.0...zkool-v6.26.1) (2026-08-02) + + +### Bug Fixes + +* ironwood tx detection in mempool ([cef5160](https://github.com/hhanh00/zkool2/commit/cef5160c39f6354f60d40f0c04df8e2a585f1a8b)) +* refresh mempool keys after new blocks ([ce74c2f](https://github.com/hhanh00/zkool2/commit/ce74c2fd1e86f1851fe9cfa57ba85357eed4bf14)) + ## [6.26.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.25.1...zkool-v6.26.0) (2026-07-31) diff --git a/build_number.txt b/build_number.txt index 87537f492..1ce6b02d7 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -338 +339 diff --git a/pubspec.yaml b/pubspec.yaml index c7f6cee00..d05106902 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.26.0 # x-release-please-version +version: 6.26.1 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 4c6a35fb6..0e10c8e2c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.26.0 +6.26.1 From aba4f3012e6d5c761388fcbd4d452c080d7dc14a Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Thu, 13 Aug 2026 06:37:31 +0800 Subject: [PATCH 057/189] fix: send to TEX (ZIP 320) addresses - decompose_address: extract the P2PKH hash from Bech32m TEX addresses via convert_if_network instead of Base58-decoding the string, which failed on the tex1... prefix (fixes #1194) - send: force the transparent source pool when a TEX recipient is present, regardless of the pool selector form state - tests: TEX address detection on mainnet/testnet vectors --- lib/pages/send.dart | 2 +- rust/src/pay/plan.rs | 31 ++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/pages/send.dart b/lib/pages/send.dart index 75672bca4..70aef512b 100644 --- a/lib/pages/send.dart +++ b/lib/pages/send.dart @@ -832,7 +832,7 @@ class Send2PageState extends ConsumerState { } } - final srcPools = form.fields['source pools']?.value ?? (hasTex ? 1 : 15); + final srcPools = hasTex ? 1 : (form.fields['source pools']?.value ?? 15); try { final options = PaymentOptions( diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index fdb4a4a29..19aac0388 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -186,11 +186,16 @@ fn decompose_address( let zaddr = ZcashAddress::try_from_encoded(address)?; if zaddr.can_receive_as(PoolType::Transparent) { - let taddr = TransparentAddress::decode(network, address) - .map_err(|e| anyhow!("Failed to decode transparent address: {e:?}"))?; - let receiver = match taddr { - TransparentAddress::PublicKeyHash(hash) => Receiver::P2pkh(hash), - TransparentAddress::ScriptHash(hash) => Receiver::P2sh(hash), + let receiver = match zaddr.convert_if_network(network.network_type()) { + Ok(zcash_keys::address::Address::Tex(data)) => Receiver::P2pkh(data), + _ => { + let taddr = TransparentAddress::decode(network, address) + .map_err(|e| anyhow!("Failed to decode transparent address: {e:?}"))?; + match taddr { + TransparentAddress::PublicKeyHash(hash) => Receiver::P2pkh(hash), + TransparentAddress::ScriptHash(hash) => Receiver::P2sh(hash), + } + } }; return Ok(ReceiverOption { receiver, @@ -1622,4 +1627,20 @@ mod tests { OrchardProvingKeyKind::Zsa, ); } + + #[test] + fn tex_addresses_are_detected() { + use super::is_tex; + use crate::api::coin::Network; + // Test vectors from zcash_address encoding.rs (same hash as the + // t1.../tm... P2PKH addresses on the same line). + assert!(is_tex(&Network::Main, "tex1s2rt77ggv6q989lr49rkgzmh5slsksa9khdgte").unwrap()); + assert!(!is_tex(&Network::Main, "t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC").unwrap()); + assert!(is_tex( + &Network::Test, + "textest1qyqszqgpqyqszqgpqyqszqgpqyqszqgpfcjgfy" + ) + .unwrap()); + assert!(!is_tex(&Network::Test, "tm9ofD7kHR7AF8MsJomEzLqGcrLCBkD9gDj").unwrap()); + } } From ca4941250d2dfac13832d40066062cf6915ba579 Mon Sep 17 00:00:00 2001 From: Mladen Markov Date: Thu, 13 Aug 2026 03:16:10 +0300 Subject: [PATCH 058/189] fix: honour RUST_LOG in zkool_graphql (#1190) The tracing subscriber is built without an EnvFilter, which pins it at INFO and silently discards RUST_LOG. None of the debug! instrumentation in the sync path can ever be observed, which makes diagnosing sync problems considerably harder than it needs to be. Falls back to info when RUST_LOG is unset, so default behaviour is unchanged. Co-authored-by: Claude Opus 5 (1M context) Co-authored-by: hhanh00 --- rust/src/graphql-cli.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/src/graphql-cli.rs b/rust/src/graphql-cli.rs index 234483f2c..1c3b57155 100644 --- a/rust/src/graphql-cli.rs +++ b/rust/src/graphql-cli.rs @@ -60,8 +60,14 @@ async fn main() -> Result<()> { rustls::crypto::ring::default_provider() .install_default() .unwrap(); + // Without an EnvFilter the subscriber is pinned at INFO and RUST_LOG is + // silently ignored, so no debug! output from the sync path is ever visible. let subscriber = tracing_subscriber::fmt() .with_ansi(false) + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), + ) .compact() .finish(); let c = Config::parse(); From b59f958915696bf3d50af590ac6ca0e765ab23cd Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Sat, 15 Aug 2026 05:54:13 +0800 Subject: [PATCH 059/189] feat: Zcash voting (ZIP 262) delegation and vote casting (#1198) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rust/src/voting.rs: core module — hotkey create/load, wallet_id, round-input gathering (Ironwood notes + snapshot-rooted witnesses), delegation keys/signing, prove-and-submit, vote flow, prepared-bundle cache - rust/src/api/voting.rs: FRB wrappers with JSON mirror structs for the delegation and vote-casting steps - zcash_voting pinned to fd4362b0 (caller-supplied input boundary, embedded voting DB, Send-safe batch execution) - regenerated flutter_rust_bridge bindings --- Cargo.lock | 778 ++- Cargo.toml | 3 + lib/src/rust/api/voting.dart | 305 ++ lib/src/rust/api/voting.freezed.dart | 5344 +++++++++++++++++++ lib/src/rust/frb_generated.dart | 7312 ++++++++++++++++---------- lib/src/rust/frb_generated.io.dart | 192 + lib/src/rust/frb_generated.web.dart | 192 + lib/store.freezed.dart | 781 ++- lib/store.g.dart | 291 +- rust/Cargo.toml | 1 + rust/src/api/mod.rs | 1 + rust/src/api/voting.rs | 615 +++ rust/src/frb_generated.rs | 3178 +++++++---- rust/src/lib.rs | 1 + rust/src/voting.rs | 550 ++ 15 files changed, 15257 insertions(+), 4287 deletions(-) create mode 100644 lib/src/rust/api/voting.dart create mode 100644 lib/src/rust/api/voting.freezed.dart create mode 100644 rust/src/api/voting.rs create mode 100644 rust/src/voting.rs diff --git a/Cargo.lock b/Cargo.lock index 132a3f5fb..5bd4fff78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -330,7 +330,7 @@ dependencies = [ "rand 0.9.5", "safelog", "serde", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tor-async-utils", "tor-basic-utils", @@ -375,7 +375,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -432,9 +432,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +checksum = "3976abdc8fe7d1133d43d304afd42abdf5bc3e1319d263d223bde07b5efc4be8" dependencies = [ "compression-codecs", "compression-core", @@ -495,7 +495,7 @@ version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener 5.4.1", + "event-listener 5.4.2", "event-listener-strategy", "pin-project-lite 0.2.17", ] @@ -546,9 +546,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.91" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", @@ -651,9 +651,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.17.3" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bdb5da18dac48ca2cc7cd4a98e533e8635a58e2361d13a1a4ee3888e0d72f1" +checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -662,9 +662,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.43.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43103168cc76fe62678a375e722fc9cb3a0146159ac5828bc4f0dfd755c2224c" +checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483" dependencies = [ "cc", "cmake", @@ -682,7 +682,7 @@ dependencies = [ "axum-core", "bytes 1.12.1", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "http-body-util", "itoa", @@ -706,7 +706,7 @@ checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes 1.12.1", "futures-core", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "http-body-util", "mime", @@ -998,7 +998,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09dc0086e469182132244e9b8d313a0742e1132da43a08c24b9dd3c18e0faf3a" dependencies = [ - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -1019,9 +1019,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" dependencies = [ "memchr", "regex-automata", @@ -1102,9 +1102,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" dependencies = [ "find-msvc-tools", "jobserver", @@ -1192,9 +1192,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.4" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -1202,9 +1202,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.2" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -1265,7 +1265,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -1695,9 +1695,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" [[package]] name = "dataloader" @@ -1742,18 +1742,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] name = "delegate-attr" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" +checksum = "a84c9a9c129b98e707ac9a31e204c10c064dd9f949b7da362310ff1a8b137d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -1960,13 +1960,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -2200,11 +2200,10 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite 0.2.17", ] @@ -2215,7 +2214,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.1", + "event-listener 5.4.2", "pin-project-lite 0.2.17", ] @@ -2296,9 +2295,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" @@ -2368,6 +2373,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", + "nanorand", "spin 0.9.9", ] @@ -2506,7 +2512,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect", - "thiserror 2.0.19", + "thiserror 2.0.20", "visibility", "zeroize", ] @@ -2536,7 +2542,7 @@ dependencies = [ "once_cell", "pwd-grp", "serde", - "thiserror 2.0.19", + "thiserror 2.0.20", "walkdir", ] @@ -2586,9 +2592,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -2601,9 +2607,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -2611,15 +2617,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -2639,9 +2645,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-lite" @@ -2658,32 +2664,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] name = "futures-sink" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -2869,7 +2875,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.4.2", + "http 1.5.0", "indexmap 2.14.0", "slab", "tokio 1.53.1", @@ -2997,7 +3003,7 @@ dependencies = [ "base64 0.22.1", "bytes 1.12.1", "headers-core", - "http 1.4.2", + "http 1.5.0", "httpdate", "mime", "sha1", @@ -3009,7 +3015,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.4.2", + "http 1.5.0", ] [[package]] @@ -3181,9 +3187,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes 1.12.1", "itoa", @@ -3207,18 +3213,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes 1.12.1", - "http 1.4.2", + "http 1.5.0", ] [[package]] name = "http-body-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes 1.12.1", "futures-core", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "pin-project-lite 0.2.17", ] @@ -3314,7 +3320,7 @@ dependencies = [ "futures-channel", "futures-core", "h2 0.4.15", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "httparse", "httpdate", @@ -3331,10 +3337,10 @@ version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "http 1.4.2", + "http 1.5.0", "hyper 1.11.0", "hyper-util", - "rustls 0.23.42", + "rustls 0.23.43", "tokio 1.53.1", "tokio-rustls", "tower-service", @@ -3377,7 +3383,7 @@ dependencies = [ "bytes 1.12.1", "futures-channel", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "hyper 1.11.0", "ipnet", @@ -3601,6 +3607,20 @@ dependencies = [ "num-traits", ] +[[package]] +name = "imt-tree" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aad3e3ab5a46f4a08d00f5525b86cd0d5204cba64ba68f46e20a590e1808aec" +dependencies = [ + "anyhow", + "ff", + "halo2_gadgets", + "hex", + "pasta_curves", + "rayon", +] + [[package]] name = "incrementalmerkletree" version = "0.8.2" @@ -3731,9 +3751,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" [[package]] name = "is_terminal_polyfill" @@ -3767,17 +3787,19 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" dependencies = [ "defmt", "jiff-core", "jiff-static", + "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", + "windows-link", ] [[package]] @@ -3791,9 +3813,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" dependencies = [ "jiff-core", "proc-macro2", @@ -3801,6 +3823,21 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "jobserver" version = "0.1.35" @@ -3813,9 +3850,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if 1.0.4", "futures-util", @@ -3962,9 +3999,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5" +checksum = "8d763e5b24120b4ddf50de6c92308156765aabfbbccebf401da7cff2d70a41ea" dependencies = [ "kqueue-sys", "libc", @@ -4046,18 +4083,18 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "liblzma" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45aec2360b3933207e27908049d8e4df4e476b58180afb1e56b2a4fb72efe4ba" +checksum = "2fe0a34ca854fd4f20c07f696fc8675aec78f87d88d29f5e10257a7490a1b2e1" dependencies = [ "liblzma-sys", ] [[package]] name = "liblzma-sys" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a046c7f353ba30f810545151e04f63545833803f5b86ee3ddf1517247fe560a5" +checksum = "a0dad045e4b1b7b170be4b60b54b780cafb4490165461bac7d1cf7b703f61d5f" dependencies = [ "cc", "libc", @@ -4072,9 +4109,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa" dependencies = [ "libc", ] @@ -4371,6 +4408,21 @@ dependencies = [ "pxfm", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.17", +] + [[package]] name = "native-tls" version = "0.2.18" @@ -4505,9 +4557,9 @@ checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" dependencies = [ "num-traits", ] @@ -4898,6 +4950,17 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap 2.14.0", +] + [[package]] name = "phf" version = "0.11.3" @@ -4989,6 +5052,38 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pir-client" +version = "0.4.0-rc.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6547ec35c8d4af154bc73d60fe2773be50f7c089e79414983d721d0dbc13db" +dependencies = [ + "anyhow", + "ff", + "futures", + "hex", + "imt-tree", + "log", + "pasta_curves", + "pir-types", + "serde_json", + "tokio 1.53.1", + "valar-ypir", +] + +[[package]] +name = "pir-types" +version = "0.3.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f3dd9f975f28591b07af57cca89804650c38fa66051cf12f34d664f7ea2ac6" +dependencies = [ + "anyhow", + "ff", + "imt-tree", + "pasta_curves", + "serde", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -5043,9 +5138,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" @@ -5108,6 +5203,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -5178,6 +5283,25 @@ dependencies = [ "prost-derive", ] +[[package]] +name = "prost-build" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" +dependencies = [ + "heck 0.5.0", + "itertools 0.14.0", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.119", + "tempfile", +] + [[package]] name = "prost-derive" version = "0.14.4" @@ -5191,6 +5315,15 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "prost-types" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" +dependencies = [ + "prost", +] + [[package]] name = "protobuf" version = "2.18.2" @@ -5216,7 +5349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c6edf525f5fa5a304eb9d64cd3d0c4656fd33755b49fcea145a49d131cc291" dependencies = [ "log", - "which", + "which 4.4.2", ] [[package]] @@ -5253,7 +5386,7 @@ dependencies = [ "derive-deftly", "libc", "paste", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -5283,9 +5416,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.3", - "rustls 0.23.42", + "rustls 0.23.43", "socket2 0.6.5", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio 1.53.1", "tracing", "web-time", @@ -5304,10 +5437,10 @@ dependencies = [ "rand_pcg 0.10.2", "ring", "rustc-hash 2.1.3", - "rustls 0.23.42", + "rustls 0.23.43", "rustls-pki-types", "slab", - "thiserror 2.0.19", + "thiserror 2.0.20", "tinyvec", "tracing", "web-time", @@ -5640,7 +5773,7 @@ dependencies = [ "pasta_curves", "rand_core 0.6.4", "serde", - "thiserror 2.0.19", + "thiserror 2.0.20", "zeroize", ] @@ -5674,7 +5807,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -5703,7 +5836,7 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ - "aho-corasick 1.1.4", + "aho-corasick 1.1.5", "memchr", "regex-automata", "regex-syntax 0.8.11", @@ -5711,11 +5844,11 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ - "aho-corasick 1.1.4", + "aho-corasick 1.1.5", "memchr", "regex-syntax 0.8.11", ] @@ -5790,7 +5923,7 @@ dependencies = [ "base64 0.22.1", "bytes 1.12.1", "futures-core", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "http-body-util", "hyper 1.11.0", @@ -5801,7 +5934,7 @@ dependencies = [ "percent-encoding", "pin-project-lite 0.2.17", "quinn", - "rustls 0.23.42", + "rustls 0.23.43", "rustls-pki-types", "serde", "serde_json", @@ -5968,7 +6101,7 @@ dependencies = [ "reqwest 0.12.28", "rhai", "ripemd 0.1.3", - "rustls 0.23.42", + "rustls 0.23.43", "sapling-crypto", "secp256k1", "serde", @@ -5976,7 +6109,7 @@ dependencies = [ "serde_with", "sha2 0.10.9", "sqlx", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio 1.53.1", "tokio-rustls", "tokio-socks", @@ -6002,6 +6135,7 @@ dependencies = [ "zcash_protocol", "zcash_script", "zcash_transparent", + "zcash_voting", "zip", "zip32", "zip321", @@ -6154,16 +6288,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.42" +version = "0.23.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.13", + "rustls-webpki 0.103.14", "subtle", "zeroize", ] @@ -6199,9 +6333,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.103.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" dependencies = [ "aws-lc-rs", "ring", @@ -6231,7 +6365,7 @@ dependencies = [ "educe", "either", "fluid-let", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -6322,9 +6456,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" dependencies = [ "dyn-clone", "ref-cast", @@ -6546,9 +6680,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.21.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" dependencies = [ "base64 0.22.1", "bs58", @@ -6556,8 +6690,9 @@ dependencies = [ "hex", "indexmap 1.9.3", "indexmap 2.14.0", + "jiff", "schemars 0.9.0", - "schemars 1.2.1", + "schemars 1.2.2", "serde_core", "serde_json", "serde_with_macros", @@ -6566,9 +6701,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.21.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" +checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -6638,6 +6773,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shardtree" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8147447aed7be4736e271825b8c3a4432efb7182e71363169b572371ddef452e" +dependencies = [ + "bitflags 2.13.1", + "either", + "incrementalmerkletree", + "tracing", +] + [[package]] name = "shellexpand" version = "3.1.2" @@ -6689,7 +6836,7 @@ checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", ] @@ -6734,7 +6881,7 @@ dependencies = [ "paste", "serde", "slotmap", - "thiserror 2.0.19", + "thiserror 2.0.20", "void", ] @@ -6848,7 +6995,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener 5.4.1", + "event-listener 5.4.2", "futures-core", "futures-intrusive", "futures-io", @@ -6863,7 +7010,7 @@ dependencies = [ "serde", "sha2 0.10.9", "smallvec", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio 1.53.1", "tokio-stream", "tracing", @@ -6925,7 +7072,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.19", + "thiserror 2.0.20", "tracing", "url", ] @@ -7133,9 +7280,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482" +checksum = "79def32ffcd477db1ff26f76dab9e3a91f0bd42a85ca96577089b24623056f9d" dependencies = [ "serde", ] @@ -7151,11 +7298,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.19", + "thiserror-impl 2.0.20", ] [[package]] @@ -7171,9 +7318,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", @@ -7200,9 +7347,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", "num-conv", @@ -7319,13 +7466,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -7344,7 +7491,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.42", + "rustls 0.23.43", "tokio 1.53.1", ] @@ -7465,9 +7612,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow 1.0.4", ] @@ -7489,7 +7636,7 @@ dependencies = [ "base64 0.22.1", "bytes 1.12.1", "h2 0.4.15", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "http-body-util", "hyper 1.11.0", @@ -7509,6 +7656,18 @@ dependencies = [ "webpki-roots 1.0.9", ] +[[package]] +name = "tonic-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "tonic-prost" version = "0.14.6" @@ -7520,6 +7679,22 @@ dependencies = [ "tonic", ] +[[package]] +name = "tonic-prost-build" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.119", + "tempfile", + "tonic-build", +] + [[package]] name = "tor-async-utils" version = "0.31.0" @@ -7532,7 +7707,7 @@ dependencies = [ "oneshot-fused-workaround", "pin-project", "postage", - "thiserror 2.0.19", + "thiserror 2.0.20", "void", ] @@ -7552,7 +7727,7 @@ dependencies = [ "serde", "slab", "smallvec", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -7567,7 +7742,7 @@ dependencies = [ "educe", "getrandom 0.3.4", "safelog", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-error", "tor-llcrypto", "zeroize", @@ -7589,7 +7764,7 @@ dependencies = [ "paste", "rand 0.9.5", "smallvec", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", "tor-cert", @@ -7613,7 +7788,7 @@ dependencies = [ "derive_builder_fork_arti", "derive_more", "digest 0.10.7", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-bytes", "tor-checkable", "tor-llcrypto", @@ -7636,7 +7811,7 @@ dependencies = [ "rand 0.9.5", "safelog", "serde", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", "tor-cell", @@ -7662,7 +7837,7 @@ checksum = "55af8d517e87c07f385bbdf8ea1fdd6e71830ecba5285b9a7bb249f7e4e47a85" dependencies = [ "humantime", "signature", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-llcrypto", ] @@ -7692,7 +7867,7 @@ dependencies = [ "safelog", "serde", "static_assertions", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", "tor-chanmgr", @@ -7739,7 +7914,7 @@ dependencies = [ "serde-value", "serde_ignored", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "toml 0.8.23", "tor-basic-utils", "tor-error", @@ -7758,7 +7933,7 @@ dependencies = [ "once_cell", "serde", "shellexpand", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-error", "tor-general-addr", ] @@ -7771,7 +7946,7 @@ checksum = "2da1b81654807c5652286cb9bfad117c0cc0f7a58f945f34fb6be30d10eb071c" dependencies = [ "digest 0.10.7", "hex", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-llcrypto", ] @@ -7786,12 +7961,12 @@ dependencies = [ "derive_more", "futures", "hex", - "http 1.4.2", + "http 1.5.0", "httparse", "httpdate", "itertools 0.14.0", "memchr", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-circmgr", "tor-error", "tor-hscrypto", @@ -7815,7 +7990,7 @@ dependencies = [ "derive_more", "digest 0.10.7", "educe", - "event-listener 5.4.1", + "event-listener 5.4.2", "fs-mistrust", "fslock", "futures", @@ -7837,7 +8012,7 @@ dependencies = [ "signature", "static_assertions", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tor-async-utils", "tor-basic-utils", @@ -7871,7 +8046,7 @@ dependencies = [ "retry-error", "static_assertions", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "tracing", "void", ] @@ -7883,7 +8058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be71b2de02947b2f8711881fe7262002b8ac2c7283937c8d7144d0a902ce7fe2" dependencies = [ "derive_more", - "thiserror 2.0.19", + "thiserror 2.0.20", "void", ] @@ -7912,7 +8087,7 @@ dependencies = [ "safelog", "serde", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", "tor-config", @@ -7949,7 +8124,7 @@ dependencies = [ "safelog", "slotmap-careful", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", "tor-bytes", @@ -7992,7 +8167,7 @@ dependencies = [ "serde", "signature", "subtle", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", "tor-error", @@ -8016,7 +8191,7 @@ dependencies = [ "rand 0.9.5", "signature", "ssh-key", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-bytes", "tor-cert", "tor-checkable", @@ -8047,7 +8222,7 @@ dependencies = [ "serde", "signature", "ssh-key", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", "tor-config", @@ -8080,7 +8255,7 @@ dependencies = [ "serde", "serde_with", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", "tor-config", @@ -8122,7 +8297,7 @@ dependencies = [ "sha3", "signature", "subtle", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-memquota", "visibility", "x25519-dalek", @@ -8138,7 +8313,7 @@ dependencies = [ "futures", "humantime", "once_cell", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-error", "tor-rtcompat", "tracing", @@ -8162,7 +8337,7 @@ dependencies = [ "serde", "slotmap-careful", "static_assertions", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", "tor-config", @@ -8192,7 +8367,7 @@ dependencies = [ "serde", "static_assertions", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tor-basic-utils", "tor-error", @@ -8232,7 +8407,7 @@ dependencies = [ "signature", "smallvec", "subtle", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tinystr", "tor-basic-utils", @@ -8269,7 +8444,7 @@ dependencies = [ "sanitize-filename", "serde", "serde_json", - "thiserror 2.0.19", + "thiserror 2.0.20", "time", "tor-async-utils", "tor-basic-utils", @@ -8310,7 +8485,7 @@ dependencies = [ "slotmap-careful", "static_assertions", "subtle", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio 1.53.1", "tokio-util", "tor-async-utils", @@ -8346,7 +8521,7 @@ dependencies = [ "caret", "paste", "serde_with", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-bytes", ] @@ -8384,7 +8559,7 @@ dependencies = [ "native-tls", "paste", "pin-project", - "thiserror 2.0.19", + "thiserror 2.0.20", "tokio 1.53.1", "tokio-util", "tor-error", @@ -8413,7 +8588,7 @@ dependencies = [ "priority-queue", "slotmap-careful", "strum", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-error", "tor-general-addr", "tor-rtcompat", @@ -8434,7 +8609,7 @@ dependencies = [ "educe", "safelog", "subtle", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-bytes", "tor-error", ] @@ -8448,7 +8623,7 @@ dependencies = [ "derive-deftly", "derive_more", "serde", - "thiserror 2.0.19", + "thiserror 2.0.20", "tor-memquota", ] @@ -8480,7 +8655,7 @@ dependencies = [ "bitflags 2.13.1", "bytes 1.12.1", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "pin-project-lite 0.2.17", "tower", @@ -8611,12 +8786,12 @@ checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" dependencies = [ "bytes 1.12.1", "data-encoding", - "http 1.4.2", + "http 1.5.0", "httparse", "log", "rand 0.9.5", "sha1", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -8797,6 +8972,38 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valar-spiral-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "208d4b69c6a9b7b0c7d856133009a514e10236cdc698ad0b6b87f2e3c4e6d9cb" +dependencies = [ + "fastrand", + "getrandom 0.2.17", + "rand 0.8.7", + "rand_chacha 0.3.1", + "serde_json", + "sha2 0.10.9", + "subtle", +] + +[[package]] +name = "valar-ypir" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06a0e6155d97d9e2df44a7f552383a311fbcb5528dfc93e9b3236c98184eb840" +dependencies = [ + "cc", + "fastrand", + "log", + "rand 0.8.7", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "sha1", + "valar-spiral-rs", +] + [[package]] name = "valuable" version = "0.1.1" @@ -8805,9 +9012,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef73bfbaf3216cb59c205d7176bee1194e0d84348979da31f4a71fefe3c2054e" +checksum = "068e763e8279de7ab94b6afebded2cb701678af094feb1c12ccb061b4783c1be" [[package]] name = "vcard4" @@ -8860,6 +9067,57 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "vote-commitment-tree" +version = "0.4.0-rc.2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +dependencies = [ + "anyhow", + "ff", + "halo2_gadgets", + "imt-tree", + "incrementalmerkletree", + "lazy_static", + "libc", + "pasta_curves", + "shardtree", +] + +[[package]] +name = "vote-commitment-tree-client" +version = "0.6.0-rc.2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +dependencies = [ + "base64 0.22.1", + "ff", + "hex", + "pasta_curves", + "serde", + "serde_json", + "thiserror 2.0.20", + "vote-commitment-tree", +] + +[[package]] +name = "voting-circuits" +version = "0.9.0-rc.3" +source = "git+https://github.com/hhanh00/voting-circuits.git?rev=9b408e712f8a2db8ca0b006846b310c6fd994941#9b408e712f8a2db8ca0b006846b310c6fd994941" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "halo2_gadgets", + "halo2_poseidon", + "halo2_proofs", + "incrementalmerkletree", + "itertools 0.14.0", + "lazy_static", + "orchard", + "pasta_curves", + "rand 0.8.7", + "sinsemilla", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -8888,7 +9146,7 @@ dependencies = [ "bytes 1.12.1", "futures-util", "headers", - "http 1.4.2", + "http 1.5.0", "http-body 1.1.0", "http-body-util", "hyper 1.11.0", @@ -8935,9 +9193,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if 1.0.4", "once_cell", @@ -8948,9 +9206,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.76" +version = "0.4.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" dependencies = [ "js-sys", "wasm-bindgen", @@ -8958,9 +9216,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8968,9 +9226,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", @@ -8981,9 +9239,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] @@ -8996,9 +9254,9 @@ checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" [[package]] name = "web-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", @@ -9041,6 +9299,15 @@ dependencies = [ "rustix 0.38.44", ] +[[package]] +name = "which" +version = "8.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3ef584124b911bcc3875c2f1472e80f24361ceb789bd1c62b3e9a3df9ff43c" +dependencies = [ + "libc", +] + [[package]] name = "widestring" version = "1.2.1" @@ -9508,7 +9775,7 @@ dependencies = [ "rayon", "sapling-crypto", "secp256k1", - "thiserror 2.0.19", + "thiserror 2.0.20", "zcash_encoding 0.5.0", "zcash_protocol", "zcash_transparent", @@ -9528,6 +9795,52 @@ dependencies = [ "zcash_protocol", ] +[[package]] +name = "zcash_client_backend" +version = "0.24.0-rc.3" +source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" +dependencies = [ + "base64 0.22.1", + "bech32 0.11.1", + "bls12_381", + "bs58", + "document-features", + "flume", + "getset", + "group", + "hex", + "hyper-util", + "incrementalmerkletree", + "memuse", + "nonempty", + "orchard", + "pasta_curves", + "percent-encoding", + "prost", + "rand_core 0.6.4", + "rayon", + "sapling-crypto", + "secrecy 0.8.0", + "shardtree", + "subtle", + "time", + "tonic", + "tonic-prost", + "tonic-prost-build", + "tracing", + "which 8.0.5", + "zcash_address", + "zcash_encoding 0.4.0", + "zcash_keys", + "zcash_note_encryption", + "zcash_primitives", + "zcash_protocol", + "zcash_script", + "zcash_transparent", + "zip32", + "zip321", +] + [[package]] name = "zcash_encoding" version = "0.4.0" @@ -9667,7 +9980,7 @@ dependencies = [ "secp256k1", "sha1", "sha2 0.10.9", - "thiserror 2.0.19", + "thiserror 2.0.20", ] [[package]] @@ -9702,20 +10015,73 @@ dependencies = [ "zip32", ] +[[package]] +name = "zcash_voting" +version = "2.0.0-rc.5" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +dependencies = [ + "anyhow", + "base64 0.22.1", + "blake2b_simd", + "bytes 1.12.1", + "ed25519-dalek", + "ff", + "group", + "halo2_gadgets", + "halo2_proofs", + "hex", + "http 1.5.0", + "http-body-util", + "hyper 1.11.0", + "hyper-rustls", + "hyper-util", + "imt-tree", + "incrementalmerkletree", + "nonempty", + "orchard", + "pasta_curves", + "pczt", + "pir-client", + "pir-types", + "prost", + "rand 0.8.7", + "rustls 0.23.43", + "serde", + "serde_json", + "sha2 0.10.9", + "sinsemilla", + "sqlx", + "subtle", + "thiserror 2.0.20", + "tokio 1.53.1", + "tonic", + "valar-spiral-rs", + "valar-ypir", + "vote-commitment-tree", + "vote-commitment-tree-client", + "voting-circuits", + "zcash_client_backend", + "zcash_keys", + "zcash_primitives", + "zcash_protocol", + "zeroize", + "zip32", +] + [[package]] name = "zerocopy" -version = "0.8.55" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.55" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" dependencies = [ "proc-macro2", "quote", @@ -9810,7 +10176,7 @@ dependencies = [ "flate2", "indexmap 2.14.0", "memchr", - "thiserror 2.0.19", + "thiserror 2.0.20", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index 777c0ae1e..575abd80e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ zcash_note_encryption = { git = "https://github.com/zcash-shielded-assets/zcash_ # -- lrz ZSA branch -- pczt = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } +zcash_client_backend = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } zcash_address = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } zcash_encoding = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } zcash_keys = { git = "https://github.com/zcash-shielded-assets/librustzcash", rev = "3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" } @@ -40,3 +41,5 @@ zcash_spec = { git = "https://github.com/zcash-shielded-assets/zcash_spec", rev halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } +voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev = "9b408e712f8a2db8ca0b006846b310c6fd994941" } + diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart new file mode 100644 index 000000000..562308a1f --- /dev/null +++ b/lib/src/rust/api/voting.dart @@ -0,0 +1,305 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'coin.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:freezed_annotation/freezed_annotation.dart' hide protected; +part 'voting.freezed.dart'; + +// These functions are ignored because they are not marked as `pub`: `to_fork` +// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `VotingShareDelivery` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` + +/// Creates and persists a fresh app-owned voting hotkey (hex stored secret). +Future votingHotkeyCreate({required Coin c}) => + RustLib.instance.api.crateApiVotingVotingHotkeyCreate(c: c); + +/// Returns the persisted voting hotkey stored secret (hex), if any. +Future votingHotkeyGet({required Coin c}) => + RustLib.instance.api.crateApiVotingVotingHotkeyGet(c: c); + +/// Prepares one delegation bundle from the wallet's own Ironwood notes. +/// +/// `round_params_json` is the JSON-serialized `VotingRoundParams` from the +/// vote chain. The wallet must be synced through the round snapshot height; +/// witnesses are rooted at the snapshot's Ironwood `nc_root`. +Future delegationPrepare( + {required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationPrepare( + roundParamsJson: roundParamsJson, + roundName: roundName, + sessionJson: sessionJson, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c); + +/// Builds and persists the governance PCZT setup for a prepared bundle. +Future delegationSetup( + {required String roundId, required int bundleIndex, required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationSetup( + roundId: roundId, bundleIndex: bundleIndex, c: c); + +/// Signs with the wallet seed, proves against the PIR server, and assembles +/// the chain-ready delegation submission for the vote chain. +Future delegationSignAndSubmit( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationSignAndSubmit( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: pcztBytes, + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c); + +/// Records a confirmed delegation transaction and persists the bundle's VAN +/// position (required before any vote). +Future delegationConfirm( + {required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: txHash, + eventsJson: eventsJson, + c: c); + +/// Syncs the vote-authority-note tree and derives this bundle's VAN witness. +Future votingVanWitness( + {required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingVanWitness( + roundId: roundId, + bundleIndex: bundleIndex, + voteNodeUrl: voteNodeUrl, + c: c); + +/// Commits a batch of vote drafts for one bundle (hotkey-signed). +/// +/// Chains the VAN witness derivation internally, so this may be called right +/// after `voting_van_witness` or standalone. +Future votingCommit( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingCommit( + roundId: roundId, + bundleIndex: bundleIndex, + draftsJson: draftsJson, + voteNodeUrl: voteNodeUrl, + c: c); + +/// Returns the chain-ready vote submission and helper-share payloads for one +/// committed vote. +Future votingPayloads( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingPayloads( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c); + +/// Records successful vote-chain and helper-share submissions for one vote. +Future votingRecordExecution( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRecordExecution( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + voteTxHash: voteTxHash, + vcTreePosition: vcTreePosition, + shareDeliveriesJson: shareDeliveriesJson, + c: c); + +/// Records a confirmed cast-vote transaction. +Future votingConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + eventsJson: eventsJson, + c: c); + +@freezed +sealed class VotingDelegationConfirmation with _$VotingDelegationConfirmation { + const factory VotingDelegationConfirmation({ + required String txHash, + required int vanLeafPosition, + }) = _VotingDelegationConfirmation; +} + +@freezed +sealed class VotingDelegationSetup with _$VotingDelegationSetup { + const factory VotingDelegationSetup({ + required Uint8List pcztBytes, + required Uint8List pcztSighash, + required Uint8List rk, + required int actionIndex, + required Uint8List actionBytes, + required Uint8List tx1Effects, + }) = _VotingDelegationSetup; +} + +@freezed +sealed class VotingDelegationSubmission with _$VotingDelegationSubmission { + const factory VotingDelegationSubmission({ + required Uint8List proof, + required Uint8List rk, + required Uint8List nfSigned, + required Uint8List cmxNew, + required Uint8List govComm, + required List govNullifiers, + required Uint8List alpha, + required String voteRoundId, + required Uint8List spendAuthSig, + required Uint8List sighash, + required Uint8List tx1Effects, + }) = _VotingDelegationSubmission; +} + +@freezed +sealed class VotingEncryptedShare with _$VotingEncryptedShare { + const factory VotingEncryptedShare({ + required Uint8List c1, + required Uint8List c2, + required int shareIndex, + }) = _VotingEncryptedShare; +} + +@freezed +sealed class VotingPirLayout with _$VotingPirLayout { + const factory VotingPirLayout({ + required int pirDepth, + required int tier0Layers, + required int tier1Layers, + required int polyLen, + }) = _VotingPirLayout; +} + +@freezed +sealed class VotingPreparedInfo with _$VotingPreparedInfo { + const factory VotingPreparedInfo({ + required String roundId, + required int bundleIndex, + required BigInt eligibleWeightZatoshi, + required BigInt delegatedWeightZatoshi, + required String roundName, + }) = _VotingPreparedInfo; +} + +@freezed +sealed class VotingSharePayload with _$VotingSharePayload { + const factory VotingSharePayload({ + required Uint8List sharesHash, + required int proposalId, + required int voteDecision, + required VotingEncryptedShare encShare, + required BigInt treePosition, + required List allEncShares, + required List shareComms, + required Uint8List primaryBlind, + }) = _VotingSharePayload; +} + +@freezed +sealed class VotingSignedVoteCommitment with _$VotingSignedVoteCommitment { + const factory VotingSignedVoteCommitment({ + required int proposalId, + required int choice, + required String voteRoundId, + required Uint8List vanNullifier, + required Uint8List voteAuthorityNoteNew, + required Uint8List voteCommitment, + required Uint8List proof, + required int anchorHeight, + required Uint8List rVpk, + required Uint8List voteAuthSig, + required String commitmentBundleJson, + }) = _VotingSignedVoteCommitment; +} + +@freezed +sealed class VotingVanWitness with _$VotingVanWitness { + const factory VotingVanWitness({ + required List authPath, + required int position, + required int anchorHeight, + }) = _VotingVanWitness; +} + +@freezed +sealed class VotingVoteCommitments with _$VotingVoteCommitments { + const factory VotingVoteCommitments({ + required int bundleIndex, + required List commitments, + }) = _VotingVoteCommitments; +} + +@freezed +sealed class VotingVoteConfirmation with _$VotingVoteConfirmation { + const factory VotingVoteConfirmation({ + required String txHash, + required int vanLeafPosition, + required BigInt vcTreePosition, + }) = _VotingVoteConfirmation; +} + +@freezed +sealed class VotingVotePayloads with _$VotingVotePayloads { + const factory VotingVotePayloads({ + required VotingVoteSubmission submission, + required List sharePayloads, + }) = _VotingVotePayloads; +} + +@freezed +sealed class VotingVoteSubmission with _$VotingVoteSubmission { + const factory VotingVoteSubmission({ + required String voteRoundId, + required int proposalId, + required Uint8List vanNullifier, + required Uint8List voteAuthorityNoteNew, + required Uint8List voteCommitment, + required Uint8List proof, + required Uint8List rVpk, + required Uint8List voteAuthSig, + required int anchorHeight, + }) = _VotingVoteSubmission; +} diff --git a/lib/src/rust/api/voting.freezed.dart b/lib/src/rust/api/voting.freezed.dart new file mode 100644 index 000000000..b0df52853 --- /dev/null +++ b/lib/src/rust/api/voting.freezed.dart @@ -0,0 +1,5344 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'voting.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$VotingDelegationConfirmation { + String get txHash; + int get vanLeafPosition; + + /// Create a copy of VotingDelegationConfirmation + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationConfirmationCopyWith + get copyWith => _$VotingDelegationConfirmationCopyWithImpl< + VotingDelegationConfirmation>( + this as VotingDelegationConfirmation, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); + + @override + String toString() { + return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationConfirmationCopyWith<$Res> { + factory $VotingDelegationConfirmationCopyWith( + VotingDelegationConfirmation value, + $Res Function(VotingDelegationConfirmation) _then) = + _$VotingDelegationConfirmationCopyWithImpl; + @useResult + $Res call({String txHash, int vanLeafPosition}); +} + +/// @nodoc +class _$VotingDelegationConfirmationCopyWithImpl<$Res> + implements $VotingDelegationConfirmationCopyWith<$Res> { + _$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); + + final VotingDelegationConfirmation _self; + final $Res Function(VotingDelegationConfirmation) _then; + + /// Create a copy of VotingDelegationConfirmation + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? txHash = null, + Object? vanLeafPosition = null, + }) { + return _then(_self.copyWith( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String, + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationConfirmation]. +extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationConfirmation value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationConfirmation value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationConfirmation value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String txHash, int vanLeafPosition)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation() when $default != null: + return $default(_that.txHash, _that.vanLeafPosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String txHash, int vanLeafPosition) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation(): + return $default(_that.txHash, _that.vanLeafPosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String txHash, int vanLeafPosition)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationConfirmation() when $default != null: + return $default(_that.txHash, _that.vanLeafPosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationConfirmation implements VotingDelegationConfirmation { + const _VotingDelegationConfirmation( + {required this.txHash, required this.vanLeafPosition}); + + @override + final String txHash; + @override + final int vanLeafPosition; + + /// Create a copy of VotingDelegationConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationConfirmationCopyWith<_VotingDelegationConfirmation> + get copyWith => __$VotingDelegationConfirmationCopyWithImpl< + _VotingDelegationConfirmation>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); + + @override + String toString() { + return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationConfirmationCopyWith<$Res> + implements $VotingDelegationConfirmationCopyWith<$Res> { + factory _$VotingDelegationConfirmationCopyWith( + _VotingDelegationConfirmation value, + $Res Function(_VotingDelegationConfirmation) _then) = + __$VotingDelegationConfirmationCopyWithImpl; + @override + @useResult + $Res call({String txHash, int vanLeafPosition}); +} + +/// @nodoc +class __$VotingDelegationConfirmationCopyWithImpl<$Res> + implements _$VotingDelegationConfirmationCopyWith<$Res> { + __$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); + + final _VotingDelegationConfirmation _self; + final $Res Function(_VotingDelegationConfirmation) _then; + + /// Create a copy of VotingDelegationConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? txHash = null, + Object? vanLeafPosition = null, + }) { + return _then(_VotingDelegationConfirmation( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String, + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingDelegationSetup { + Uint8List get pcztBytes; + Uint8List get pcztSighash; + Uint8List get rk; + int get actionIndex; + Uint8List get actionBytes; + Uint8List get tx1Effects; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationSetupCopyWith get copyWith => + _$VotingDelegationSetupCopyWithImpl( + this as VotingDelegationSetup, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationSetup && + const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && + const DeepCollectionEquality() + .equals(other.pcztSighash, pcztSighash) && + const DeepCollectionEquality().equals(other.rk, rk) && + (identical(other.actionIndex, actionIndex) || + other.actionIndex == actionIndex) && + const DeepCollectionEquality() + .equals(other.actionBytes, actionBytes) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(pcztBytes), + const DeepCollectionEquality().hash(pcztSighash), + const DeepCollectionEquality().hash(rk), + actionIndex, + const DeepCollectionEquality().hash(actionBytes), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationSetupCopyWith<$Res> { + factory $VotingDelegationSetupCopyWith(VotingDelegationSetup value, + $Res Function(VotingDelegationSetup) _then) = + _$VotingDelegationSetupCopyWithImpl; + @useResult + $Res call( + {Uint8List pcztBytes, + Uint8List pcztSighash, + Uint8List rk, + int actionIndex, + Uint8List actionBytes, + Uint8List tx1Effects}); +} + +/// @nodoc +class _$VotingDelegationSetupCopyWithImpl<$Res> + implements $VotingDelegationSetupCopyWith<$Res> { + _$VotingDelegationSetupCopyWithImpl(this._self, this._then); + + final VotingDelegationSetup _self; + final $Res Function(VotingDelegationSetup) _then; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pcztBytes = null, + Object? pcztSighash = null, + Object? rk = null, + Object? actionIndex = null, + Object? actionBytes = null, + Object? tx1Effects = null, + }) { + return _then(_self.copyWith( + pcztBytes: null == pcztBytes + ? _self.pcztBytes + : pcztBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + pcztSighash: null == pcztSighash + ? _self.pcztSighash + : pcztSighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + actionIndex: null == actionIndex + ? _self.actionIndex + : actionIndex // ignore: cast_nullable_to_non_nullable + as int, + actionBytes: null == actionBytes + ? _self.actionBytes + : actionBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationSetup]. +extension VotingDelegationSetupPatterns on VotingDelegationSetup { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationSetup value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationSetup value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationSetup value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup(): + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationSetup implements VotingDelegationSetup { + const _VotingDelegationSetup( + {required this.pcztBytes, + required this.pcztSighash, + required this.rk, + required this.actionIndex, + required this.actionBytes, + required this.tx1Effects}); + + @override + final Uint8List pcztBytes; + @override + final Uint8List pcztSighash; + @override + final Uint8List rk; + @override + final int actionIndex; + @override + final Uint8List actionBytes; + @override + final Uint8List tx1Effects; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationSetupCopyWith<_VotingDelegationSetup> get copyWith => + __$VotingDelegationSetupCopyWithImpl<_VotingDelegationSetup>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationSetup && + const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && + const DeepCollectionEquality() + .equals(other.pcztSighash, pcztSighash) && + const DeepCollectionEquality().equals(other.rk, rk) && + (identical(other.actionIndex, actionIndex) || + other.actionIndex == actionIndex) && + const DeepCollectionEquality() + .equals(other.actionBytes, actionBytes) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(pcztBytes), + const DeepCollectionEquality().hash(pcztSighash), + const DeepCollectionEquality().hash(rk), + actionIndex, + const DeepCollectionEquality().hash(actionBytes), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationSetupCopyWith<$Res> + implements $VotingDelegationSetupCopyWith<$Res> { + factory _$VotingDelegationSetupCopyWith(_VotingDelegationSetup value, + $Res Function(_VotingDelegationSetup) _then) = + __$VotingDelegationSetupCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List pcztBytes, + Uint8List pcztSighash, + Uint8List rk, + int actionIndex, + Uint8List actionBytes, + Uint8List tx1Effects}); +} + +/// @nodoc +class __$VotingDelegationSetupCopyWithImpl<$Res> + implements _$VotingDelegationSetupCopyWith<$Res> { + __$VotingDelegationSetupCopyWithImpl(this._self, this._then); + + final _VotingDelegationSetup _self; + final $Res Function(_VotingDelegationSetup) _then; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? pcztBytes = null, + Object? pcztSighash = null, + Object? rk = null, + Object? actionIndex = null, + Object? actionBytes = null, + Object? tx1Effects = null, + }) { + return _then(_VotingDelegationSetup( + pcztBytes: null == pcztBytes + ? _self.pcztBytes + : pcztBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + pcztSighash: null == pcztSighash + ? _self.pcztSighash + : pcztSighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + actionIndex: null == actionIndex + ? _self.actionIndex + : actionIndex // ignore: cast_nullable_to_non_nullable + as int, + actionBytes: null == actionBytes + ? _self.actionBytes + : actionBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// @nodoc +mixin _$VotingDelegationSubmission { + Uint8List get proof; + Uint8List get rk; + Uint8List get nfSigned; + Uint8List get cmxNew; + Uint8List get govComm; + List get govNullifiers; + Uint8List get alpha; + String get voteRoundId; + Uint8List get spendAuthSig; + Uint8List get sighash; + Uint8List get tx1Effects; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationSubmissionCopyWith + get copyWith => + _$VotingDelegationSubmissionCopyWithImpl( + this as VotingDelegationSubmission, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationSubmission && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rk, rk) && + const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && + const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && + const DeepCollectionEquality().equals(other.govComm, govComm) && + const DeepCollectionEquality() + .equals(other.govNullifiers, govNullifiers) && + const DeepCollectionEquality().equals(other.alpha, alpha) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.spendAuthSig, spendAuthSig) && + const DeepCollectionEquality().equals(other.sighash, sighash) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rk), + const DeepCollectionEquality().hash(nfSigned), + const DeepCollectionEquality().hash(cmxNew), + const DeepCollectionEquality().hash(govComm), + const DeepCollectionEquality().hash(govNullifiers), + const DeepCollectionEquality().hash(alpha), + voteRoundId, + const DeepCollectionEquality().hash(spendAuthSig), + const DeepCollectionEquality().hash(sighash), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationSubmissionCopyWith<$Res> { + factory $VotingDelegationSubmissionCopyWith(VotingDelegationSubmission value, + $Res Function(VotingDelegationSubmission) _then) = + _$VotingDelegationSubmissionCopyWithImpl; + @useResult + $Res call( + {Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects}); +} + +/// @nodoc +class _$VotingDelegationSubmissionCopyWithImpl<$Res> + implements $VotingDelegationSubmissionCopyWith<$Res> { + _$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); + + final VotingDelegationSubmission _self; + final $Res Function(VotingDelegationSubmission) _then; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proof = null, + Object? rk = null, + Object? nfSigned = null, + Object? cmxNew = null, + Object? govComm = null, + Object? govNullifiers = null, + Object? alpha = null, + Object? voteRoundId = null, + Object? spendAuthSig = null, + Object? sighash = null, + Object? tx1Effects = null, + }) { + return _then(_self.copyWith( + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + nfSigned: null == nfSigned + ? _self.nfSigned + : nfSigned // ignore: cast_nullable_to_non_nullable + as Uint8List, + cmxNew: null == cmxNew + ? _self.cmxNew + : cmxNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + govComm: null == govComm + ? _self.govComm + : govComm // ignore: cast_nullable_to_non_nullable + as Uint8List, + govNullifiers: null == govNullifiers + ? _self.govNullifiers + : govNullifiers // ignore: cast_nullable_to_non_nullable + as List, + alpha: null == alpha + ? _self.alpha + : alpha // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + spendAuthSig: null == spendAuthSig + ? _self.spendAuthSig + : spendAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + sighash: null == sighash + ? _self.sighash + : sighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationSubmission]. +extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationSubmission value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationSubmission value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationSubmission value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission(): + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationSubmission implements VotingDelegationSubmission { + const _VotingDelegationSubmission( + {required this.proof, + required this.rk, + required this.nfSigned, + required this.cmxNew, + required this.govComm, + required final List govNullifiers, + required this.alpha, + required this.voteRoundId, + required this.spendAuthSig, + required this.sighash, + required this.tx1Effects}) + : _govNullifiers = govNullifiers; + + @override + final Uint8List proof; + @override + final Uint8List rk; + @override + final Uint8List nfSigned; + @override + final Uint8List cmxNew; + @override + final Uint8List govComm; + final List _govNullifiers; + @override + List get govNullifiers { + if (_govNullifiers is EqualUnmodifiableListView) return _govNullifiers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_govNullifiers); + } + + @override + final Uint8List alpha; + @override + final String voteRoundId; + @override + final Uint8List spendAuthSig; + @override + final Uint8List sighash; + @override + final Uint8List tx1Effects; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationSubmissionCopyWith<_VotingDelegationSubmission> + get copyWith => __$VotingDelegationSubmissionCopyWithImpl< + _VotingDelegationSubmission>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationSubmission && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rk, rk) && + const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && + const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && + const DeepCollectionEquality().equals(other.govComm, govComm) && + const DeepCollectionEquality() + .equals(other._govNullifiers, _govNullifiers) && + const DeepCollectionEquality().equals(other.alpha, alpha) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.spendAuthSig, spendAuthSig) && + const DeepCollectionEquality().equals(other.sighash, sighash) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rk), + const DeepCollectionEquality().hash(nfSigned), + const DeepCollectionEquality().hash(cmxNew), + const DeepCollectionEquality().hash(govComm), + const DeepCollectionEquality().hash(_govNullifiers), + const DeepCollectionEquality().hash(alpha), + voteRoundId, + const DeepCollectionEquality().hash(spendAuthSig), + const DeepCollectionEquality().hash(sighash), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationSubmissionCopyWith<$Res> + implements $VotingDelegationSubmissionCopyWith<$Res> { + factory _$VotingDelegationSubmissionCopyWith( + _VotingDelegationSubmission value, + $Res Function(_VotingDelegationSubmission) _then) = + __$VotingDelegationSubmissionCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects}); +} + +/// @nodoc +class __$VotingDelegationSubmissionCopyWithImpl<$Res> + implements _$VotingDelegationSubmissionCopyWith<$Res> { + __$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); + + final _VotingDelegationSubmission _self; + final $Res Function(_VotingDelegationSubmission) _then; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proof = null, + Object? rk = null, + Object? nfSigned = null, + Object? cmxNew = null, + Object? govComm = null, + Object? govNullifiers = null, + Object? alpha = null, + Object? voteRoundId = null, + Object? spendAuthSig = null, + Object? sighash = null, + Object? tx1Effects = null, + }) { + return _then(_VotingDelegationSubmission( + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + nfSigned: null == nfSigned + ? _self.nfSigned + : nfSigned // ignore: cast_nullable_to_non_nullable + as Uint8List, + cmxNew: null == cmxNew + ? _self.cmxNew + : cmxNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + govComm: null == govComm + ? _self.govComm + : govComm // ignore: cast_nullable_to_non_nullable + as Uint8List, + govNullifiers: null == govNullifiers + ? _self._govNullifiers + : govNullifiers // ignore: cast_nullable_to_non_nullable + as List, + alpha: null == alpha + ? _self.alpha + : alpha // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + spendAuthSig: null == spendAuthSig + ? _self.spendAuthSig + : spendAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + sighash: null == sighash + ? _self.sighash + : sighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// @nodoc +mixin _$VotingEncryptedShare { + Uint8List get c1; + Uint8List get c2; + int get shareIndex; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith get copyWith => + _$VotingEncryptedShareCopyWithImpl( + this as VotingEncryptedShare, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingEncryptedShare && + const DeepCollectionEquality().equals(other.c1, c1) && + const DeepCollectionEquality().equals(other.c2, c2) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(c1), + const DeepCollectionEquality().hash(c2), + shareIndex); + + @override + String toString() { + return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingEncryptedShareCopyWith<$Res> { + factory $VotingEncryptedShareCopyWith(VotingEncryptedShare value, + $Res Function(VotingEncryptedShare) _then) = + _$VotingEncryptedShareCopyWithImpl; + @useResult + $Res call({Uint8List c1, Uint8List c2, int shareIndex}); +} + +/// @nodoc +class _$VotingEncryptedShareCopyWithImpl<$Res> + implements $VotingEncryptedShareCopyWith<$Res> { + _$VotingEncryptedShareCopyWithImpl(this._self, this._then); + + final VotingEncryptedShare _self; + final $Res Function(VotingEncryptedShare) _then; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? c1 = null, + Object? c2 = null, + Object? shareIndex = null, + }) { + return _then(_self.copyWith( + c1: null == c1 + ? _self.c1 + : c1 // ignore: cast_nullable_to_non_nullable + as Uint8List, + c2: null == c2 + ? _self.c2 + : c2 // ignore: cast_nullable_to_non_nullable + as Uint8List, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingEncryptedShare]. +extension VotingEncryptedSharePatterns on VotingEncryptedShare { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingEncryptedShare value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingEncryptedShare value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingEncryptedShare value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that.c1, _that.c2, _that.shareIndex); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(Uint8List c1, Uint8List c2, int shareIndex) $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare(): + return $default(_that.c1, _that.c2, _that.shareIndex); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that.c1, _that.c2, _that.shareIndex); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingEncryptedShare implements VotingEncryptedShare { + const _VotingEncryptedShare( + {required this.c1, required this.c2, required this.shareIndex}); + + @override + final Uint8List c1; + @override + final Uint8List c2; + @override + final int shareIndex; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingEncryptedShareCopyWith<_VotingEncryptedShare> get copyWith => + __$VotingEncryptedShareCopyWithImpl<_VotingEncryptedShare>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingEncryptedShare && + const DeepCollectionEquality().equals(other.c1, c1) && + const DeepCollectionEquality().equals(other.c2, c2) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(c1), + const DeepCollectionEquality().hash(c2), + shareIndex); + + @override + String toString() { + return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class _$VotingEncryptedShareCopyWith<$Res> + implements $VotingEncryptedShareCopyWith<$Res> { + factory _$VotingEncryptedShareCopyWith(_VotingEncryptedShare value, + $Res Function(_VotingEncryptedShare) _then) = + __$VotingEncryptedShareCopyWithImpl; + @override + @useResult + $Res call({Uint8List c1, Uint8List c2, int shareIndex}); +} + +/// @nodoc +class __$VotingEncryptedShareCopyWithImpl<$Res> + implements _$VotingEncryptedShareCopyWith<$Res> { + __$VotingEncryptedShareCopyWithImpl(this._self, this._then); + + final _VotingEncryptedShare _self; + final $Res Function(_VotingEncryptedShare) _then; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? c1 = null, + Object? c2 = null, + Object? shareIndex = null, + }) { + return _then(_VotingEncryptedShare( + c1: null == c1 + ? _self.c1 + : c1 // ignore: cast_nullable_to_non_nullable + as Uint8List, + c2: null == c2 + ? _self.c2 + : c2 // ignore: cast_nullable_to_non_nullable + as Uint8List, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingPirLayout { + int get pirDepth; + int get tier0Layers; + int get tier1Layers; + int get polyLen; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingPirLayoutCopyWith get copyWith => + _$VotingPirLayoutCopyWithImpl( + this as VotingPirLayout, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingPirLayout && + (identical(other.pirDepth, pirDepth) || + other.pirDepth == pirDepth) && + (identical(other.tier0Layers, tier0Layers) || + other.tier0Layers == tier0Layers) && + (identical(other.tier1Layers, tier1Layers) || + other.tier1Layers == tier1Layers) && + (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + } + + @override + int get hashCode => + Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + + @override + String toString() { + return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + } +} + +/// @nodoc +abstract mixin class $VotingPirLayoutCopyWith<$Res> { + factory $VotingPirLayoutCopyWith( + VotingPirLayout value, $Res Function(VotingPirLayout) _then) = + _$VotingPirLayoutCopyWithImpl; + @useResult + $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); +} + +/// @nodoc +class _$VotingPirLayoutCopyWithImpl<$Res> + implements $VotingPirLayoutCopyWith<$Res> { + _$VotingPirLayoutCopyWithImpl(this._self, this._then); + + final VotingPirLayout _self; + final $Res Function(VotingPirLayout) _then; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pirDepth = null, + Object? tier0Layers = null, + Object? tier1Layers = null, + Object? polyLen = null, + }) { + return _then(_self.copyWith( + pirDepth: null == pirDepth + ? _self.pirDepth + : pirDepth // ignore: cast_nullable_to_non_nullable + as int, + tier0Layers: null == tier0Layers + ? _self.tier0Layers + : tier0Layers // ignore: cast_nullable_to_non_nullable + as int, + tier1Layers: null == tier1Layers + ? _self.tier1Layers + : tier1Layers // ignore: cast_nullable_to_non_nullable + as int, + polyLen: null == polyLen + ? _self.polyLen + : polyLen // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingPirLayout]. +extension VotingPirLayoutPatterns on VotingPirLayout { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingPirLayout value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingPirLayout value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingPirLayout value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout(): + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingPirLayout implements VotingPirLayout { + const _VotingPirLayout( + {required this.pirDepth, + required this.tier0Layers, + required this.tier1Layers, + required this.polyLen}); + + @override + final int pirDepth; + @override + final int tier0Layers; + @override + final int tier1Layers; + @override + final int polyLen; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingPirLayoutCopyWith<_VotingPirLayout> get copyWith => + __$VotingPirLayoutCopyWithImpl<_VotingPirLayout>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingPirLayout && + (identical(other.pirDepth, pirDepth) || + other.pirDepth == pirDepth) && + (identical(other.tier0Layers, tier0Layers) || + other.tier0Layers == tier0Layers) && + (identical(other.tier1Layers, tier1Layers) || + other.tier1Layers == tier1Layers) && + (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + } + + @override + int get hashCode => + Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + + @override + String toString() { + return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + } +} + +/// @nodoc +abstract mixin class _$VotingPirLayoutCopyWith<$Res> + implements $VotingPirLayoutCopyWith<$Res> { + factory _$VotingPirLayoutCopyWith( + _VotingPirLayout value, $Res Function(_VotingPirLayout) _then) = + __$VotingPirLayoutCopyWithImpl; + @override + @useResult + $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); +} + +/// @nodoc +class __$VotingPirLayoutCopyWithImpl<$Res> + implements _$VotingPirLayoutCopyWith<$Res> { + __$VotingPirLayoutCopyWithImpl(this._self, this._then); + + final _VotingPirLayout _self; + final $Res Function(_VotingPirLayout) _then; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? pirDepth = null, + Object? tier0Layers = null, + Object? tier1Layers = null, + Object? polyLen = null, + }) { + return _then(_VotingPirLayout( + pirDepth: null == pirDepth + ? _self.pirDepth + : pirDepth // ignore: cast_nullable_to_non_nullable + as int, + tier0Layers: null == tier0Layers + ? _self.tier0Layers + : tier0Layers // ignore: cast_nullable_to_non_nullable + as int, + tier1Layers: null == tier1Layers + ? _self.tier1Layers + : tier1Layers // ignore: cast_nullable_to_non_nullable + as int, + polyLen: null == polyLen + ? _self.polyLen + : polyLen // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingPreparedInfo { + String get roundId; + int get bundleIndex; + BigInt get eligibleWeightZatoshi; + BigInt get delegatedWeightZatoshi; + String get roundName; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingPreparedInfoCopyWith get copyWith => + _$VotingPreparedInfoCopyWithImpl( + this as VotingPreparedInfo, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingPreparedInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || + other.delegatedWeightZatoshi == delegatedWeightZatoshi) && + (identical(other.roundName, roundName) || + other.roundName == roundName)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, + eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + + @override + String toString() { + return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + } +} + +/// @nodoc +abstract mixin class $VotingPreparedInfoCopyWith<$Res> { + factory $VotingPreparedInfoCopyWith( + VotingPreparedInfo value, $Res Function(VotingPreparedInfo) _then) = + _$VotingPreparedInfoCopyWithImpl; + @useResult + $Res call( + {String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName}); +} + +/// @nodoc +class _$VotingPreparedInfoCopyWithImpl<$Res> + implements $VotingPreparedInfoCopyWith<$Res> { + _$VotingPreparedInfoCopyWithImpl(this._self, this._then); + + final VotingPreparedInfo _self; + final $Res Function(VotingPreparedInfo) _then; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? eligibleWeightZatoshi = null, + Object? delegatedWeightZatoshi = null, + Object? roundName = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + eligibleWeightZatoshi: null == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + delegatedWeightZatoshi: null == delegatedWeightZatoshi + ? _self.delegatedWeightZatoshi + : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + roundName: null == roundName + ? _self.roundName + : roundName // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingPreparedInfo]. +extension VotingPreparedInfoPatterns on VotingPreparedInfo { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingPreparedInfo value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingPreparedInfo value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingPreparedInfo value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo(): + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingPreparedInfo implements VotingPreparedInfo { + const _VotingPreparedInfo( + {required this.roundId, + required this.bundleIndex, + required this.eligibleWeightZatoshi, + required this.delegatedWeightZatoshi, + required this.roundName}); + + @override + final String roundId; + @override + final int bundleIndex; + @override + final BigInt eligibleWeightZatoshi; + @override + final BigInt delegatedWeightZatoshi; + @override + final String roundName; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingPreparedInfoCopyWith<_VotingPreparedInfo> get copyWith => + __$VotingPreparedInfoCopyWithImpl<_VotingPreparedInfo>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingPreparedInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || + other.delegatedWeightZatoshi == delegatedWeightZatoshi) && + (identical(other.roundName, roundName) || + other.roundName == roundName)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, + eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + + @override + String toString() { + return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + } +} + +/// @nodoc +abstract mixin class _$VotingPreparedInfoCopyWith<$Res> + implements $VotingPreparedInfoCopyWith<$Res> { + factory _$VotingPreparedInfoCopyWith( + _VotingPreparedInfo value, $Res Function(_VotingPreparedInfo) _then) = + __$VotingPreparedInfoCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName}); +} + +/// @nodoc +class __$VotingPreparedInfoCopyWithImpl<$Res> + implements _$VotingPreparedInfoCopyWith<$Res> { + __$VotingPreparedInfoCopyWithImpl(this._self, this._then); + + final _VotingPreparedInfo _self; + final $Res Function(_VotingPreparedInfo) _then; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? eligibleWeightZatoshi = null, + Object? delegatedWeightZatoshi = null, + Object? roundName = null, + }) { + return _then(_VotingPreparedInfo( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + eligibleWeightZatoshi: null == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + delegatedWeightZatoshi: null == delegatedWeightZatoshi + ? _self.delegatedWeightZatoshi + : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + roundName: null == roundName + ? _self.roundName + : roundName // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingSharePayload { + Uint8List get sharesHash; + int get proposalId; + int get voteDecision; + VotingEncryptedShare get encShare; + BigInt get treePosition; + List get allEncShares; + List get shareComms; + Uint8List get primaryBlind; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSharePayloadCopyWith get copyWith => + _$VotingSharePayloadCopyWithImpl( + this as VotingSharePayload, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSharePayload && + const DeepCollectionEquality() + .equals(other.sharesHash, sharesHash) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.voteDecision, voteDecision) || + other.voteDecision == voteDecision) && + (identical(other.encShare, encShare) || + other.encShare == encShare) && + (identical(other.treePosition, treePosition) || + other.treePosition == treePosition) && + const DeepCollectionEquality() + .equals(other.allEncShares, allEncShares) && + const DeepCollectionEquality() + .equals(other.shareComms, shareComms) && + const DeepCollectionEquality() + .equals(other.primaryBlind, primaryBlind)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(sharesHash), + proposalId, + voteDecision, + encShare, + treePosition, + const DeepCollectionEquality().hash(allEncShares), + const DeepCollectionEquality().hash(shareComms), + const DeepCollectionEquality().hash(primaryBlind)); + + @override + String toString() { + return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + } +} + +/// @nodoc +abstract mixin class $VotingSharePayloadCopyWith<$Res> { + factory $VotingSharePayloadCopyWith( + VotingSharePayload value, $Res Function(VotingSharePayload) _then) = + _$VotingSharePayloadCopyWithImpl; + @useResult + $Res call( + {Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind}); + + $VotingEncryptedShareCopyWith<$Res> get encShare; +} + +/// @nodoc +class _$VotingSharePayloadCopyWithImpl<$Res> + implements $VotingSharePayloadCopyWith<$Res> { + _$VotingSharePayloadCopyWithImpl(this._self, this._then); + + final VotingSharePayload _self; + final $Res Function(VotingSharePayload) _then; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? sharesHash = null, + Object? proposalId = null, + Object? voteDecision = null, + Object? encShare = null, + Object? treePosition = null, + Object? allEncShares = null, + Object? shareComms = null, + Object? primaryBlind = null, + }) { + return _then(_self.copyWith( + sharesHash: null == sharesHash + ? _self.sharesHash + : sharesHash // ignore: cast_nullable_to_non_nullable + as Uint8List, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + voteDecision: null == voteDecision + ? _self.voteDecision + : voteDecision // ignore: cast_nullable_to_non_nullable + as int, + encShare: null == encShare + ? _self.encShare + : encShare // ignore: cast_nullable_to_non_nullable + as VotingEncryptedShare, + treePosition: null == treePosition + ? _self.treePosition + : treePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + allEncShares: null == allEncShares + ? _self.allEncShares + : allEncShares // ignore: cast_nullable_to_non_nullable + as List, + shareComms: null == shareComms + ? _self.shareComms + : shareComms // ignore: cast_nullable_to_non_nullable + as List, + primaryBlind: null == primaryBlind + ? _self.primaryBlind + : primaryBlind // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith<$Res> get encShare { + return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { + return _then(_self.copyWith(encShare: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingSharePayload]. +extension VotingSharePayloadPatterns on VotingSharePayload { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSharePayload value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSharePayload value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSharePayload value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload(): + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSharePayload implements VotingSharePayload { + const _VotingSharePayload( + {required this.sharesHash, + required this.proposalId, + required this.voteDecision, + required this.encShare, + required this.treePosition, + required final List allEncShares, + required final List shareComms, + required this.primaryBlind}) + : _allEncShares = allEncShares, + _shareComms = shareComms; + + @override + final Uint8List sharesHash; + @override + final int proposalId; + @override + final int voteDecision; + @override + final VotingEncryptedShare encShare; + @override + final BigInt treePosition; + final List _allEncShares; + @override + List get allEncShares { + if (_allEncShares is EqualUnmodifiableListView) return _allEncShares; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_allEncShares); + } + + final List _shareComms; + @override + List get shareComms { + if (_shareComms is EqualUnmodifiableListView) return _shareComms; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_shareComms); + } + + @override + final Uint8List primaryBlind; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSharePayloadCopyWith<_VotingSharePayload> get copyWith => + __$VotingSharePayloadCopyWithImpl<_VotingSharePayload>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSharePayload && + const DeepCollectionEquality() + .equals(other.sharesHash, sharesHash) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.voteDecision, voteDecision) || + other.voteDecision == voteDecision) && + (identical(other.encShare, encShare) || + other.encShare == encShare) && + (identical(other.treePosition, treePosition) || + other.treePosition == treePosition) && + const DeepCollectionEquality() + .equals(other._allEncShares, _allEncShares) && + const DeepCollectionEquality() + .equals(other._shareComms, _shareComms) && + const DeepCollectionEquality() + .equals(other.primaryBlind, primaryBlind)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(sharesHash), + proposalId, + voteDecision, + encShare, + treePosition, + const DeepCollectionEquality().hash(_allEncShares), + const DeepCollectionEquality().hash(_shareComms), + const DeepCollectionEquality().hash(primaryBlind)); + + @override + String toString() { + return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSharePayloadCopyWith<$Res> + implements $VotingSharePayloadCopyWith<$Res> { + factory _$VotingSharePayloadCopyWith( + _VotingSharePayload value, $Res Function(_VotingSharePayload) _then) = + __$VotingSharePayloadCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind}); + + @override + $VotingEncryptedShareCopyWith<$Res> get encShare; +} + +/// @nodoc +class __$VotingSharePayloadCopyWithImpl<$Res> + implements _$VotingSharePayloadCopyWith<$Res> { + __$VotingSharePayloadCopyWithImpl(this._self, this._then); + + final _VotingSharePayload _self; + final $Res Function(_VotingSharePayload) _then; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? sharesHash = null, + Object? proposalId = null, + Object? voteDecision = null, + Object? encShare = null, + Object? treePosition = null, + Object? allEncShares = null, + Object? shareComms = null, + Object? primaryBlind = null, + }) { + return _then(_VotingSharePayload( + sharesHash: null == sharesHash + ? _self.sharesHash + : sharesHash // ignore: cast_nullable_to_non_nullable + as Uint8List, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + voteDecision: null == voteDecision + ? _self.voteDecision + : voteDecision // ignore: cast_nullable_to_non_nullable + as int, + encShare: null == encShare + ? _self.encShare + : encShare // ignore: cast_nullable_to_non_nullable + as VotingEncryptedShare, + treePosition: null == treePosition + ? _self.treePosition + : treePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + allEncShares: null == allEncShares + ? _self._allEncShares + : allEncShares // ignore: cast_nullable_to_non_nullable + as List, + shareComms: null == shareComms + ? _self._shareComms + : shareComms // ignore: cast_nullable_to_non_nullable + as List, + primaryBlind: null == primaryBlind + ? _self.primaryBlind + : primaryBlind // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith<$Res> get encShare { + return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { + return _then(_self.copyWith(encShare: value)); + }); + } +} + +/// @nodoc +mixin _$VotingSignedVoteCommitment { + int get proposalId; + int get choice; + String get voteRoundId; + Uint8List get vanNullifier; + Uint8List get voteAuthorityNoteNew; + Uint8List get voteCommitment; + Uint8List get proof; + int get anchorHeight; + Uint8List get rVpk; + Uint8List get voteAuthSig; + String get commitmentBundleJson; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSignedVoteCommitmentCopyWith + get copyWith => + _$VotingSignedVoteCommitmentCopyWithImpl( + this as VotingSignedVoteCommitment, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSignedVoteCommitment && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.commitmentBundleJson, commitmentBundleJson) || + other.commitmentBundleJson == commitmentBundleJson)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + proposalId, + choice, + voteRoundId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + anchorHeight, + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + commitmentBundleJson); + + @override + String toString() { + return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + } +} + +/// @nodoc +abstract mixin class $VotingSignedVoteCommitmentCopyWith<$Res> { + factory $VotingSignedVoteCommitmentCopyWith(VotingSignedVoteCommitment value, + $Res Function(VotingSignedVoteCommitment) _then) = + _$VotingSignedVoteCommitmentCopyWithImpl; + @useResult + $Res call( + {int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson}); +} + +/// @nodoc +class _$VotingSignedVoteCommitmentCopyWithImpl<$Res> + implements $VotingSignedVoteCommitmentCopyWith<$Res> { + _$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); + + final VotingSignedVoteCommitment _self; + final $Res Function(VotingSignedVoteCommitment) _then; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proposalId = null, + Object? choice = null, + Object? voteRoundId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? anchorHeight = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? commitmentBundleJson = null, + }) { + return _then(_self.copyWith( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + commitmentBundleJson: null == commitmentBundleJson + ? _self.commitmentBundleJson + : commitmentBundleJson // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingSignedVoteCommitment]. +extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSignedVoteCommitment value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSignedVoteCommitment value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSignedVoteCommitment value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment(): + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSignedVoteCommitment implements VotingSignedVoteCommitment { + const _VotingSignedVoteCommitment( + {required this.proposalId, + required this.choice, + required this.voteRoundId, + required this.vanNullifier, + required this.voteAuthorityNoteNew, + required this.voteCommitment, + required this.proof, + required this.anchorHeight, + required this.rVpk, + required this.voteAuthSig, + required this.commitmentBundleJson}); + + @override + final int proposalId; + @override + final int choice; + @override + final String voteRoundId; + @override + final Uint8List vanNullifier; + @override + final Uint8List voteAuthorityNoteNew; + @override + final Uint8List voteCommitment; + @override + final Uint8List proof; + @override + final int anchorHeight; + @override + final Uint8List rVpk; + @override + final Uint8List voteAuthSig; + @override + final String commitmentBundleJson; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSignedVoteCommitmentCopyWith<_VotingSignedVoteCommitment> + get copyWith => __$VotingSignedVoteCommitmentCopyWithImpl< + _VotingSignedVoteCommitment>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSignedVoteCommitment && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.commitmentBundleJson, commitmentBundleJson) || + other.commitmentBundleJson == commitmentBundleJson)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + proposalId, + choice, + voteRoundId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + anchorHeight, + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + commitmentBundleJson); + + @override + String toString() { + return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSignedVoteCommitmentCopyWith<$Res> + implements $VotingSignedVoteCommitmentCopyWith<$Res> { + factory _$VotingSignedVoteCommitmentCopyWith( + _VotingSignedVoteCommitment value, + $Res Function(_VotingSignedVoteCommitment) _then) = + __$VotingSignedVoteCommitmentCopyWithImpl; + @override + @useResult + $Res call( + {int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson}); +} + +/// @nodoc +class __$VotingSignedVoteCommitmentCopyWithImpl<$Res> + implements _$VotingSignedVoteCommitmentCopyWith<$Res> { + __$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); + + final _VotingSignedVoteCommitment _self; + final $Res Function(_VotingSignedVoteCommitment) _then; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proposalId = null, + Object? choice = null, + Object? voteRoundId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? anchorHeight = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? commitmentBundleJson = null, + }) { + return _then(_VotingSignedVoteCommitment( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + commitmentBundleJson: null == commitmentBundleJson + ? _self.commitmentBundleJson + : commitmentBundleJson // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingVanWitness { + List get authPath; + int get position; + int get anchorHeight; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVanWitnessCopyWith get copyWith => + _$VotingVanWitnessCopyWithImpl( + this as VotingVanWitness, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVanWitness && + const DeepCollectionEquality().equals(other.authPath, authPath) && + (identical(other.position, position) || + other.position == position) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(authPath), position, anchorHeight); + + @override + String toString() { + return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class $VotingVanWitnessCopyWith<$Res> { + factory $VotingVanWitnessCopyWith( + VotingVanWitness value, $Res Function(VotingVanWitness) _then) = + _$VotingVanWitnessCopyWithImpl; + @useResult + $Res call({List authPath, int position, int anchorHeight}); +} + +/// @nodoc +class _$VotingVanWitnessCopyWithImpl<$Res> + implements $VotingVanWitnessCopyWith<$Res> { + _$VotingVanWitnessCopyWithImpl(this._self, this._then); + + final VotingVanWitness _self; + final $Res Function(VotingVanWitness) _then; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? authPath = null, + Object? position = null, + Object? anchorHeight = null, + }) { + return _then(_self.copyWith( + authPath: null == authPath + ? _self.authPath + : authPath // ignore: cast_nullable_to_non_nullable + as List, + position: null == position + ? _self.position + : position // ignore: cast_nullable_to_non_nullable + as int, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVanWitness]. +extension VotingVanWitnessPatterns on VotingVanWitness { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVanWitness value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVanWitness value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVanWitness value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(List authPath, int position, int anchorHeight)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that.authPath, _that.position, _that.anchorHeight); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(List authPath, int position, int anchorHeight) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness(): + return $default(_that.authPath, _that.position, _that.anchorHeight); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(List authPath, int position, int anchorHeight)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that.authPath, _that.position, _that.anchorHeight); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVanWitness implements VotingVanWitness { + const _VotingVanWitness( + {required final List authPath, + required this.position, + required this.anchorHeight}) + : _authPath = authPath; + + final List _authPath; + @override + List get authPath { + if (_authPath is EqualUnmodifiableListView) return _authPath; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_authPath); + } + + @override + final int position; + @override + final int anchorHeight; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVanWitnessCopyWith<_VotingVanWitness> get copyWith => + __$VotingVanWitnessCopyWithImpl<_VotingVanWitness>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVanWitness && + const DeepCollectionEquality().equals(other._authPath, _authPath) && + (identical(other.position, position) || + other.position == position) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_authPath), position, anchorHeight); + + @override + String toString() { + return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVanWitnessCopyWith<$Res> + implements $VotingVanWitnessCopyWith<$Res> { + factory _$VotingVanWitnessCopyWith( + _VotingVanWitness value, $Res Function(_VotingVanWitness) _then) = + __$VotingVanWitnessCopyWithImpl; + @override + @useResult + $Res call({List authPath, int position, int anchorHeight}); +} + +/// @nodoc +class __$VotingVanWitnessCopyWithImpl<$Res> + implements _$VotingVanWitnessCopyWith<$Res> { + __$VotingVanWitnessCopyWithImpl(this._self, this._then); + + final _VotingVanWitness _self; + final $Res Function(_VotingVanWitness) _then; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? authPath = null, + Object? position = null, + Object? anchorHeight = null, + }) { + return _then(_VotingVanWitness( + authPath: null == authPath + ? _self._authPath + : authPath // ignore: cast_nullable_to_non_nullable + as List, + position: null == position + ? _self.position + : position // ignore: cast_nullable_to_non_nullable + as int, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingVoteCommitments { + int get bundleIndex; + List get commitments; + + /// Create a copy of VotingVoteCommitments + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteCommitmentsCopyWith get copyWith => + _$VotingVoteCommitmentsCopyWithImpl( + this as VotingVoteCommitments, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteCommitments && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + const DeepCollectionEquality() + .equals(other.commitments, commitments)); + } + + @override + int get hashCode => Object.hash(runtimeType, bundleIndex, + const DeepCollectionEquality().hash(commitments)); + + @override + String toString() { + return 'VotingVoteCommitments(bundleIndex: $bundleIndex, commitments: $commitments)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteCommitmentsCopyWith<$Res> { + factory $VotingVoteCommitmentsCopyWith(VotingVoteCommitments value, + $Res Function(VotingVoteCommitments) _then) = + _$VotingVoteCommitmentsCopyWithImpl; + @useResult + $Res call({int bundleIndex, List commitments}); +} + +/// @nodoc +class _$VotingVoteCommitmentsCopyWithImpl<$Res> + implements $VotingVoteCommitmentsCopyWith<$Res> { + _$VotingVoteCommitmentsCopyWithImpl(this._self, this._then); + + final VotingVoteCommitments _self; + final $Res Function(VotingVoteCommitments) _then; + + /// Create a copy of VotingVoteCommitments + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? commitments = null, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + commitments: null == commitments + ? _self.commitments + : commitments // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteCommitments]. +extension VotingVoteCommitmentsPatterns on VotingVoteCommitments { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVoteCommitments value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVoteCommitments value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVoteCommitments value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int bundleIndex, List commitments)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments() when $default != null: + return $default(_that.bundleIndex, _that.commitments); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int bundleIndex, List commitments) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments(): + return $default(_that.bundleIndex, _that.commitments); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int bundleIndex, List commitments)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteCommitments() when $default != null: + return $default(_that.bundleIndex, _that.commitments); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVoteCommitments implements VotingVoteCommitments { + const _VotingVoteCommitments( + {required this.bundleIndex, + required final List commitments}) + : _commitments = commitments; + + @override + final int bundleIndex; + final List _commitments; + @override + List get commitments { + if (_commitments is EqualUnmodifiableListView) return _commitments; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_commitments); + } + + /// Create a copy of VotingVoteCommitments + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVoteCommitmentsCopyWith<_VotingVoteCommitments> get copyWith => + __$VotingVoteCommitmentsCopyWithImpl<_VotingVoteCommitments>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVoteCommitments && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + const DeepCollectionEquality() + .equals(other._commitments, _commitments)); + } + + @override + int get hashCode => Object.hash(runtimeType, bundleIndex, + const DeepCollectionEquality().hash(_commitments)); + + @override + String toString() { + return 'VotingVoteCommitments(bundleIndex: $bundleIndex, commitments: $commitments)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVoteCommitmentsCopyWith<$Res> + implements $VotingVoteCommitmentsCopyWith<$Res> { + factory _$VotingVoteCommitmentsCopyWith(_VotingVoteCommitments value, + $Res Function(_VotingVoteCommitments) _then) = + __$VotingVoteCommitmentsCopyWithImpl; + @override + @useResult + $Res call({int bundleIndex, List commitments}); +} + +/// @nodoc +class __$VotingVoteCommitmentsCopyWithImpl<$Res> + implements _$VotingVoteCommitmentsCopyWith<$Res> { + __$VotingVoteCommitmentsCopyWithImpl(this._self, this._then); + + final _VotingVoteCommitments _self; + final $Res Function(_VotingVoteCommitments) _then; + + /// Create a copy of VotingVoteCommitments + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? bundleIndex = null, + Object? commitments = null, + }) { + return _then(_VotingVoteCommitments( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + commitments: null == commitments + ? _self._commitments + : commitments // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +mixin _$VotingVoteConfirmation { + String get txHash; + int get vanLeafPosition; + BigInt get vcTreePosition; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteConfirmationCopyWith get copyWith => + _$VotingVoteConfirmationCopyWithImpl( + this as VotingVoteConfirmation, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition)); + } + + @override + int get hashCode => + Object.hash(runtimeType, txHash, vanLeafPosition, vcTreePosition); + + @override + String toString() { + return 'VotingVoteConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition, vcTreePosition: $vcTreePosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteConfirmationCopyWith<$Res> { + factory $VotingVoteConfirmationCopyWith(VotingVoteConfirmation value, + $Res Function(VotingVoteConfirmation) _then) = + _$VotingVoteConfirmationCopyWithImpl; + @useResult + $Res call({String txHash, int vanLeafPosition, BigInt vcTreePosition}); +} + +/// @nodoc +class _$VotingVoteConfirmationCopyWithImpl<$Res> + implements $VotingVoteConfirmationCopyWith<$Res> { + _$VotingVoteConfirmationCopyWithImpl(this._self, this._then); + + final VotingVoteConfirmation _self; + final $Res Function(VotingVoteConfirmation) _then; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? txHash = null, + Object? vanLeafPosition = null, + Object? vcTreePosition = null, + }) { + return _then(_self.copyWith( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String, + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int, + vcTreePosition: null == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteConfirmation]. +extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVoteConfirmation value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVoteConfirmation value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVoteConfirmation value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation(): + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String txHash, int vanLeafPosition, BigInt vcTreePosition)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVoteConfirmation implements VotingVoteConfirmation { + const _VotingVoteConfirmation( + {required this.txHash, + required this.vanLeafPosition, + required this.vcTreePosition}); + + @override + final String txHash; + @override + final int vanLeafPosition; + @override + final BigInt vcTreePosition; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVoteConfirmationCopyWith<_VotingVoteConfirmation> get copyWith => + __$VotingVoteConfirmationCopyWithImpl<_VotingVoteConfirmation>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVoteConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition)); + } + + @override + int get hashCode => + Object.hash(runtimeType, txHash, vanLeafPosition, vcTreePosition); + + @override + String toString() { + return 'VotingVoteConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition, vcTreePosition: $vcTreePosition)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVoteConfirmationCopyWith<$Res> + implements $VotingVoteConfirmationCopyWith<$Res> { + factory _$VotingVoteConfirmationCopyWith(_VotingVoteConfirmation value, + $Res Function(_VotingVoteConfirmation) _then) = + __$VotingVoteConfirmationCopyWithImpl; + @override + @useResult + $Res call({String txHash, int vanLeafPosition, BigInt vcTreePosition}); +} + +/// @nodoc +class __$VotingVoteConfirmationCopyWithImpl<$Res> + implements _$VotingVoteConfirmationCopyWith<$Res> { + __$VotingVoteConfirmationCopyWithImpl(this._self, this._then); + + final _VotingVoteConfirmation _self; + final $Res Function(_VotingVoteConfirmation) _then; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? txHash = null, + Object? vanLeafPosition = null, + Object? vcTreePosition = null, + }) { + return _then(_VotingVoteConfirmation( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String, + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int, + vcTreePosition: null == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// @nodoc +mixin _$VotingVotePayloads { + VotingVoteSubmission get submission; + List get sharePayloads; + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVotePayloadsCopyWith get copyWith => + _$VotingVotePayloadsCopyWithImpl( + this as VotingVotePayloads, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVotePayloads && + (identical(other.submission, submission) || + other.submission == submission) && + const DeepCollectionEquality() + .equals(other.sharePayloads, sharePayloads)); + } + + @override + int get hashCode => Object.hash(runtimeType, submission, + const DeepCollectionEquality().hash(sharePayloads)); + + @override + String toString() { + return 'VotingVotePayloads(submission: $submission, sharePayloads: $sharePayloads)'; + } +} + +/// @nodoc +abstract mixin class $VotingVotePayloadsCopyWith<$Res> { + factory $VotingVotePayloadsCopyWith( + VotingVotePayloads value, $Res Function(VotingVotePayloads) _then) = + _$VotingVotePayloadsCopyWithImpl; + @useResult + $Res call( + {VotingVoteSubmission submission, + List sharePayloads}); + + $VotingVoteSubmissionCopyWith<$Res> get submission; +} + +/// @nodoc +class _$VotingVotePayloadsCopyWithImpl<$Res> + implements $VotingVotePayloadsCopyWith<$Res> { + _$VotingVotePayloadsCopyWithImpl(this._self, this._then); + + final VotingVotePayloads _self; + final $Res Function(VotingVotePayloads) _then; + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? submission = null, + Object? sharePayloads = null, + }) { + return _then(_self.copyWith( + submission: null == submission + ? _self.submission + : submission // ignore: cast_nullable_to_non_nullable + as VotingVoteSubmission, + sharePayloads: null == sharePayloads + ? _self.sharePayloads + : sharePayloads // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingVoteSubmissionCopyWith<$Res> get submission { + return $VotingVoteSubmissionCopyWith<$Res>(_self.submission, (value) { + return _then(_self.copyWith(submission: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingVotePayloads]. +extension VotingVotePayloadsPatterns on VotingVotePayloads { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVotePayloads value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVotePayloads() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVotePayloads value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVotePayloads(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVotePayloads value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVotePayloads() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(VotingVoteSubmission submission, + List sharePayloads)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVotePayloads() when $default != null: + return $default(_that.submission, _that.sharePayloads); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(VotingVoteSubmission submission, + List sharePayloads) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVotePayloads(): + return $default(_that.submission, _that.sharePayloads); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(VotingVoteSubmission submission, + List sharePayloads)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVotePayloads() when $default != null: + return $default(_that.submission, _that.sharePayloads); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVotePayloads implements VotingVotePayloads { + const _VotingVotePayloads( + {required this.submission, + required final List sharePayloads}) + : _sharePayloads = sharePayloads; + + @override + final VotingVoteSubmission submission; + final List _sharePayloads; + @override + List get sharePayloads { + if (_sharePayloads is EqualUnmodifiableListView) return _sharePayloads; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_sharePayloads); + } + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVotePayloadsCopyWith<_VotingVotePayloads> get copyWith => + __$VotingVotePayloadsCopyWithImpl<_VotingVotePayloads>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVotePayloads && + (identical(other.submission, submission) || + other.submission == submission) && + const DeepCollectionEquality() + .equals(other._sharePayloads, _sharePayloads)); + } + + @override + int get hashCode => Object.hash(runtimeType, submission, + const DeepCollectionEquality().hash(_sharePayloads)); + + @override + String toString() { + return 'VotingVotePayloads(submission: $submission, sharePayloads: $sharePayloads)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVotePayloadsCopyWith<$Res> + implements $VotingVotePayloadsCopyWith<$Res> { + factory _$VotingVotePayloadsCopyWith( + _VotingVotePayloads value, $Res Function(_VotingVotePayloads) _then) = + __$VotingVotePayloadsCopyWithImpl; + @override + @useResult + $Res call( + {VotingVoteSubmission submission, + List sharePayloads}); + + @override + $VotingVoteSubmissionCopyWith<$Res> get submission; +} + +/// @nodoc +class __$VotingVotePayloadsCopyWithImpl<$Res> + implements _$VotingVotePayloadsCopyWith<$Res> { + __$VotingVotePayloadsCopyWithImpl(this._self, this._then); + + final _VotingVotePayloads _self; + final $Res Function(_VotingVotePayloads) _then; + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? submission = null, + Object? sharePayloads = null, + }) { + return _then(_VotingVotePayloads( + submission: null == submission + ? _self.submission + : submission // ignore: cast_nullable_to_non_nullable + as VotingVoteSubmission, + sharePayloads: null == sharePayloads + ? _self._sharePayloads + : sharePayloads // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingVoteSubmissionCopyWith<$Res> get submission { + return $VotingVoteSubmissionCopyWith<$Res>(_self.submission, (value) { + return _then(_self.copyWith(submission: value)); + }); + } +} + +/// @nodoc +mixin _$VotingVoteSubmission { + String get voteRoundId; + int get proposalId; + Uint8List get vanNullifier; + Uint8List get voteAuthorityNoteNew; + Uint8List get voteCommitment; + Uint8List get proof; + Uint8List get rVpk; + Uint8List get voteAuthSig; + int get anchorHeight; + + /// Create a copy of VotingVoteSubmission + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteSubmissionCopyWith get copyWith => + _$VotingVoteSubmissionCopyWithImpl( + this as VotingVoteSubmission, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteSubmission && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + voteRoundId, + proposalId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + anchorHeight); + + @override + String toString() { + return 'VotingVoteSubmission(voteRoundId: $voteRoundId, proposalId: $proposalId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, rVpk: $rVpk, voteAuthSig: $voteAuthSig, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteSubmissionCopyWith<$Res> { + factory $VotingVoteSubmissionCopyWith(VotingVoteSubmission value, + $Res Function(VotingVoteSubmission) _then) = + _$VotingVoteSubmissionCopyWithImpl; + @useResult + $Res call( + {String voteRoundId, + int proposalId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + Uint8List rVpk, + Uint8List voteAuthSig, + int anchorHeight}); +} + +/// @nodoc +class _$VotingVoteSubmissionCopyWithImpl<$Res> + implements $VotingVoteSubmissionCopyWith<$Res> { + _$VotingVoteSubmissionCopyWithImpl(this._self, this._then); + + final VotingVoteSubmission _self; + final $Res Function(VotingVoteSubmission) _then; + + /// Create a copy of VotingVoteSubmission + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? voteRoundId = null, + Object? proposalId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? anchorHeight = null, + }) { + return _then(_self.copyWith( + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteSubmission]. +extension VotingVoteSubmissionPatterns on VotingVoteSubmission { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVoteSubmission value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVoteSubmission value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVoteSubmission value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String voteRoundId, + int proposalId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + Uint8List rVpk, + Uint8List voteAuthSig, + int anchorHeight)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission() when $default != null: + return $default( + _that.voteRoundId, + _that.proposalId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.rVpk, + _that.voteAuthSig, + _that.anchorHeight); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String voteRoundId, + int proposalId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + Uint8List rVpk, + Uint8List voteAuthSig, + int anchorHeight) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission(): + return $default( + _that.voteRoundId, + _that.proposalId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.rVpk, + _that.voteAuthSig, + _that.anchorHeight); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String voteRoundId, + int proposalId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + Uint8List rVpk, + Uint8List voteAuthSig, + int anchorHeight)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteSubmission() when $default != null: + return $default( + _that.voteRoundId, + _that.proposalId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.rVpk, + _that.voteAuthSig, + _that.anchorHeight); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVoteSubmission implements VotingVoteSubmission { + const _VotingVoteSubmission( + {required this.voteRoundId, + required this.proposalId, + required this.vanNullifier, + required this.voteAuthorityNoteNew, + required this.voteCommitment, + required this.proof, + required this.rVpk, + required this.voteAuthSig, + required this.anchorHeight}); + + @override + final String voteRoundId; + @override + final int proposalId; + @override + final Uint8List vanNullifier; + @override + final Uint8List voteAuthorityNoteNew; + @override + final Uint8List voteCommitment; + @override + final Uint8List proof; + @override + final Uint8List rVpk; + @override + final Uint8List voteAuthSig; + @override + final int anchorHeight; + + /// Create a copy of VotingVoteSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVoteSubmissionCopyWith<_VotingVoteSubmission> get copyWith => + __$VotingVoteSubmissionCopyWithImpl<_VotingVoteSubmission>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVoteSubmission && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + voteRoundId, + proposalId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + anchorHeight); + + @override + String toString() { + return 'VotingVoteSubmission(voteRoundId: $voteRoundId, proposalId: $proposalId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, rVpk: $rVpk, voteAuthSig: $voteAuthSig, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVoteSubmissionCopyWith<$Res> + implements $VotingVoteSubmissionCopyWith<$Res> { + factory _$VotingVoteSubmissionCopyWith(_VotingVoteSubmission value, + $Res Function(_VotingVoteSubmission) _then) = + __$VotingVoteSubmissionCopyWithImpl; + @override + @useResult + $Res call( + {String voteRoundId, + int proposalId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + Uint8List rVpk, + Uint8List voteAuthSig, + int anchorHeight}); +} + +/// @nodoc +class __$VotingVoteSubmissionCopyWithImpl<$Res> + implements _$VotingVoteSubmissionCopyWith<$Res> { + __$VotingVoteSubmissionCopyWithImpl(this._self, this._then); + + final _VotingVoteSubmission _self; + final $Res Function(_VotingVoteSubmission) _then; + + /// Create a copy of VotingVoteSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? voteRoundId = null, + Object? proposalId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? anchorHeight = null, + }) { + return _then(_VotingVoteSubmission( + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +// dart format on diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index c2c201e83..3aa7b2ff8 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -23,6 +23,7 @@ import 'api/sweep.dart'; import 'api/sync.dart'; import 'api/transaction.dart'; import 'api/vault.dart'; +import 'api/voting.dart'; import 'api/zsa.dart'; import 'dart:async'; import 'dart:convert'; @@ -94,7 +95,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 151776773; + int get rustContentHash => -1244747988; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -229,6 +230,33 @@ abstract class RustLibApi extends BaseApi { Future crateApiRaptorDecode({required List packet}); + Future crateApiVotingDelegationConfirm( + {required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c}); + + Future crateApiVotingDelegationPrepare( + {required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c}); + + Future crateApiVotingDelegationSetup( + {required String roundId, required int bundleIndex, required Coin c}); + + Future crateApiVotingDelegationSignAndSubmit( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c}); + Future crateApiAccountDeleteAccount( {required int account, required Coin c}); @@ -612,6 +640,46 @@ abstract class RustLibApi extends BaseApi { bool crateApiOpenaliasValidateZcashAddress( {required String address, required Coin c}); + Future crateApiVotingVotingCommit( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}); + + Future crateApiVotingVotingConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c}); + + Future crateApiVotingVotingHotkeyCreate({required Coin c}); + + Future crateApiVotingVotingHotkeyGet({required Coin c}); + + Future crateApiVotingVotingPayloads( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}); + + Future crateApiVotingVotingRecordExecution( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c}); + + Future crateApiVotingVotingVanWitness( + {required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c}); + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault; @@ -658,24 +726,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { {required DartVault that, required List vaultBytes, required String masterPassword}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - sse_encode_list_prim_u_8_loose(vaultBytes, serializer); - sse_encode_String(masterPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 1, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_restored_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRecoverConstMeta, - argValues: [that, vaultBytes, masterPassword], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(vaultBytes, serializer); + sse_encode_String(masterPassword, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 1, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_restored_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRecoverConstMeta, + argValues: [that, vaultBytes, masterPassword], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultRecoverConstMeta => @@ -690,25 +760,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required List vaultBytes, required String deviceIdStr, required List prfOutput}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - sse_encode_list_prim_u_8_loose(vaultBytes, serializer); - sse_encode_String(deviceIdStr, serializer); - sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 2, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_restored_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRecoverWithPrfConstMeta, - argValues: [that, vaultBytes, deviceIdStr, prfOutput], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(vaultBytes, serializer); + sse_encode_String(deviceIdStr, serializer); + sse_encode_list_prim_u_8_loose(prfOutput, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 2, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_restored_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRecoverWithPrfConstMeta, + argValues: [that, vaultBytes, deviceIdStr, prfOutput], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultRecoverWithPrfConstMeta => @@ -724,26 +796,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required String masterPassword, required String deviceIdStr, required List prfOutput}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - sse_encode_list_prim_u_8_loose(initBytes, serializer); - sse_encode_String(masterPassword, serializer); - sse_encode_String(deviceIdStr, serializer); - sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 3, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultRegisterDeviceConstMeta, - argValues: [that, initBytes, masterPassword, deviceIdStr, prfOutput], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_list_prim_u_8_loose(initBytes, serializer); + sse_encode_String(masterPassword, serializer); + sse_encode_String(deviceIdStr, serializer); + sse_encode_list_prim_u_8_loose(prfOutput, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 3, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultRegisterDeviceConstMeta, + argValues: [that, initBytes, masterPassword, deviceIdStr, prfOutput], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultRegisterDeviceConstMeta => @@ -764,25 +838,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { String? oldPassword, required String newPassword, Uint8List? oldBytes}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - sse_encode_opt_String(oldPassword, serializer); - sse_encode_String(newPassword, serializer); - sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 4, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultSetMasterPasswordConstMeta, - argValues: [that, oldPassword, newPassword, oldBytes], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_opt_String(oldPassword, serializer); + sse_encode_String(newPassword, serializer); + sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 4, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultSetMasterPasswordConstMeta, + argValues: [that, oldPassword, newPassword, oldBytes], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultSetMasterPasswordConstMeta => @@ -801,38 +877,40 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required bool useInternal, required int birthHeight, required List pk}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - sse_encode_u_32(timestamp, serializer); - sse_encode_String(name, serializer); - sse_encode_String(seed, serializer); - sse_encode_u_32(aindex, serializer); - sse_encode_bool(useInternal, serializer); - sse_encode_u_32(birthHeight, serializer); - sse_encode_list_prim_u_8_loose(pk, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 5, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultDartVaultStoreAccountConstMeta, - argValues: [ - that, - timestamp, - name, - seed, - aindex, - useInternal, - birthHeight, - pk - ], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + sse_encode_u_32(timestamp, serializer); + sse_encode_String(name, serializer); + sse_encode_String(seed, serializer); + sse_encode_u_32(aindex, serializer); + sse_encode_bool(useInternal, serializer); + sse_encode_u_32(birthHeight, serializer); + sse_encode_list_prim_u_8_loose(pk, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 5, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultDartVaultStoreAccountConstMeta, + argValues: [ + that, + timestamp, + name, + seed, + aindex, + useInternal, + birthHeight, + pk + ], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultStoreAccountConstMeta => @@ -852,22 +930,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiVaultDartVaultTest({required DartVault that}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 6, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiVaultDartVaultTestConstMeta, - argValues: [that], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 6, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiVaultDartVaultTestConstMeta, + argValues: [that], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultDartVaultTestConstMeta => const TaskConstMeta( @@ -877,22 +957,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMempoolMempoolCancel({required Mempool that}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 7, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolMempoolCancelConstMeta, - argValues: [that], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 7, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMempoolMempoolCancelConstMeta, + argValues: [that], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => @@ -903,20 +985,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Mempool crateApiMempoolMempoolNew() { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, - decodeErrorData: null, - ), - constMeta: kCrateApiMempoolMempoolNewConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool, + decodeErrorData: null, + ), + constMeta: kCrateApiMempoolMempoolNewConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMempoolMempoolNewConstMeta => const TaskConstMeta( @@ -928,24 +1012,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Stream crateApiMempoolMempoolRun( {required Mempool that, required Coin c}) { final mempoolSink = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); - sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 9, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolMempoolRunConstMeta, - argValues: [that, mempoolSink, c], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + that, serializer); + sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 9, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMempoolMempoolRunConstMeta, + argValues: [that, mempoolSink, c], + apiImpl: this, + ), + ), + ); return mempoolSink.stream; } @@ -957,22 +1045,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMigrateNoteMigrationCancel( {required NoteMigration that}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 10, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationCancelConstMeta, - argValues: [that], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 10, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationCancelConstMeta, + argValues: [that], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMigrateNoteMigrationCancelConstMeta => @@ -983,20 +1073,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override NoteMigration crateApiMigrateNoteMigrationNew() { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11)!; + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationNewConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => @@ -1011,25 +1103,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required Coin c, required BigInt meanDelayMs}) { final sink = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); - sse_encode_StreamSink_migration_status_Sse(sink, serializer); - sse_encode_box_autoadd_coin(c, serializer); - sse_encode_u_64(meanDelayMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 12, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateNoteMigrationRunConstMeta, - argValues: [that, sink, c, meanDelayMs], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + sse_encode_StreamSink_migration_status_Sse(sink, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_u_64(meanDelayMs, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 12, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateNoteMigrationRunConstMeta, + argValues: [that, sink, c, meanDelayMs], + apiImpl: this, + ), + ), + ); return sink.stream; } @@ -1042,22 +1138,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiMigrateNoteMigrationUpdateHeight( {required NoteMigration that, required int height}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); - sse_encode_u_32(height, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMigrateNoteMigrationUpdateHeightConstMeta, - argValues: [that, height], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + that, serializer); + sse_encode_u_32(height, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiMigrateNoteMigrationUpdateHeightConstMeta, + argValues: [that, height], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMigrateNoteMigrationUpdateHeightConstMeta => @@ -1069,22 +1167,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSweepTransparentScannerCancel( {required TransparentScanner that}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 14, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerCancelConstMeta, - argValues: [that], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 14, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSweepTransparentScannerCancelConstMeta, + argValues: [that], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSweepTransparentScannerCancelConstMeta => @@ -1095,21 +1195,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSweepTransparentScannerNew() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 15, port: port_); - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerNewConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 15, port: port_); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSweepTransparentScannerNewConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => @@ -1125,26 +1227,30 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required int gapLimit, required Coin c}) { final addressStream = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); - sse_encode_StreamSink_String_Sse(addressStream, serializer); - sse_encode_u_32(endHeight, serializer); - sse_encode_u_32(gapLimit, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 16, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSweepTransparentScannerRunConstMeta, - argValues: [that, addressStream, endHeight, gapLimit, c], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + that, serializer); + sse_encode_StreamSink_String_Sse(addressStream, serializer); + sse_encode_u_32(endHeight, serializer); + sse_encode_u_32(gapLimit, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 16, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSweepTransparentScannerRunConstMeta, + argValues: [that, addressStream, endHeight, gapLimit, c], + apiImpl: this, + ), + ), + ); return addressStream.stream; } @@ -1156,21 +1262,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncBalance({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 17, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pool_balance, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncBalanceConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 17, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pool_balance, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncBalanceConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncBalanceConstMeta => const TaskConstMeta( @@ -1181,23 +1289,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayBroadcastTransaction( {required int height, required List txBytes, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(txBytes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 18, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayBroadcastTransactionConstMeta, - argValues: [height, txBytes, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(txBytes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 18, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayBroadcastTransactionConstMeta, + argValues: [height, txBytes, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayBroadcastTransactionConstMeta => @@ -1208,21 +1318,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayBuildPuri({required List recipients}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 19, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayBuildPuriConstMeta, - argValues: [recipients], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 19, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayBuildPuriConstMeta, + argValues: [recipients], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayBuildPuriConstMeta => const TaskConstMeta( @@ -1233,22 +1345,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncCacheBlockTime( {required int height, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 20, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncCacheBlockTimeConstMeta, - argValues: [height, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 20, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncCacheBlockTimeConstMeta, + argValues: [height, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncCacheBlockTimeConstMeta => const TaskConstMeta( @@ -1258,21 +1372,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostCancelDkg({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 21, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostCancelDkgConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 21, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostCancelDkgConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostCancelDkgConstMeta => const TaskConstMeta( @@ -1282,20 +1398,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncCancelSync() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 22, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncCancelSyncConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 22, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncCancelSyncConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncCancelSyncConstMeta => const TaskConstMeta( @@ -1309,24 +1427,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required String tmpDir, required String oldPassword, required String newPassword}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - sse_encode_String(tmpDir, serializer); - sse_encode_String(oldPassword, serializer); - sse_encode_String(newPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 23, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbChangeDbPasswordConstMeta, - argValues: [dbFilepath, tmpDir, oldPassword, newPassword], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + sse_encode_String(tmpDir, serializer); + sse_encode_String(oldPassword, serializer); + sse_encode_String(newPassword, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 23, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbChangeDbPasswordConstMeta, + argValues: [dbFilepath, tmpDir, oldPassword, newPassword], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiDbChangeDbPasswordConstMeta => const TaskConstMeta( @@ -1336,19 +1456,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override SaplingParamsStatus crateApiSaplingCheckSaplingParams() { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_sapling_params_status, - decodeErrorData: null, + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_sapling_params_status, + decodeErrorData: null, + ), + constMeta: kCrateApiSaplingCheckSaplingParamsConstMeta, + argValues: [], + apiImpl: this, ), - constMeta: kCrateApiSaplingCheckSaplingParamsConstMeta, - argValues: [], - apiImpl: this, - )); + ); } TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => @@ -1359,21 +1481,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinClosePool({required String dbFilepath}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 25, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinClosePoolConstMeta, - argValues: [dbFilepath], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 25, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinClosePoolConstMeta, + argValues: [dbFilepath], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinClosePoolConstMeta => const TaskConstMeta( @@ -1383,21 +1507,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinCoinGetName({required Coin that}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 26, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinCoinGetNameConstMeta, - argValues: [that], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 26, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinCoinGetNameConstMeta, + argValues: [that], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinGetNameConstMeta => const TaskConstMeta( @@ -1407,20 +1533,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Coin crateApiCoinCoinNew({int? defaultCoin}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinCoinNewConstMeta, - argValues: [defaultCoin], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_8(defaultCoin, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinCoinNewConstMeta, + argValues: [defaultCoin], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinNewConstMeta => const TaskConstMeta( @@ -1431,23 +1559,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinCoinOpenDatabase( {required Coin that, required String dbFilepath, String? password}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_String(dbFilepath, serializer); - sse_encode_opt_String(password, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 28, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinOpenDatabaseConstMeta, - argValues: [that, dbFilepath, password], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_String(dbFilepath, serializer); + sse_encode_opt_String(password, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 28, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinOpenDatabaseConstMeta, + argValues: [that, dbFilepath, password], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinOpenDatabaseConstMeta => @@ -1459,22 +1589,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinCoinSetAccount( {required Coin that, required int account}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_u_32(account, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 29, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetAccountConstMeta, - argValues: [that, account], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_u_32(account, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 29, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinSetAccountConstMeta, + argValues: [that, account], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinSetAccountConstMeta => const TaskConstMeta( @@ -1485,22 +1617,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Coin crateApiCoinCoinSetLwd( {required Coin that, required int serverType, required String url}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_u_8(serverType, serializer); - sse_encode_String(url, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetLwdConstMeta, - argValues: [that, serverType, url], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_u_8(serverType, serializer); + sse_encode_String(url, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinSetLwdConstMeta, + argValues: [that, serverType, url], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinSetLwdConstMeta => const TaskConstMeta( @@ -1510,21 +1644,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_String(proxy, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetProxyConstMeta, - argValues: [that, proxy], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_String(proxy, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinSetProxyConstMeta, + argValues: [that, proxy], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinSetProxyConstMeta => const TaskConstMeta( @@ -1535,22 +1671,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinCoinSetUseTor( {required Coin that, required bool useTor}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(that, serializer); - sse_encode_bool(useTor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 32, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_coin, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinCoinSetUseTorConstMeta, - argValues: [that, useTor], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(that, serializer); + sse_encode_bool(useTor, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 32, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_coin, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinCoinSetUseTorConstMeta, + argValues: [that, useTor], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinCoinSetUseTorConstMeta => const TaskConstMeta( @@ -1564,24 +1702,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required List addresses, required String notes, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_list_String(addresses, serializer); - sse_encode_String(notes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 33, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsCreateContactConstMeta, - argValues: [name, addresses, notes, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_list_String(addresses, serializer); + sse_encode_String(notes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 33, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_contact, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsCreateContactConstMeta, + argValues: [name, addresses, notes, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsCreateContactConstMeta => @@ -1593,22 +1733,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountCreateNewCategory( {required Category category, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_category(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 34, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountCreateNewCategoryConstMeta, - argValues: [category, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_category(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 34, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountCreateNewCategoryConstMeta, + argValues: [category, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountCreateNewCategoryConstMeta => @@ -1620,22 +1762,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountCreateNewFolder( {required String name, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 35, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_folder, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountCreateNewFolderConstMeta, - argValues: [name, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 35, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_folder, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountCreateNewFolderConstMeta, + argValues: [name, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountCreateNewFolderConstMeta => @@ -1646,21 +1790,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiRaptorDecode({required List packet}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(packet, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 36, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorDecodeConstMeta, - argValues: [packet], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(packet, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 36, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorDecodeConstMeta, + argValues: [packet], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiRaptorDecodeConstMeta => const TaskConstMeta( @@ -1668,25 +1814,201 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["packet"], ); + @override + Future crateApiVotingDelegationConfirm( + {required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(txHash, serializer); + sse_encode_String(eventsJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 37, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_delegation_confirmation, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationConfirmConstMeta, + argValues: [roundId, bundleIndex, txHash, eventsJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationConfirmConstMeta => + const TaskConstMeta( + debugName: "delegation_confirm", + argNames: ["roundId", "bundleIndex", "txHash", "eventsJson", "c"], + ); + + @override + Future crateApiVotingDelegationPrepare( + {required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundParamsJson, serializer); + sse_encode_String(roundName, serializer); + sse_encode_opt_String(sessionJson, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_opt_box_autoadd_u_32(maxRealNotesPerBundle, serializer); + sse_encode_String(lightwalletdUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 38, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_prepared_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationPrepareConstMeta, + argValues: [ + roundParamsJson, + roundName, + sessionJson, + bundleIndex, + maxRealNotesPerBundle, + lightwalletdUrl, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationPrepareConstMeta => + const TaskConstMeta( + debugName: "delegation_prepare", + argNames: [ + "roundParamsJson", + "roundName", + "sessionJson", + "bundleIndex", + "maxRealNotesPerBundle", + "lightwalletdUrl", + "c" + ], + ); + + @override + Future crateApiVotingDelegationSetup( + {required String roundId, required int bundleIndex, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 39, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_delegation_setup, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationSetupConstMeta, + argValues: [roundId, bundleIndex, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationSetupConstMeta => + const TaskConstMeta( + debugName: "delegation_setup", + argNames: ["roundId", "bundleIndex", "c"], + ); + + @override + Future crateApiVotingDelegationSignAndSubmit( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_list_prim_u_8_loose(pcztBytes, serializer); + sse_encode_box_autoadd_voting_pir_layout(pirLayout, serializer); + sse_encode_String(pirServerUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 40, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_delegation_submission, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationSignAndSubmitConstMeta, + argValues: [ + roundId, + bundleIndex, + pcztBytes, + pirLayout, + pirServerUrl, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationSignAndSubmitConstMeta => + const TaskConstMeta( + debugName: "delegation_sign_and_submit", + argNames: [ + "roundId", + "bundleIndex", + "pcztBytes", + "pirLayout", + "pirServerUrl", + "c" + ], + ); + @override Future crateApiAccountDeleteAccount( {required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 37, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteAccountConstMeta, - argValues: [account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 41, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountDeleteAccountConstMeta, + argValues: [account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => @@ -1698,22 +2020,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountDeleteCategories( {required List ids, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 38, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteCategoriesConstMeta, - argValues: [ids, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 42, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountDeleteCategoriesConstMeta, + argValues: [ids, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => @@ -1725,22 +2049,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiContactsDeleteContacts( {required List ids, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 39, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsDeleteContactsConstMeta, - argValues: [ids, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 43, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsDeleteContactsConstMeta, + argValues: [ids, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => @@ -1752,22 +2078,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountDeleteFolders( {required List ids, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 40, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountDeleteFoldersConstMeta, - argValues: [ids, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 44, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountDeleteFoldersConstMeta, + argValues: [ids, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => @@ -1779,22 +2107,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiFrostDoDkg({required Coin c}) { final status = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_dkg_status_Sse(status, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 41, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostDoDkgConstMeta, - argValues: [status, c], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_dkg_status_Sse(status, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 45, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostDoDkgConstMeta, + argValues: [status, c], + apiImpl: this, + ), + ), + ); return status.stream; } @@ -1806,22 +2138,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiFrostDoSign({required Coin c}) { final status = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_signing_status_Sse(status, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 42, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostDoSignConstMeta, - argValues: [status, c], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_signing_status_Sse(status, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 46, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostDoSignConstMeta, + argValues: [status, c], + apiImpl: this, + ), + ), + ); return status.stream; } @@ -1832,20 +2168,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSaplingDownloadSaplingParams() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 43, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSaplingDownloadSaplingParamsConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 47, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSaplingDownloadSaplingParamsConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => @@ -1856,21 +2194,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountDummyExport({required SigningEvent a}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_signing_event(a, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 44, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountDummyExportConstMeta, - argValues: [a], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_signing_event(a, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 48, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountDummyExportConstMeta, + argValues: [a], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountDummyExportConstMeta => const TaskConstMeta( @@ -1881,22 +2221,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiRaptorEncode( {required String path, required RaptorQParams params}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(path, serializer); - sse_encode_box_autoadd_raptor_q_params(params, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 45, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorEncodeConstMeta, - argValues: [path, params], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(path, serializer); + sse_encode_box_autoadd_raptor_q_params(params, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 49, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorEncodeConstMeta, + argValues: [path, params], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiRaptorEncodeConstMeta => const TaskConstMeta( @@ -1906,20 +2248,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiRaptorEndDecode() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 46, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorEndDecodeConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 50, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorEndDecodeConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiRaptorEndDecodeConstMeta => const TaskConstMeta( @@ -1930,23 +2274,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountExportAccount( {required int id, required String passphrase, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_String(passphrase, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 47, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountExportAccountConstMeta, - argValues: [id, passphrase, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_String(passphrase, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 51, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountExportAccountConstMeta, + argValues: [id, passphrase, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountExportAccountConstMeta => @@ -1957,21 +2303,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiContactsExportContactsVcard({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 48, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsExportContactsVcardConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 52, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsExportContactsVcardConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => @@ -1983,21 +2331,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayExtractTransaction( {required PcztPackage package}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(package, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 49, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayExtractTransactionConstMeta, - argValues: [package], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(package, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 53, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayExtractTransactionConstMeta, + argValues: [package], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayExtractTransactionConstMeta => @@ -2009,23 +2359,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountFetchAddressTxCount( {required Coin c, required bool aggregate, required int poolFilter}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - sse_encode_bool(aggregate, serializer); - sse_encode_u_8(poolFilter, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 50, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_t_address_tx_count, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountFetchAddressTxCountConstMeta, - argValues: [c, aggregate, poolFilter], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_bool(aggregate, serializer); + sse_encode_u_8(poolFilter, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 54, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_t_address_tx_count, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountFetchAddressTxCountConstMeta, + argValues: [c, aggregate, poolFilter], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountFetchAddressTxCountConstMeta => @@ -2037,24 +2389,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiTransactionFetchAmounts( {int? from, int? to, required int category, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_32(from, serializer); - sse_encode_opt_box_autoadd_u_32(to, serializer); - sse_encode_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 51, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_record_u_32_f_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFetchAmountsConstMeta, - argValues: [from, to, category, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_32(from, serializer); + sse_encode_opt_box_autoadd_u_32(to, serializer); + sse_encode_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 55, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_record_u_32_f_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionFetchAmountsConstMeta, + argValues: [from, to, category, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionFetchAmountsConstMeta => @@ -2066,23 +2420,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiTransactionFetchCategoryAmounts( {int? from, int? to, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_opt_box_autoadd_u_32(from, serializer); - sse_encode_opt_box_autoadd_u_32(to, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 52, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_record_string_f_64_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFetchCategoryAmountsConstMeta, - argValues: [from, to, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_opt_box_autoadd_u_32(from, serializer); + sse_encode_opt_box_autoadd_u_32(to, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 56, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_record_string_f_64_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionFetchCategoryAmountsConstMeta, + argValues: [from, to, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionFetchCategoryAmountsConstMeta => @@ -2094,21 +2450,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountFetchTransparentAddressTxCount( {required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 53, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_t_address_tx_count, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountFetchTransparentAddressTxCountConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 57, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_t_address_tx_count, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountFetchTransparentAddressTxCountConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountFetchTransparentAddressTxCountConstMeta => @@ -2120,22 +2478,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncFetchTxDetails( {required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 54, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncFetchTxDetailsConstMeta, - argValues: [account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 58, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncFetchTxDetailsConstMeta, + argValues: [account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncFetchTxDetailsConstMeta => const TaskConstMeta( @@ -2146,23 +2506,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiTransactionFillMissingTxPrices( {required String api, required String currency, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(currency, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 55, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionFillMissingTxPricesConstMeta, - argValues: [api, currency, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(currency, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 59, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionFillMissingTxPricesConstMeta, + argValues: [api, currency, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionFillMissingTxPricesConstMeta => @@ -2174,22 +2536,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiContactsFindContactsForAddress( {required String address, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 56, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact_match, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsFindContactsForAddressConstMeta, - argValues: [address, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 60, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact_match, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsFindContactsForAddressConstMeta, + argValues: [address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsFindContactsForAddressConstMeta => @@ -2200,20 +2564,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostFrostSignParamsDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 57, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_frost_sign_params, - decodeErrorData: null, - ), - constMeta: kCrateApiFrostFrostSignParamsDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 61, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_frost_sign_params, + decodeErrorData: null, + ), + constMeta: kCrateApiFrostFrostSignParamsDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => @@ -2224,21 +2590,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGenerateNextChangeAddress({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 58, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGenerateNextChangeAddressConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 62, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGenerateNextChangeAddressConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGenerateNextChangeAddressConstMeta => @@ -2249,21 +2617,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGenerateNextDindex({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 59, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGenerateNextDindexConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 63, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGenerateNextDindexConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => @@ -2274,19 +2644,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override String crateApiKeyGenerateSeed() { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 60)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiKeyGenerateSeedConstMeta, + argValues: [], + apiImpl: this, ), - constMeta: kCrateApiKeyGenerateSeedConstMeta, - argValues: [], - apiImpl: this, - )); + ); } TaskConstMeta get kCrateApiKeyGenerateSeedConstMeta => const TaskConstMeta( @@ -2297,23 +2669,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountAddresses( {required int account, required int uaPools, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_u_8(uaPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 61, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_addresses, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountAddressesConstMeta, - argValues: [account, uaPools, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_u_8(uaPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 65, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_addresses, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountAddressesConstMeta, + argValues: [account, uaPools, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountAddressesConstMeta => @@ -2325,22 +2699,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountFingerprint( {required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 62, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountFingerprintConstMeta, - argValues: [account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 66, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountFingerprintConstMeta, + argValues: [account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountFingerprintConstMeta => @@ -2351,21 +2727,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountFrostParams({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 63, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountFrostParamsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 67, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountFrostParamsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountFrostParamsConstMeta => @@ -2377,22 +2755,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountPools( {required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 64, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_8, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountPoolsConstMeta, - argValues: [account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 68, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_8, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountPoolsConstMeta, + argValues: [account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountPoolsConstMeta => @@ -2404,22 +2784,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountSeed( {required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_box_autoadd_seed, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountSeedConstMeta, - argValues: [account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 69, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_seed, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountSeedConstMeta, + argValues: [account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountSeedConstMeta => @@ -2431,23 +2813,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAccountUfvk( {required int account, required int pools, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); - sse_encode_u_8(pools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAccountUfvkConstMeta, - argValues: [account, pools, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(account, serializer); + sse_encode_u_8(pools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 70, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAccountUfvkConstMeta, + argValues: [account, pools, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAccountUfvkConstMeta => @@ -2459,22 +2843,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetAddresses( {required int uaPools, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(uaPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_addresses, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetAddressesConstMeta, - argValues: [uaPools, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(uaPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 71, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_addresses, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetAddressesConstMeta, + argValues: [uaPools, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetAddressesConstMeta => @@ -2486,23 +2872,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkGetCoingeckoPrice( {required String api, required String currency}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(currency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_f_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetCoingeckoPriceConstMeta, - argValues: [api, currency], - apiImpl: this, - )); - } + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(currency, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 72, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_f_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetCoingeckoPriceConstMeta, + argValues: [api, currency], + apiImpl: this, + ), + ); + } TaskConstMeta get kCrateApiNetworkGetCoingeckoPriceConstMeta => const TaskConstMeta( @@ -2512,21 +2900,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkGetCurrentHeight({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 69, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetCurrentHeightConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 73, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetCurrentHeightConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => @@ -2537,21 +2927,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncGetDbHeight({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 70, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_sync_height, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncGetDbHeightConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 74, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_sync_height, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncGetDbHeightConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncGetDbHeightConstMeta => const TaskConstMeta( @@ -2561,21 +2953,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiFrostGetDkgAddresses({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 71, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostGetDkgAddressesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 75, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostGetDkgAddressesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => @@ -2589,23 +2983,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { {required String api, required String fromCurrency, required String toCurrency}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - sse_encode_String(fromCurrency, serializer); - sse_encode_String(toCurrency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_exchange_rate, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetExchangeRateConstMeta, - argValues: [api, fromCurrency, toCurrency], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + sse_encode_String(fromCurrency, serializer); + sse_encode_String(toCurrency, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 76, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_exchange_rate, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetExchangeRateConstMeta, + argValues: [api, fromCurrency, toCurrency], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkGetExchangeRateConstMeta => @@ -2617,22 +3013,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetExportedData( {required int type, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(type, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 73, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetExportedDataConstMeta, - argValues: [type, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(type, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 77, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetExportedDataConstMeta, + argValues: [type, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetExportedDataConstMeta => @@ -2643,21 +3041,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override int crateApiKeyGetKeyPools({required String key, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_8, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiKeyGetKeyPoolsConstMeta, - argValues: [key, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_8, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiKeyGetKeyPoolsConstMeta, + argValues: [key, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyGetKeyPoolsConstMeta => const TaskConstMeta( @@ -2668,22 +3068,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMempoolGetMempoolTx( {required String txId, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(txId, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 75, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMempoolGetMempoolTxConstMeta, - argValues: [txId, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(txId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 79, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMempoolGetMempoolTxConstMeta, + argValues: [txId, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => @@ -2694,21 +3096,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMigrateGetMigrationStatus({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 76, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_migration_status, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateGetMigrationStatusConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 80, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_migration_status, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateGetMigrationStatusConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => @@ -2719,21 +3123,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkGetNetworkName({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: null, - ), - constMeta: kCrateApiNetworkGetNetworkNameConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 81, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kCrateApiNetworkGetNetworkNameConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => @@ -2744,22 +3150,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiDbGetProp({required String key, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 78, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbGetPropConstMeta, - argValues: [key, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 82, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbGetPropConstMeta, + argValues: [key, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiDbGetPropConstMeta => const TaskConstMeta( @@ -2769,20 +3177,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Uint8List crateApiRaptorGetQrBytes({required List data}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiRaptorGetQrBytesConstMeta, - argValues: [data], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(data, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiRaptorGetQrBytesConstMeta, + argValues: [data], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiRaptorGetQrBytesConstMeta => const TaskConstMeta( @@ -2793,21 +3203,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiNetworkGetSupportedVsCurrencies( {required String api}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(api, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkGetSupportedVsCurrenciesConstMeta, - argValues: [api], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(api, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 84, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkGetSupportedVsCurrenciesConstMeta, + argValues: [api], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkGetSupportedVsCurrenciesConstMeta => @@ -2818,20 +3230,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinGetTorClient() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiCoinGetTorClientConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 85, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiCoinGetTorClientConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinGetTorClientConstMeta => const TaskConstMeta( @@ -2842,22 +3256,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountGetTxDetails( {required int idTx, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(idTx, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountGetTxDetailsConstMeta, - argValues: [idTx, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(idTx, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 86, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountGetTxDetailsConstMeta, + argValues: [idTx, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => @@ -2868,21 +3284,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostHasDkgAddresses({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 83, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostHasDkgAddressesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 87, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostHasDkgAddressesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => @@ -2893,21 +3311,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostHasDkgParams({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostHasDkgParamsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 88, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostHasDkgParamsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostHasDkgParamsConstMeta => const TaskConstMeta( @@ -2917,21 +3337,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountHasTransparentPubKey({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountHasTransparentPubKeyConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 89, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountHasTransparentPubKeyConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountHasTransparentPubKeyConstMeta => @@ -2943,23 +3365,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountImportAccount( {required String passphrase, required List data, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(passphrase, serializer); - sse_encode_list_prim_u_8_loose(data, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountImportAccountConstMeta, - argValues: [passphrase, data, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(passphrase, serializer); + sse_encode_list_prim_u_8_loose(data, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 90, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountImportAccountConstMeta, + argValues: [passphrase, data, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountImportAccountConstMeta => @@ -2971,22 +3395,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiContactsImportContactsVcard( {required String vcardData, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(vcardData, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsImportContactsVcardConstMeta, - argValues: [vcardData, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(vcardData, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 91, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsImportContactsVcardConstMeta, + argValues: [vcardData, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsImportContactsVcardConstMeta => @@ -2997,20 +3423,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiInitInitApp() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 88, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitInitAppConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 92, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitInitAppConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiInitInitAppConstMeta => const TaskConstMeta( @@ -3020,20 +3448,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiRaptorInitApp() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 89, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiRaptorInitAppConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 93, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiRaptorInitAppConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiRaptorInitAppConstMeta => const TaskConstMeta( @@ -3043,21 +3473,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiCoinInitDatadir({required String directory}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 90, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiCoinInitDatadirConstMeta, - argValues: [directory], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(directory, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 94, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiCoinInitDatadirConstMeta, + argValues: [directory], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiCoinInitDatadirConstMeta => const TaskConstMeta( @@ -3067,21 +3499,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkInitDatadir({required String directory}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkInitDatadirConstMeta, - argValues: [directory], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(directory, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 95, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkInitDatadirConstMeta, + argValues: [directory], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkInitDatadirConstMeta => const TaskConstMeta( @@ -3091,21 +3525,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostInitDkg({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 92, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostInitDkgConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 96, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostInitDkgConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostInitDkgConstMeta => const TaskConstMeta( @@ -3115,19 +3551,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiPluginInitPlugins() { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 93)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginInitPluginsConstMeta, + argValues: [], + apiImpl: this, ), - constMeta: kCrateApiPluginInitPluginsConstMeta, - argValues: [], - apiImpl: this, - )); + ); } TaskConstMeta get kCrateApiPluginInitPluginsConstMeta => const TaskConstMeta( @@ -3141,24 +3579,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required int fundingAccount, required PcztPackage pczt, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(coordinator, serializer); - sse_encode_u_32(fundingAccount, serializer); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostInitSignConstMeta, - argValues: [coordinator, fundingAccount, pczt, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(coordinator, serializer); + sse_encode_u_32(fundingAccount, serializer); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 98, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostInitSignConstMeta, + argValues: [coordinator, fundingAccount, pczt, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostInitSignConstMeta => const TaskConstMeta( @@ -3169,23 +3609,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiVaultInitVault( {required FutureOr Function(Uint8List) append}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - append, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 95, port: port_); - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiVaultInitVaultConstMeta, - argValues: [append], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + append, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 99, port: port_); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVaultInitVaultConstMeta, + argValues: [append], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiVaultInitVaultConstMeta => const TaskConstMeta( @@ -3196,22 +3638,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPluginInstallPlugin( {required String url, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(url, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 96, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_plugin_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginInstallPluginConstMeta, - argValues: [url, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(url, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 100, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_plugin_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginInstallPluginConstMeta, + argValues: [url, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => @@ -3222,21 +3666,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiNetworkIsIronwoodActive({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 97, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkIsIronwoodActiveConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 101, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkIsIronwoodActiveConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => @@ -3247,21 +3693,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostIsSigningInProgress({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 98, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostIsSigningInProgressConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 102, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostIsSigningInProgressConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => @@ -3272,21 +3720,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsTexAddress({required String address, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 99)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsTexAddressConstMeta, - argValues: [address, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 103)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsTexAddressConstMeta, + argValues: [address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsTexAddressConstMeta => const TaskConstMeta( @@ -3296,20 +3747,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidAddress({required String address}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 100)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidAddressConstMeta, - argValues: [address], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 104)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidAddressConstMeta, + argValues: [address], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsValidAddressConstMeta => const TaskConstMeta( @@ -3319,21 +3773,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidFvk({required String fvk, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(fvk, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 101)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidFvkConstMeta, - argValues: [fvk, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(fvk, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 105)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidFvkConstMeta, + argValues: [fvk, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsValidFvkConstMeta => const TaskConstMeta( @@ -3343,21 +3800,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidKey({required String key, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 102)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidKeyConstMeta, - argValues: [key, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 106)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidKeyConstMeta, + argValues: [key, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsValidKeyConstMeta => const TaskConstMeta( @@ -3367,20 +3827,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidPhrase({required String phrase}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 103)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidPhraseConstMeta, - argValues: [phrase], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(phrase, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 107)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidPhraseConstMeta, + argValues: [phrase], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsValidPhraseConstMeta => const TaskConstMeta( @@ -3391,21 +3854,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiKeyIsValidTransparentAddress( {required String address, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 104)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiKeyIsValidTransparentAddressConstMeta, - argValues: [address, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 108)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiKeyIsValidTransparentAddressConstMeta, + argValues: [address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiKeyIsValidTransparentAddressConstMeta => @@ -3416,21 +3882,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiZsaIsZsaAvailable({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiZsaIsZsaAvailableConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 109, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiZsaIsZsaAvailableConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiZsaIsZsaAvailableConstMeta => const TaskConstMeta( @@ -3447,35 +3915,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Uint8List? descHash, required int idAccount, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(assetName, serializer); - sse_encode_u_64(amount, serializer); - sse_encode_bool(firstIssuance, serializer); - sse_encode_bool(finalize, serializer); - sse_encode_opt_list_prim_u_8_strict(descHash, serializer); - sse_encode_u_32(idAccount, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiIssuanceIssueAssetConstMeta, - argValues: [ - assetName, - amount, - firstIssuance, - finalize, - descHash, - idAccount, - c - ], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(assetName, serializer); + sse_encode_u_64(amount, serializer); + sse_encode_bool(firstIssuance, serializer); + sse_encode_bool(finalize, serializer); + sse_encode_opt_list_prim_u_8_strict(descHash, serializer); + sse_encode_u_32(idAccount, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 110, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiIssuanceIssueAssetConstMeta, + argValues: [ + assetName, + amount, + firstIssuance, + finalize, + descHash, + idAccount, + c + ], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiIssuanceIssueAssetConstMeta => const TaskConstMeta( @@ -3493,21 +3963,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListAccounts({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_account, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListAccountsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 111, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_account, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListAccountsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListAccountsConstMeta => @@ -3518,21 +3990,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListCategories({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_category, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListCategoriesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 112, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_category, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListCategoriesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => @@ -3543,21 +4017,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiContactsListContacts({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_contact, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsListContactsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 113, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_contact, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsListContactsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsListContactsConstMeta => @@ -3569,21 +4045,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiDbListDbAccounts( {required String dbFilepath}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_db_account_preview, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbListDbAccountsConstMeta, - argValues: [dbFilepath], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dbFilepath, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 114, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_db_account_preview, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbListDbAccountsConstMeta, + argValues: [dbFilepath], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiDbListDbAccountsConstMeta => const TaskConstMeta( @@ -3593,21 +4071,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiDbListDbNames({required String dir}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(dir, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbListDbNamesConstMeta, - argValues: [dir], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(dir, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 115, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbListDbNamesConstMeta, + argValues: [dir], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiDbListDbNamesConstMeta => const TaskConstMeta( @@ -3617,21 +4097,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListFolders({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_folder, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListFoldersConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 116, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_folder, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListFoldersConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListFoldersConstMeta => const TaskConstMeta( @@ -3641,21 +4123,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListMemos({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_memo, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListMemosConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 117, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_memo, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListMemosConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListMemosConstMeta => const TaskConstMeta( @@ -3665,21 +4149,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListNotes({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_tx_note, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListNotesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 118, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_tx_note, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListNotesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListNotesConstMeta => const TaskConstMeta( @@ -3689,21 +4175,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiPluginListPlugins({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_plugin_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginListPluginsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 119, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_plugin_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginListPluginsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPluginListPluginsConstMeta => const TaskConstMeta( @@ -3713,21 +4201,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiAccountListTxHistory({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_tx, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountListTxHistoryConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 120, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_tx, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListTxHistoryConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => @@ -3738,21 +4228,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiZsaListZsaHoldings({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_zsa_holding, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiZsaListZsaHoldingsConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 121, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_zsa_holding, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiZsaListZsaHoldingsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiZsaListZsaHoldingsConstMeta => const TaskConstMeta( @@ -3763,23 +4255,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountLockNote( {required int id, required bool locked, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_bool(locked, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountLockNoteConstMeta, - argValues: [id, locked, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_bool(locked, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 122, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountLockNoteConstMeta, + argValues: [id, locked, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountLockNoteConstMeta => const TaskConstMeta( @@ -3790,23 +4284,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountLockRecentNotes( {required int height, required int threshold, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_u_32(threshold, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountLockRecentNotesConstMeta, - argValues: [height, threshold, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_u_32(threshold, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 123, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountLockRecentNotesConstMeta, + argValues: [height, threshold, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountLockRecentNotesConstMeta => @@ -3817,21 +4313,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountMaxSpendable({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_64, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountMaxSpendableConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 124, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountMaxSpendableConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => @@ -3843,22 +4341,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountNewAccount( {required NewAccount na, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_new_account(na, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountNewAccountConstMeta, - argValues: [na, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_new_account(na, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 125, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountNewAccountConstMeta, + argValues: [na, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountNewAccountConstMeta => const TaskConstMeta( @@ -3868,21 +4368,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayPackTransaction({required PcztPackage pczt}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPackTransactionConstMeta, - argValues: [pczt], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 126, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPackTransactionConstMeta, + argValues: [pczt], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayPackTransactionConstMeta => const TaskConstMeta( @@ -3893,22 +4395,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiPluginParseMemoWithPlugins( {required List memoBytes, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(memoBytes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_memo_section, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginParseMemoWithPluginsConstMeta, - argValues: [memoBytes, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(memoBytes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 127, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_memo_section, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginParseMemoWithPluginsConstMeta, + argValues: [memoBytes, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPluginParseMemoWithPluginsConstMeta => @@ -3919,20 +4423,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override List? crateApiPayParsePaymentUri({required String uri}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(uri, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 124)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_opt_list_recipient, - decodeErrorData: null, - ), - constMeta: kCrateApiPayParsePaymentUriConstMeta, - argValues: [uri], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(uri, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 128)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_list_recipient, + decodeErrorData: null, + ), + constMeta: kCrateApiPayParsePaymentUriConstMeta, + argValues: [uri], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayParsePaymentUriConstMeta => const TaskConstMeta( @@ -3945,23 +4452,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { {required List recipients, required PaymentOptions options, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - sse_encode_box_autoadd_payment_options(options, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPrepareConstMeta, - argValues: [recipients, options, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + sse_encode_box_autoadd_payment_options(options, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 129, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPrepareConstMeta, + argValues: [recipients, options, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayPrepareConstMeta => const TaskConstMeta( @@ -3974,23 +4483,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { {required List recipients, required int srcPools, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_recipient(recipients, serializer); - sse_encode_u_8(srcPools, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayPrepareMigrationConstMeta, - argValues: [recipients, srcPools, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_recipient(recipients, serializer); + sse_encode_u_8(srcPools, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 130, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPrepareMigrationConstMeta, + argValues: [recipients, srcPools, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayPrepareMigrationConstMeta => @@ -4001,22 +4512,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountPrintKeys({required int id, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountPrintKeysConstMeta, - argValues: [id, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 131, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountPrintKeysConstMeta, + argValues: [id, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountPrintKeysConstMeta => const TaskConstMeta( @@ -4027,23 +4540,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiDbPutProp( {required String key, required String value, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(key, serializer); - sse_encode_String(value, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiDbPutPropConstMeta, - argValues: [key, value, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(key, serializer); + sse_encode_String(value, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 132, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDbPutPropConstMeta, + argValues: [key, value, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiDbPutPropConstMeta => const TaskConstMeta( @@ -4053,21 +4568,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future> crateApiNetworkQueryLwdList({required int coin}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(coin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_lwd_info, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiNetworkQueryLwdListConstMeta, - argValues: [coin], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(coin, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 133, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_lwd_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiNetworkQueryLwdListConstMeta, + argValues: [coin], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => @@ -4078,20 +4595,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountReceiversDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_receivers, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountReceiversDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 134, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_receivers, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountReceiversDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => @@ -4103,21 +4622,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Receivers crateApiAccountReceiversFromUa( {required String ua, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(ua, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 131)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_receivers, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountReceiversFromUaConstMeta, - argValues: [ua, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ua, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 135)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_receivers, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountReceiversFromUaConstMeta, + argValues: [ua, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountReceiversFromUaConstMeta => @@ -4129,22 +4651,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountRemoveAccount( {required int accountId, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(accountId, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRemoveAccountConstMeta, - argValues: [accountId, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(accountId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 136, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountRemoveAccountConstMeta, + argValues: [accountId, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountRemoveAccountConstMeta => @@ -4156,22 +4680,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPluginRemovePlugin( {required String id, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginRemovePluginConstMeta, - argValues: [id, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 137, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginRemovePluginConstMeta, + argValues: [id, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPluginRemovePluginConstMeta => const TaskConstMeta( @@ -4182,22 +4708,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountRenameCategory( {required Category category, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_category(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRenameCategoryConstMeta, - argValues: [category, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_category(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 138, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountRenameCategoryConstMeta, + argValues: [category, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountRenameCategoryConstMeta => @@ -4209,23 +4737,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountRenameFolder( {required int id, required String name, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountRenameFolderConstMeta, - argValues: [id, name, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 139, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountRenameFolderConstMeta, + argValues: [id, name, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountRenameFolderConstMeta => @@ -4237,23 +4767,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountReorderAccount( {required int oldPosition, required int newPosition, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(oldPosition, serializer); - sse_encode_u_32(newPosition, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountReorderAccountConstMeta, - argValues: [oldPosition, newPosition, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(oldPosition, serializer); + sse_encode_u_32(newPosition, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 140, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountReorderAccountConstMeta, + argValues: [oldPosition, newPosition, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountReorderAccountConstMeta => @@ -4264,21 +4796,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostResetSign({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostResetSignConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 141, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostResetSignConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostResetSignConstMeta => const TaskConstMeta( @@ -4288,22 +4822,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountResetSync({required int id, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountResetSyncConstMeta, - argValues: [id, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 142, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountResetSyncConstMeta, + argValues: [id, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountResetSyncConstMeta => const TaskConstMeta( @@ -4314,22 +4850,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiOpenaliasResolveOpenalias( {required String alias, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasConstMeta, - argValues: [alias, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 143, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiOpenaliasResolveOpenaliasConstMeta, + argValues: [alias, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasConstMeta => @@ -4341,21 +4879,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiOpenaliasResolveOpenaliasAll( {required String alias}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasAllConstMeta, - argValues: [alias], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 144, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiOpenaliasResolveOpenaliasAllConstMeta, + argValues: [alias], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasAllConstMeta => @@ -4367,21 +4907,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiOpenaliasResolveOpenaliasRaw( {required String alias}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_raw_open_alias_resolution, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasResolveOpenaliasRawConstMeta, - argValues: [alias], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 145, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_raw_open_alias_resolution, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiOpenaliasResolveOpenaliasRawConstMeta, + argValues: [alias], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasResolveOpenaliasRawConstMeta => @@ -4393,23 +4935,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiSyncRewindSync( {required int height, required int account, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_u_32(account, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncRewindSyncConstMeta, - argValues: [height, account, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_u_32(account, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 146, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncRewindSyncConstMeta, + argValues: [height, account, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiSyncRewindSyncConstMeta => const TaskConstMeta( @@ -4420,23 +4964,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPaySend( {required int height, required List data, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(data, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPaySendConstMeta, - argValues: [height, data, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(data, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 147, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPaySendConstMeta, + argValues: [height, data, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPaySendConstMeta => const TaskConstMeta( @@ -4447,23 +4993,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiZsaSetAssetName( {required PlatformInt64 idAsset, required String name, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_i_64(idAsset, serializer); - sse_encode_String(name, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiZsaSetAssetNameConstMeta, - argValues: [idAsset, name, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_i_64(idAsset, serializer); + sse_encode_String(name, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 148, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiZsaSetAssetNameConstMeta, + argValues: [idAsset, name, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiZsaSetAssetNameConstMeta => const TaskConstMeta( @@ -4474,23 +5022,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiFrostSetDkgAddress( {required int id, required String address, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_8(id, serializer); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostSetDkgAddressConstMeta, - argValues: [id, address, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_8(id, serializer); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 149, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostSetDkgAddressConstMeta, + argValues: [id, address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostSetDkgAddressConstMeta => const TaskConstMeta( @@ -4506,26 +5056,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required int t, required int fundingAccount, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(name, serializer); - sse_encode_u_8(id, serializer); - sse_encode_u_8(n, serializer); - sse_encode_u_8(t, serializer); - sse_encode_u_32(fundingAccount, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiFrostSetDkgParamsConstMeta, - argValues: [name, id, n, t, fundingAccount, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(name, serializer); + sse_encode_u_8(id, serializer); + sse_encode_u_8(n, serializer); + sse_encode_u_8(t, serializer); + sse_encode_u_32(fundingAccount, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 150, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiFrostSetDkgParamsConstMeta, + argValues: [name, id, n, t, fundingAccount, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiFrostSetDkgParamsConstMeta => const TaskConstMeta( @@ -4535,20 +5087,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiInitSetExpertMode({required bool enabled}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_bool(enabled, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 147)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitSetExpertModeConstMeta, - argValues: [enabled], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_bool(enabled, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 151)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitSetExpertModeConstMeta, + argValues: [enabled], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiInitSetExpertModeConstMeta => const TaskConstMeta( @@ -4559,20 +5114,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Stream crateApiInitSetLogStream() { final s = RustStreamSink(); - handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_log_message_Sse(s, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 148)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiInitSetLogStreamConstMeta, - argValues: [s], - apiImpl: this, - )); + handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_log_message_Sse(s, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 152)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiInitSetLogStreamConstMeta, + argValues: [s], + apiImpl: this, + ), + ); return s.stream; } @@ -4584,23 +5142,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPluginSetPluginEnabled( {required String id, required bool enabled, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(id, serializer); - sse_encode_bool(enabled, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPluginSetPluginEnabledConstMeta, - argValues: [id, enabled, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(id, serializer); + sse_encode_bool(enabled, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 153, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPluginSetPluginEnabledConstMeta, + argValues: [id, enabled, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPluginSetPluginEnabledConstMeta => @@ -4612,23 +5172,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiTransactionSetTxCategory( {required int id, int? category, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_box_autoadd_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetTxCategoryConstMeta, - argValues: [id, category, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_box_autoadd_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 154, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionSetTxCategoryConstMeta, + argValues: [id, category, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionSetTxCategoryConstMeta => @@ -4640,23 +5202,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiTransactionSetTxPrice( {required int id, double? price, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_box_autoadd_f_64(price, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetTxPriceConstMeta, - argValues: [id, price, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_box_autoadd_f_64(price, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 155, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionSetTxPriceConstMeta, + argValues: [id, price, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionSetTxPriceConstMeta => @@ -4668,23 +5232,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiTransactionSetUserMemo( {required int idTx, String? memo, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(idTx, serializer); - sse_encode_opt_String(memo, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionSetUserMemoConstMeta, - argValues: [idTx, memo, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(idTx, serializer); + sse_encode_opt_String(memo, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 156, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionSetUserMemoConstMeta, + argValues: [idTx, memo, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionSetUserMemoConstMeta => @@ -4695,21 +5261,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountShowLedgerSaplingAddress({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountShowLedgerSaplingAddressConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 157, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountShowLedgerSaplingAddressConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountShowLedgerSaplingAddressConstMeta => @@ -4721,21 +5289,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountShowLedgerTransparentAddress( {required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountShowLedgerTransparentAddressConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 158, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountShowLedgerTransparentAddressConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountShowLedgerTransparentAddressConstMeta => @@ -4748,23 +5318,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Stream crateApiAccountSignLedgerTransaction( {required PcztPackage package, required Coin c}) { final sink = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_signing_event_Sse(sink, serializer); - sse_encode_box_autoadd_pczt_package(package, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountSignLedgerTransactionConstMeta, - argValues: [sink, package, c], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_signing_event_Sse(sink, serializer); + sse_encode_box_autoadd_pczt_package(package, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 159, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountSignLedgerTransactionConstMeta, + argValues: [sink, package, c], + apiImpl: this, + ), + ), + ); return sink.stream; } @@ -4777,22 +5351,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPaySignTransaction( {required PcztPackage pczt, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(pczt, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPaySignTransactionConstMeta, - argValues: [pczt, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 160, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPaySignTransactionConstMeta, + argValues: [pczt, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPaySignTransactionConstMeta => const TaskConstMeta( @@ -4802,21 +5378,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiMigrateStepMigration({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_migration_event, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMigrateStepMigrationConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 161, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_migration_event, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMigrateStepMigrationConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => @@ -4832,25 +5410,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { double? price, int? category, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(height, serializer); - sse_encode_list_prim_u_8_loose(txid, serializer); - sse_encode_opt_box_autoadd_f_64(price, serializer); - sse_encode_opt_box_autoadd_u_32(category, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayStorePendingTxConstMeta, - argValues: [height, txid, price, category, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(height, serializer); + sse_encode_list_prim_u_8_loose(txid, serializer); + sse_encode_opt_box_autoadd_f_64(price, serializer); + sse_encode_opt_box_autoadd_u_32(category, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 162, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayStorePendingTxConstMeta, + argValues: [height, txid, price, category, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayStorePendingTxConstMeta => const TaskConstMeta( @@ -4868,37 +5448,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required bool fast, required Coin c}) { final progress = RustStreamSink(); - unawaited(handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_StreamSink_sync_progress_Sse(progress, serializer); - sse_encode_list_prim_u_32_loose(accounts, serializer); - sse_encode_u_32(currentHeight, serializer); - sse_encode_u_32(actionsPerSync, serializer); - sse_encode_u_32(transparentLimit, serializer); - sse_encode_u_32(checkpointAge, serializer); - sse_encode_bool(fast, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_u_32, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiSyncSynchronizeConstMeta, - argValues: [ - progress, - accounts, - currentHeight, - actionsPerSync, - transparentLimit, - checkpointAge, - fast, - c - ], - apiImpl: this, - ))); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_sync_progress_Sse(progress, serializer); + sse_encode_list_prim_u_32_loose(accounts, serializer); + sse_encode_u_32(currentHeight, serializer); + sse_encode_u_32(actionsPerSync, serializer); + sse_encode_u_32(transparentLimit, serializer); + sse_encode_u_32(checkpointAge, serializer); + sse_encode_bool(fast, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 163, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_32, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiSyncSynchronizeConstMeta, + argValues: [ + progress, + accounts, + currentHeight, + actionsPerSync, + transparentLimit, + checkpointAge, + fast, + c + ], + apiImpl: this, + ), + ), + ); return progress.stream; } @@ -4918,21 +5502,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override TxPlan crateApiPayToPlan({required PcztPackage package, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_pczt_package(package, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 160)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_plan, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayToPlanConstMeta, - argValues: [package, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(package, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 164)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_plan, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayToPlanConstMeta, + argValues: [package, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayToPlanConstMeta => const TaskConstMeta( @@ -4942,21 +5529,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountToggleAllNotes({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountToggleAllNotesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 165, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountToggleAllNotesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => @@ -4968,21 +5557,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override void crateApiOpenaliasTryValidateZcashAddress( {required String address, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 162)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiOpenaliasTryValidateZcashAddressConstMeta, - argValues: [address, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 166)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiOpenaliasTryValidateZcashAddressConstMeta, + argValues: [address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasTryValidateZcashAddressConstMeta => @@ -4993,20 +5585,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountTxAccountDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_account, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxAccountDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 167, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_account, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxAccountDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => @@ -5017,20 +5611,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountTxMemoDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_memo, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxMemoDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 168, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_memo, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxMemoDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => @@ -5041,20 +5637,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountTxNoteDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_note, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxNoteDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 169, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_note, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxNoteDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => @@ -5065,20 +5663,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountTxOutputDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_output, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxOutputDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 170, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_output, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxOutputDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => @@ -5089,20 +5689,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountTxSpendDefault() { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_tx_spend, - decodeErrorData: null, - ), - constMeta: kCrateApiAccountTxSpendDefaultConstMeta, - argValues: [], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 171, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_tx_spend, + decodeErrorData: null, + ), + constMeta: kCrateApiAccountTxSpendDefaultConstMeta, + argValues: [], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => @@ -5114,22 +5716,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override String crateApiAccountUaFromUfvk( {required String ufvk, int? di, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(ufvk, serializer); - sse_encode_opt_box_autoadd_u_32(di, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 168)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_String, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUaFromUfvkConstMeta, - argValues: [ufvk, di, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ufvk, serializer); + sse_encode_opt_box_autoadd_u_32(di, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 172)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountUaFromUfvkConstMeta, + argValues: [ufvk, di, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountUaFromUfvkConstMeta => const TaskConstMeta( @@ -5139,21 +5744,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountUnlockAllNotes({required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUnlockAllNotesConstMeta, - argValues: [c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 173, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountUnlockAllNotesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => @@ -5164,21 +5771,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiPayUnpackTransaction({required List bytes}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_pczt_package, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiPayUnpackTransactionConstMeta, - argValues: [bytes], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(bytes, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 174, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayUnpackTransactionConstMeta, + argValues: [bytes], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => @@ -5190,22 +5799,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override Future crateApiAccountUpdateAccount( {required AccountUpdate update, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_box_autoadd_account_update(update, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiAccountUpdateAccountConstMeta, - argValues: [update, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_account_update(update, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 175, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountUpdateAccountConstMeta, + argValues: [update, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiAccountUpdateAccountConstMeta => @@ -5221,25 +5832,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { List? addresses, String? notes, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(id, serializer); - sse_encode_opt_String(name, serializer); - sse_encode_opt_list_String(addresses, serializer); - sse_encode_opt_String(notes, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiContactsUpdateContactConstMeta, - argValues: [id, name, addresses, notes, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(id, serializer); + sse_encode_opt_String(name, serializer); + sse_encode_opt_list_String(addresses, serializer); + sse_encode_opt_String(notes, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 176, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsUpdateContactConstMeta, + argValues: [id, name, addresses, notes, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiContactsUpdateContactConstMeta => @@ -5253,23 +5866,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { {required String currency, required double exchangeRate, required Coin c}) { - return handler.executeNormal(NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(currency, serializer); - sse_encode_f_64(exchangeRate, serializer); - sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiTransactionUpdateHistoricalPricesConstMeta, - argValues: [currency, exchangeRate, c], - apiImpl: this, - )); + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(currency, serializer); + sse_encode_f_64(exchangeRate, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 177, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiTransactionUpdateHistoricalPricesConstMeta, + argValues: [currency, exchangeRate, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiTransactionUpdateHistoricalPricesConstMeta => @@ -5280,20 +5895,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiOpenaliasValidateOpenaliasName({required String alias}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(alias, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 174)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiOpenaliasValidateOpenaliasNameConstMeta, - argValues: [alias], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(alias, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 178)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiOpenaliasValidateOpenaliasNameConstMeta, + argValues: [alias], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasValidateOpenaliasNameConstMeta => @@ -5305,21 +5923,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @override bool crateApiOpenaliasValidateZcashAddress( {required String address, required Coin c}) { - return handler.executeSync(SyncTask( - callFfi: () { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(address, serializer); - sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 175)!; - }, - codec: SseCodec( - decodeSuccessData: sse_decode_bool, - decodeErrorData: null, - ), - constMeta: kCrateApiOpenaliasValidateZcashAddressConstMeta, - argValues: [address, c], - apiImpl: this, - )); + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(address, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 179)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiOpenaliasValidateZcashAddressConstMeta, + argValues: [address, c], + apiImpl: this, + ), + ); } TaskConstMeta get kCrateApiOpenaliasValidateZcashAddressConstMeta => @@ -5328,6 +5949,264 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["address", "c"], ); + @override + Future crateApiVotingVotingCommit( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(draftsJson, serializer); + sse_encode_String(voteNodeUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 180, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_commitments, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingCommitConstMeta, + argValues: [roundId, bundleIndex, draftsJson, voteNodeUrl, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingCommitConstMeta => const TaskConstMeta( + debugName: "voting_commit", + argNames: ["roundId", "bundleIndex", "draftsJson", "voteNodeUrl", "c"], + ); + + @override + Future crateApiVotingVotingConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_String(txHash, serializer); + sse_encode_String(eventsJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 181, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_confirmation, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingConfirmConstMeta, + argValues: [roundId, bundleIndex, proposalId, txHash, eventsJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingConfirmConstMeta => + const TaskConstMeta( + debugName: "voting_confirm", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "txHash", + "eventsJson", + "c" + ], + ); + + @override + Future crateApiVotingVotingHotkeyCreate({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 182, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingHotkeyCreateConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingHotkeyCreateConstMeta => + const TaskConstMeta( + debugName: "voting_hotkey_create", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingHotkeyGet({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 183, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingHotkeyGetConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingHotkeyGetConstMeta => + const TaskConstMeta( + debugName: "voting_hotkey_get", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingPayloads( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 184, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_payloads, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingPayloadsConstMeta, + argValues: [roundId, bundleIndex, proposalId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingPayloadsConstMeta => + const TaskConstMeta( + debugName: "voting_payloads", + argNames: ["roundId", "bundleIndex", "proposalId", "c"], + ); + + @override + Future crateApiVotingVotingRecordExecution( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_String(voteTxHash, serializer); + sse_encode_u_64(vcTreePosition, serializer); + sse_encode_String(shareDeliveriesJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 185, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRecordExecutionConstMeta, + argValues: [ + roundId, + bundleIndex, + proposalId, + voteTxHash, + vcTreePosition, + shareDeliveriesJson, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRecordExecutionConstMeta => + const TaskConstMeta( + debugName: "voting_record_execution", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "voteTxHash", + "vcTreePosition", + "shareDeliveriesJson", + "c" + ], + ); + + @override + Future crateApiVotingVotingVanWitness( + {required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(voteNodeUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 186, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_van_witness, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingVanWitnessConstMeta, + argValues: [roundId, bundleIndex, voteNodeUrl, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingVanWitnessConstMeta => + const TaskConstMeta( + debugName: "voting_van_witness", + argNames: ["roundId", "bundleIndex", "voteNodeUrl", "c"], + ); + Future Function(int, dynamic) encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( FutureOr Function(Uint8List) raw) { @@ -5354,10 +6233,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final output = serializer.intoRaw(); generalizedFrbRustBinding.dartFnDeliverOutput( - callId: callId, - ptr: output.ptr, - rustVecLen: output.rustVecLen, - dataLen: output.dataLen); + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); }; } @@ -5754,6 +6634,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as int; } + @protected + VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_voting_pir_layout(raw); + } + @protected Category dco_decode_category(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -6134,6 +7020,30 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_tx_spend).toList(); } + @protected + List dco_decode_list_voting_encrypted_share( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_encrypted_share) + .toList(); + } + + @protected + List dco_decode_list_voting_share_payload(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_share_payload).toList(); + } + + @protected + List + dco_decode_list_voting_signed_vote_commitment(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_signed_vote_commitment) + .toList(); + } + @protected List dco_decode_list_zsa_holding(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -6839,88 +7749,290 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - TxPlanIn dco_decode_tx_plan_in(dynamic raw) { + TxPlanIn dco_decode_tx_plan_in(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return TxPlanIn( + pool: dco_decode_u_8(arr[0]), + amount: dco_decode_opt_box_autoadd_u_64(arr[1]), + assetName: dco_decode_String(arr[2]), + ); + } + + @protected + TxPlanOut dco_decode_tx_plan_out(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return TxPlanOut( + pool: dco_decode_u_8(arr[0]), + amount: dco_decode_u_64(arr[1]), + address: dco_decode_String(arr[2]), + assetName: dco_decode_String(arr[3]), + ); + } + + @protected + TxSpend dco_decode_tx_spend(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + return TxSpend( + id: dco_decode_u_32(arr[0]), + pool: dco_decode_u_8(arr[1]), + height: dco_decode_u_32(arr[2]), + value: dco_decode_u_64(arr[3]), + idAsset: dco_decode_opt_box_autoadd_u_32(arr[4]), + assetDisplay: dco_decode_String(arr[5]), + ); + } + + @protected + int dco_decode_u_16(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + int dco_decode_u_32(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + BigInt dco_decode_u_64(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeU64(raw); + } + + @protected + int dco_decode_u_8(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + void dco_decode_unit(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return; + } + + @protected + BigInt dco_decode_usize(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeU64(raw); + } + + @protected + UsizeArray4 dco_decode_usize_array_4(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return UsizeArray4(dco_decode_list_prim_usize_strict(raw)); + } + + @protected + VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingDelegationConfirmation( + txHash: dco_decode_String(arr[0]), + vanLeafPosition: dco_decode_u_32(arr[1]), + ); + } + + @protected + VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 6) + throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); + return VotingDelegationSetup( + pcztBytes: dco_decode_list_prim_u_8_strict(arr[0]), + pcztSighash: dco_decode_list_prim_u_8_strict(arr[1]), + rk: dco_decode_list_prim_u_8_strict(arr[2]), + actionIndex: dco_decode_u_32(arr[3]), + actionBytes: dco_decode_list_prim_u_8_strict(arr[4]), + tx1Effects: dco_decode_list_prim_u_8_strict(arr[5]), + ); + } + + @protected + VotingDelegationSubmission dco_decode_voting_delegation_submission( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 11) + throw Exception('unexpected arr length: expect 11 but see ${arr.length}'); + return VotingDelegationSubmission( + proof: dco_decode_list_prim_u_8_strict(arr[0]), + rk: dco_decode_list_prim_u_8_strict(arr[1]), + nfSigned: dco_decode_list_prim_u_8_strict(arr[2]), + cmxNew: dco_decode_list_prim_u_8_strict(arr[3]), + govComm: dco_decode_list_prim_u_8_strict(arr[4]), + govNullifiers: dco_decode_list_list_prim_u_8_strict(arr[5]), + alpha: dco_decode_list_prim_u_8_strict(arr[6]), + voteRoundId: dco_decode_String(arr[7]), + spendAuthSig: dco_decode_list_prim_u_8_strict(arr[8]), + sighash: dco_decode_list_prim_u_8_strict(arr[9]), + tx1Effects: dco_decode_list_prim_u_8_strict(arr[10]), + ); + } + + @protected + VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; if (arr.length != 3) throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); - return TxPlanIn( - pool: dco_decode_u_8(arr[0]), - amount: dco_decode_opt_box_autoadd_u_64(arr[1]), - assetName: dco_decode_String(arr[2]), + return VotingEncryptedShare( + c1: dco_decode_list_prim_u_8_strict(arr[0]), + c2: dco_decode_list_prim_u_8_strict(arr[1]), + shareIndex: dco_decode_u_32(arr[2]), ); } @protected - TxPlanOut dco_decode_tx_plan_out(dynamic raw) { + VotingPirLayout dco_decode_voting_pir_layout(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; if (arr.length != 4) throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); - return TxPlanOut( - pool: dco_decode_u_8(arr[0]), - amount: dco_decode_u_64(arr[1]), - address: dco_decode_String(arr[2]), - assetName: dco_decode_String(arr[3]), + return VotingPirLayout( + pirDepth: dco_decode_u_32(arr[0]), + tier0Layers: dco_decode_u_32(arr[1]), + tier1Layers: dco_decode_u_32(arr[2]), + polyLen: dco_decode_u_32(arr[3]), ); } @protected - TxSpend dco_decode_tx_spend(dynamic raw) { + VotingPreparedInfo dco_decode_voting_prepared_info(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List; - if (arr.length != 6) - throw Exception('unexpected arr length: expect 6 but see ${arr.length}'); - return TxSpend( - id: dco_decode_u_32(arr[0]), - pool: dco_decode_u_8(arr[1]), - height: dco_decode_u_32(arr[2]), - value: dco_decode_u_64(arr[3]), - idAsset: dco_decode_opt_box_autoadd_u_32(arr[4]), - assetDisplay: dco_decode_String(arr[5]), + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + return VotingPreparedInfo( + roundId: dco_decode_String(arr[0]), + bundleIndex: dco_decode_u_32(arr[1]), + eligibleWeightZatoshi: dco_decode_u_64(arr[2]), + delegatedWeightZatoshi: dco_decode_u_64(arr[3]), + roundName: dco_decode_String(arr[4]), ); } @protected - int dco_decode_u_16(dynamic raw) { + VotingSharePayload dco_decode_voting_share_payload(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; + final arr = raw as List; + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + return VotingSharePayload( + sharesHash: dco_decode_list_prim_u_8_strict(arr[0]), + proposalId: dco_decode_u_32(arr[1]), + voteDecision: dco_decode_u_32(arr[2]), + encShare: dco_decode_voting_encrypted_share(arr[3]), + treePosition: dco_decode_u_64(arr[4]), + allEncShares: dco_decode_list_voting_encrypted_share(arr[5]), + shareComms: dco_decode_list_list_prim_u_8_strict(arr[6]), + primaryBlind: dco_decode_list_prim_u_8_strict(arr[7]), + ); } @protected - int dco_decode_u_32(dynamic raw) { + VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( + dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; + final arr = raw as List; + if (arr.length != 11) + throw Exception('unexpected arr length: expect 11 but see ${arr.length}'); + return VotingSignedVoteCommitment( + proposalId: dco_decode_u_32(arr[0]), + choice: dco_decode_u_32(arr[1]), + voteRoundId: dco_decode_String(arr[2]), + vanNullifier: dco_decode_list_prim_u_8_strict(arr[3]), + voteAuthorityNoteNew: dco_decode_list_prim_u_8_strict(arr[4]), + voteCommitment: dco_decode_list_prim_u_8_strict(arr[5]), + proof: dco_decode_list_prim_u_8_strict(arr[6]), + anchorHeight: dco_decode_u_32(arr[7]), + rVpk: dco_decode_list_prim_u_8_strict(arr[8]), + voteAuthSig: dco_decode_list_prim_u_8_strict(arr[9]), + commitmentBundleJson: dco_decode_String(arr[10]), + ); } @protected - BigInt dco_decode_u_64(dynamic raw) { + VotingVanWitness dco_decode_voting_van_witness(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return dcoDecodeU64(raw); + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return VotingVanWitness( + authPath: dco_decode_list_list_prim_u_8_strict(arr[0]), + position: dco_decode_u_32(arr[1]), + anchorHeight: dco_decode_u_32(arr[2]), + ); } @protected - int dco_decode_u_8(dynamic raw) { + VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingVoteCommitments( + bundleIndex: dco_decode_u_32(arr[0]), + commitments: dco_decode_list_voting_signed_vote_commitment(arr[1]), + ); } @protected - void dco_decode_unit(dynamic raw) { + VotingVoteConfirmation dco_decode_voting_vote_confirmation(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return; + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return VotingVoteConfirmation( + txHash: dco_decode_String(arr[0]), + vanLeafPosition: dco_decode_u_32(arr[1]), + vcTreePosition: dco_decode_u_64(arr[2]), + ); } @protected - BigInt dco_decode_usize(dynamic raw) { + VotingVotePayloads dco_decode_voting_vote_payloads(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return dcoDecodeU64(raw); + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingVotePayloads( + submission: dco_decode_voting_vote_submission(arr[0]), + sharePayloads: dco_decode_list_voting_share_payload(arr[1]), + ); } @protected - UsizeArray4 dco_decode_usize_array_4(dynamic raw) { + VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs - return UsizeArray4(dco_decode_list_prim_usize_strict(raw)); + final arr = raw as List; + if (arr.length != 9) + throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + return VotingVoteSubmission( + voteRoundId: dco_decode_String(arr[0]), + proposalId: dco_decode_u_32(arr[1]), + vanNullifier: dco_decode_list_prim_u_8_strict(arr[2]), + voteAuthorityNoteNew: dco_decode_list_prim_u_8_strict(arr[3]), + voteCommitment: dco_decode_list_prim_u_8_strict(arr[4]), + proof: dco_decode_list_prim_u_8_strict(arr[5]), + rVpk: dco_decode_list_prim_u_8_strict(arr[6]), + voteAuthSig: dco_decode_list_prim_u_8_strict(arr[7]), + anchorHeight: dco_decode_u_32(arr[8]), + ); } @protected @@ -7339,6 +8451,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_u_8(deserializer)); } + @protected + VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_voting_pir_layout(deserializer)); + } + @protected Category sse_decode_category(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -7878,6 +8997,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_voting_encrypted_share( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_encrypted_share(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_share_payload( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_share_payload(deserializer)); + } + return ans_; + } + + @protected + List + sse_decode_list_voting_signed_vote_commitment( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_signed_vote_commitment(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -8756,6 +9915,231 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return UsizeArray4(inner); } + @protected + VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_txHash = sse_decode_String(deserializer); + var var_vanLeafPosition = sse_decode_u_32(deserializer); + return VotingDelegationConfirmation( + txHash: var_txHash, vanLeafPosition: var_vanLeafPosition); + } + + @protected + VotingDelegationSetup sse_decode_voting_delegation_setup( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_pcztBytes = sse_decode_list_prim_u_8_strict(deserializer); + var var_pcztSighash = sse_decode_list_prim_u_8_strict(deserializer); + var var_rk = sse_decode_list_prim_u_8_strict(deserializer); + var var_actionIndex = sse_decode_u_32(deserializer); + var var_actionBytes = sse_decode_list_prim_u_8_strict(deserializer); + var var_tx1Effects = sse_decode_list_prim_u_8_strict(deserializer); + return VotingDelegationSetup( + pcztBytes: var_pcztBytes, + pcztSighash: var_pcztSighash, + rk: var_rk, + actionIndex: var_actionIndex, + actionBytes: var_actionBytes, + tx1Effects: var_tx1Effects); + } + + @protected + VotingDelegationSubmission sse_decode_voting_delegation_submission( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_proof = sse_decode_list_prim_u_8_strict(deserializer); + var var_rk = sse_decode_list_prim_u_8_strict(deserializer); + var var_nfSigned = sse_decode_list_prim_u_8_strict(deserializer); + var var_cmxNew = sse_decode_list_prim_u_8_strict(deserializer); + var var_govComm = sse_decode_list_prim_u_8_strict(deserializer); + var var_govNullifiers = sse_decode_list_list_prim_u_8_strict(deserializer); + var var_alpha = sse_decode_list_prim_u_8_strict(deserializer); + var var_voteRoundId = sse_decode_String(deserializer); + var var_spendAuthSig = sse_decode_list_prim_u_8_strict(deserializer); + var var_sighash = sse_decode_list_prim_u_8_strict(deserializer); + var var_tx1Effects = sse_decode_list_prim_u_8_strict(deserializer); + return VotingDelegationSubmission( + proof: var_proof, + rk: var_rk, + nfSigned: var_nfSigned, + cmxNew: var_cmxNew, + govComm: var_govComm, + govNullifiers: var_govNullifiers, + alpha: var_alpha, + voteRoundId: var_voteRoundId, + spendAuthSig: var_spendAuthSig, + sighash: var_sighash, + tx1Effects: var_tx1Effects); + } + + @protected + VotingEncryptedShare sse_decode_voting_encrypted_share( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_c1 = sse_decode_list_prim_u_8_strict(deserializer); + var var_c2 = sse_decode_list_prim_u_8_strict(deserializer); + var var_shareIndex = sse_decode_u_32(deserializer); + return VotingEncryptedShare( + c1: var_c1, c2: var_c2, shareIndex: var_shareIndex); + } + + @protected + VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_pirDepth = sse_decode_u_32(deserializer); + var var_tier0Layers = sse_decode_u_32(deserializer); + var var_tier1Layers = sse_decode_u_32(deserializer); + var var_polyLen = sse_decode_u_32(deserializer); + return VotingPirLayout( + pirDepth: var_pirDepth, + tier0Layers: var_tier0Layers, + tier1Layers: var_tier1Layers, + polyLen: var_polyLen); + } + + @protected + VotingPreparedInfo sse_decode_voting_prepared_info( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_eligibleWeightZatoshi = sse_decode_u_64(deserializer); + var var_delegatedWeightZatoshi = sse_decode_u_64(deserializer); + var var_roundName = sse_decode_String(deserializer); + return VotingPreparedInfo( + roundId: var_roundId, + bundleIndex: var_bundleIndex, + eligibleWeightZatoshi: var_eligibleWeightZatoshi, + delegatedWeightZatoshi: var_delegatedWeightZatoshi, + roundName: var_roundName); + } + + @protected + VotingSharePayload sse_decode_voting_share_payload( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_sharesHash = sse_decode_list_prim_u_8_strict(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_voteDecision = sse_decode_u_32(deserializer); + var var_encShare = sse_decode_voting_encrypted_share(deserializer); + var var_treePosition = sse_decode_u_64(deserializer); + var var_allEncShares = sse_decode_list_voting_encrypted_share(deserializer); + var var_shareComms = sse_decode_list_list_prim_u_8_strict(deserializer); + var var_primaryBlind = sse_decode_list_prim_u_8_strict(deserializer); + return VotingSharePayload( + sharesHash: var_sharesHash, + proposalId: var_proposalId, + voteDecision: var_voteDecision, + encShare: var_encShare, + treePosition: var_treePosition, + allEncShares: var_allEncShares, + shareComms: var_shareComms, + primaryBlind: var_primaryBlind); + } + + @protected + VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_proposalId = sse_decode_u_32(deserializer); + var var_choice = sse_decode_u_32(deserializer); + var var_voteRoundId = sse_decode_String(deserializer); + var var_vanNullifier = sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthorityNoteNew = + sse_decode_list_prim_u_8_strict(deserializer); + var var_voteCommitment = sse_decode_list_prim_u_8_strict(deserializer); + var var_proof = sse_decode_list_prim_u_8_strict(deserializer); + var var_anchorHeight = sse_decode_u_32(deserializer); + var var_rVpk = sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthSig = sse_decode_list_prim_u_8_strict(deserializer); + var var_commitmentBundleJson = sse_decode_String(deserializer); + return VotingSignedVoteCommitment( + proposalId: var_proposalId, + choice: var_choice, + voteRoundId: var_voteRoundId, + vanNullifier: var_vanNullifier, + voteAuthorityNoteNew: var_voteAuthorityNoteNew, + voteCommitment: var_voteCommitment, + proof: var_proof, + anchorHeight: var_anchorHeight, + rVpk: var_rVpk, + voteAuthSig: var_voteAuthSig, + commitmentBundleJson: var_commitmentBundleJson); + } + + @protected + VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_authPath = sse_decode_list_list_prim_u_8_strict(deserializer); + var var_position = sse_decode_u_32(deserializer); + var var_anchorHeight = sse_decode_u_32(deserializer); + return VotingVanWitness( + authPath: var_authPath, + position: var_position, + anchorHeight: var_anchorHeight); + } + + @protected + VotingVoteCommitments sse_decode_voting_vote_commitments( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_commitments = + sse_decode_list_voting_signed_vote_commitment(deserializer); + return VotingVoteCommitments( + bundleIndex: var_bundleIndex, commitments: var_commitments); + } + + @protected + VotingVoteConfirmation sse_decode_voting_vote_confirmation( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_txHash = sse_decode_String(deserializer); + var var_vanLeafPosition = sse_decode_u_32(deserializer); + var var_vcTreePosition = sse_decode_u_64(deserializer); + return VotingVoteConfirmation( + txHash: var_txHash, + vanLeafPosition: var_vanLeafPosition, + vcTreePosition: var_vcTreePosition); + } + + @protected + VotingVotePayloads sse_decode_voting_vote_payloads( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_submission = sse_decode_voting_vote_submission(deserializer); + var var_sharePayloads = sse_decode_list_voting_share_payload(deserializer); + return VotingVotePayloads( + submission: var_submission, sharePayloads: var_sharePayloads); + } + + @protected + VotingVoteSubmission sse_decode_voting_vote_submission( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_voteRoundId = sse_decode_String(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_vanNullifier = sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthorityNoteNew = + sse_decode_list_prim_u_8_strict(deserializer); + var var_voteCommitment = sse_decode_list_prim_u_8_strict(deserializer); + var var_proof = sse_decode_list_prim_u_8_strict(deserializer); + var var_rVpk = sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthSig = sse_decode_list_prim_u_8_strict(deserializer); + var var_anchorHeight = sse_decode_u_32(deserializer); + return VotingVoteSubmission( + voteRoundId: var_voteRoundId, + proposalId: var_proposalId, + vanNullifier: var_vanNullifier, + voteAuthorityNoteNew: var_voteAuthorityNoteNew, + voteCommitment: var_voteCommitment, + proof: var_proof, + rVpk: var_rVpk, + voteAuthSig: var_voteAuthSig, + anchorHeight: var_anchorHeight); + } + @protected ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -8934,12 +10318,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_String, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -8947,12 +10333,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_dkg_status, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -8960,12 +10348,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_log_message, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -8973,12 +10363,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_mempool_msg, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -8986,12 +10378,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_migration_status, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -8999,12 +10393,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_signing_event, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -9012,12 +10408,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_signing_status, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -9025,12 +10423,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( - self.setupAndSerialize( - codec: SseCodec( + self.setupAndSerialize( + codec: SseCodec( decodeSuccessData: sse_decode_sync_progress, decodeErrorData: sse_decode_AnyhowException, - )), - serializer); + ), + ), + serializer, + ); } @protected @@ -9211,6 +10611,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(self, serializer); } + @protected + void sse_encode_box_autoadd_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_pir_layout(self, serializer); + } + @protected void sse_encode_category(Category self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -9655,6 +11062,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_encrypted_share( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_encrypted_share(item, serializer); + } + } + + @protected + void sse_encode_list_voting_share_payload( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_share_payload(item, serializer); + } + } + + @protected + void sse_encode_list_voting_signed_vote_commitment( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_signed_vote_commitment(item, serializer); + } + } + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer) { @@ -10312,6 +11749,153 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_usize_strict(self.inner, serializer); } + @protected + void sse_encode_voting_delegation_confirmation( + VotingDelegationConfirmation self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.txHash, serializer); + sse_encode_u_32(self.vanLeafPosition, serializer); + } + + @protected + void sse_encode_voting_delegation_setup( + VotingDelegationSetup self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(self.pcztBytes, serializer); + sse_encode_list_prim_u_8_strict(self.pcztSighash, serializer); + sse_encode_list_prim_u_8_strict(self.rk, serializer); + sse_encode_u_32(self.actionIndex, serializer); + sse_encode_list_prim_u_8_strict(self.actionBytes, serializer); + sse_encode_list_prim_u_8_strict(self.tx1Effects, serializer); + } + + @protected + void sse_encode_voting_delegation_submission( + VotingDelegationSubmission self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(self.proof, serializer); + sse_encode_list_prim_u_8_strict(self.rk, serializer); + sse_encode_list_prim_u_8_strict(self.nfSigned, serializer); + sse_encode_list_prim_u_8_strict(self.cmxNew, serializer); + sse_encode_list_prim_u_8_strict(self.govComm, serializer); + sse_encode_list_list_prim_u_8_strict(self.govNullifiers, serializer); + sse_encode_list_prim_u_8_strict(self.alpha, serializer); + sse_encode_String(self.voteRoundId, serializer); + sse_encode_list_prim_u_8_strict(self.spendAuthSig, serializer); + sse_encode_list_prim_u_8_strict(self.sighash, serializer); + sse_encode_list_prim_u_8_strict(self.tx1Effects, serializer); + } + + @protected + void sse_encode_voting_encrypted_share( + VotingEncryptedShare self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(self.c1, serializer); + sse_encode_list_prim_u_8_strict(self.c2, serializer); + sse_encode_u_32(self.shareIndex, serializer); + } + + @protected + void sse_encode_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.pirDepth, serializer); + sse_encode_u_32(self.tier0Layers, serializer); + sse_encode_u_32(self.tier1Layers, serializer); + sse_encode_u_32(self.polyLen, serializer); + } + + @protected + void sse_encode_voting_prepared_info( + VotingPreparedInfo self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_64(self.eligibleWeightZatoshi, serializer); + sse_encode_u_64(self.delegatedWeightZatoshi, serializer); + sse_encode_String(self.roundName, serializer); + } + + @protected + void sse_encode_voting_share_payload( + VotingSharePayload self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(self.sharesHash, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.voteDecision, serializer); + sse_encode_voting_encrypted_share(self.encShare, serializer); + sse_encode_u_64(self.treePosition, serializer); + sse_encode_list_voting_encrypted_share(self.allEncShares, serializer); + sse_encode_list_list_prim_u_8_strict(self.shareComms, serializer); + sse_encode_list_prim_u_8_strict(self.primaryBlind, serializer); + } + + @protected + void sse_encode_voting_signed_vote_commitment( + VotingSignedVoteCommitment self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.choice, serializer); + sse_encode_String(self.voteRoundId, serializer); + sse_encode_list_prim_u_8_strict(self.vanNullifier, serializer); + sse_encode_list_prim_u_8_strict(self.voteAuthorityNoteNew, serializer); + sse_encode_list_prim_u_8_strict(self.voteCommitment, serializer); + sse_encode_list_prim_u_8_strict(self.proof, serializer); + sse_encode_u_32(self.anchorHeight, serializer); + sse_encode_list_prim_u_8_strict(self.rVpk, serializer); + sse_encode_list_prim_u_8_strict(self.voteAuthSig, serializer); + sse_encode_String(self.commitmentBundleJson, serializer); + } + + @protected + void sse_encode_voting_van_witness( + VotingVanWitness self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_list_prim_u_8_strict(self.authPath, serializer); + sse_encode_u_32(self.position, serializer); + sse_encode_u_32(self.anchorHeight, serializer); + } + + @protected + void sse_encode_voting_vote_commitments( + VotingVoteCommitments self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_list_voting_signed_vote_commitment(self.commitments, serializer); + } + + @protected + void sse_encode_voting_vote_confirmation( + VotingVoteConfirmation self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.txHash, serializer); + sse_encode_u_32(self.vanLeafPosition, serializer); + sse_encode_u_64(self.vcTreePosition, serializer); + } + + @protected + void sse_encode_voting_vote_payloads( + VotingVotePayloads self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_vote_submission(self.submission, serializer); + sse_encode_list_voting_share_payload(self.sharePayloads, serializer); + } + + @protected + void sse_encode_voting_vote_submission( + VotingVoteSubmission self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.voteRoundId, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_list_prim_u_8_strict(self.vanNullifier, serializer); + sse_encode_list_prim_u_8_strict(self.voteAuthorityNoteNew, serializer); + sse_encode_list_prim_u_8_strict(self.voteCommitment, serializer); + sse_encode_list_prim_u_8_strict(self.proof, serializer); + sse_encode_list_prim_u_8_strict(self.rVpk, serializer); + sse_encode_list_prim_u_8_strict(self.voteAuthSig, serializer); + sse_encode_u_32(self.anchorHeight, serializer); + } + @protected void sse_encode_zsa_holding(ZsaHolding self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 54fd0b567..21d121681 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -23,6 +23,7 @@ import 'api/sweep.dart'; import 'api/sync.dart'; import 'api/transaction.dart'; import 'api/vault.dart'; +import 'api/voting.dart'; import 'api/zsa.dart'; import 'dart:async'; import 'dart:convert'; @@ -228,6 +229,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int dco_decode_box_autoadd_u_8(dynamic raw); + @protected + VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw); + @protected Category dco_decode_category(dynamic raw); @@ -373,6 +377,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_tx_spend(dynamic raw); + @protected + List dco_decode_list_voting_encrypted_share( + dynamic raw); + + @protected + List dco_decode_list_voting_share_payload(dynamic raw); + + @protected + List + dco_decode_list_voting_signed_vote_commitment(dynamic raw); + @protected List dco_decode_list_zsa_holding(dynamic raw); @@ -559,6 +574,48 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 dco_decode_usize_array_4(dynamic raw); + @protected + VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( + dynamic raw); + + @protected + VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw); + + @protected + VotingDelegationSubmission dco_decode_voting_delegation_submission( + dynamic raw); + + @protected + VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); + + @protected + VotingPirLayout dco_decode_voting_pir_layout(dynamic raw); + + @protected + VotingPreparedInfo dco_decode_voting_prepared_info(dynamic raw); + + @protected + VotingSharePayload dco_decode_voting_share_payload(dynamic raw); + + @protected + VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( + dynamic raw); + + @protected + VotingVanWitness dco_decode_voting_van_witness(dynamic raw); + + @protected + VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw); + + @protected + VotingVoteConfirmation dco_decode_voting_vote_confirmation(dynamic raw); + + @protected + VotingVotePayloads dco_decode_voting_vote_payloads(dynamic raw); + + @protected + VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw); + @protected ZsaHolding dco_decode_zsa_holding(dynamic raw); @@ -738,6 +795,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int sse_decode_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( + SseDeserializer deserializer); + @protected Category sse_decode_category(SseDeserializer deserializer); @@ -890,6 +951,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_tx_spend(SseDeserializer deserializer); + @protected + List sse_decode_list_voting_encrypted_share( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_share_payload( + SseDeserializer deserializer); + + @protected + List + sse_decode_list_voting_signed_vote_commitment( + SseDeserializer deserializer); + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1081,6 +1155,56 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 sse_decode_usize_array_4(SseDeserializer deserializer); + @protected + VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( + SseDeserializer deserializer); + + @protected + VotingDelegationSetup sse_decode_voting_delegation_setup( + SseDeserializer deserializer); + + @protected + VotingDelegationSubmission sse_decode_voting_delegation_submission( + SseDeserializer deserializer); + + @protected + VotingEncryptedShare sse_decode_voting_encrypted_share( + SseDeserializer deserializer); + + @protected + VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer); + + @protected + VotingPreparedInfo sse_decode_voting_prepared_info( + SseDeserializer deserializer); + + @protected + VotingSharePayload sse_decode_voting_share_payload( + SseDeserializer deserializer); + + @protected + VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( + SseDeserializer deserializer); + + @protected + VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); + + @protected + VotingVoteCommitments sse_decode_voting_vote_commitments( + SseDeserializer deserializer); + + @protected + VotingVoteConfirmation sse_decode_voting_vote_confirmation( + SseDeserializer deserializer); + + @protected + VotingVotePayloads sse_decode_voting_vote_payloads( + SseDeserializer deserializer); + + @protected + VotingVoteSubmission sse_decode_voting_vote_submission( + SseDeserializer deserializer); + @protected ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @@ -1271,6 +1395,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_u_8(int self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer); + @protected void sse_encode_category(Category self, SseSerializer serializer); @@ -1436,6 +1564,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_encrypted_share( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_payload( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_signed_vote_commitment( + List self, SseSerializer serializer); + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer); @@ -1637,6 +1777,58 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_usize_array_4(UsizeArray4 self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_confirmation( + VotingDelegationConfirmation self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_setup( + VotingDelegationSetup self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_submission( + VotingDelegationSubmission self, SseSerializer serializer); + + @protected + void sse_encode_voting_encrypted_share( + VotingEncryptedShare self, SseSerializer serializer); + + @protected + void sse_encode_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer); + + @protected + void sse_encode_voting_prepared_info( + VotingPreparedInfo self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_payload( + VotingSharePayload self, SseSerializer serializer); + + @protected + void sse_encode_voting_signed_vote_commitment( + VotingSignedVoteCommitment self, SseSerializer serializer); + + @protected + void sse_encode_voting_van_witness( + VotingVanWitness self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_commitments( + VotingVoteCommitments self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_confirmation( + VotingVoteConfirmation self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_payloads( + VotingVotePayloads self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_submission( + VotingVoteSubmission self, SseSerializer serializer); + @protected void sse_encode_zsa_holding(ZsaHolding self, SseSerializer serializer); } diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 85135bd8a..316297029 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -26,6 +26,7 @@ import 'api/sweep.dart'; import 'api/sync.dart'; import 'api/transaction.dart'; import 'api/vault.dart'; +import 'api/voting.dart'; import 'api/zsa.dart'; import 'dart:async'; import 'dart:convert'; @@ -230,6 +231,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int dco_decode_box_autoadd_u_8(dynamic raw); + @protected + VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw); + @protected Category dco_decode_category(dynamic raw); @@ -375,6 +379,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_tx_spend(dynamic raw); + @protected + List dco_decode_list_voting_encrypted_share( + dynamic raw); + + @protected + List dco_decode_list_voting_share_payload(dynamic raw); + + @protected + List + dco_decode_list_voting_signed_vote_commitment(dynamic raw); + @protected List dco_decode_list_zsa_holding(dynamic raw); @@ -561,6 +576,48 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 dco_decode_usize_array_4(dynamic raw); + @protected + VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( + dynamic raw); + + @protected + VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw); + + @protected + VotingDelegationSubmission dco_decode_voting_delegation_submission( + dynamic raw); + + @protected + VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); + + @protected + VotingPirLayout dco_decode_voting_pir_layout(dynamic raw); + + @protected + VotingPreparedInfo dco_decode_voting_prepared_info(dynamic raw); + + @protected + VotingSharePayload dco_decode_voting_share_payload(dynamic raw); + + @protected + VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( + dynamic raw); + + @protected + VotingVanWitness dco_decode_voting_van_witness(dynamic raw); + + @protected + VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw); + + @protected + VotingVoteConfirmation dco_decode_voting_vote_confirmation(dynamic raw); + + @protected + VotingVotePayloads dco_decode_voting_vote_payloads(dynamic raw); + + @protected + VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw); + @protected ZsaHolding dco_decode_zsa_holding(dynamic raw); @@ -740,6 +797,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int sse_decode_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( + SseDeserializer deserializer); + @protected Category sse_decode_category(SseDeserializer deserializer); @@ -892,6 +953,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_tx_spend(SseDeserializer deserializer); + @protected + List sse_decode_list_voting_encrypted_share( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_share_payload( + SseDeserializer deserializer); + + @protected + List + sse_decode_list_voting_signed_vote_commitment( + SseDeserializer deserializer); + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1083,6 +1157,56 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 sse_decode_usize_array_4(SseDeserializer deserializer); + @protected + VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( + SseDeserializer deserializer); + + @protected + VotingDelegationSetup sse_decode_voting_delegation_setup( + SseDeserializer deserializer); + + @protected + VotingDelegationSubmission sse_decode_voting_delegation_submission( + SseDeserializer deserializer); + + @protected + VotingEncryptedShare sse_decode_voting_encrypted_share( + SseDeserializer deserializer); + + @protected + VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer); + + @protected + VotingPreparedInfo sse_decode_voting_prepared_info( + SseDeserializer deserializer); + + @protected + VotingSharePayload sse_decode_voting_share_payload( + SseDeserializer deserializer); + + @protected + VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( + SseDeserializer deserializer); + + @protected + VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); + + @protected + VotingVoteCommitments sse_decode_voting_vote_commitments( + SseDeserializer deserializer); + + @protected + VotingVoteConfirmation sse_decode_voting_vote_confirmation( + SseDeserializer deserializer); + + @protected + VotingVotePayloads sse_decode_voting_vote_payloads( + SseDeserializer deserializer); + + @protected + VotingVoteSubmission sse_decode_voting_vote_submission( + SseDeserializer deserializer); + @protected ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @@ -1273,6 +1397,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_u_8(int self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer); + @protected void sse_encode_category(Category self, SseSerializer serializer); @@ -1438,6 +1566,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_encrypted_share( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_payload( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_signed_vote_commitment( + List self, SseSerializer serializer); + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer); @@ -1639,6 +1779,58 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_usize_array_4(UsizeArray4 self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_confirmation( + VotingDelegationConfirmation self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_setup( + VotingDelegationSetup self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_submission( + VotingDelegationSubmission self, SseSerializer serializer); + + @protected + void sse_encode_voting_encrypted_share( + VotingEncryptedShare self, SseSerializer serializer); + + @protected + void sse_encode_voting_pir_layout( + VotingPirLayout self, SseSerializer serializer); + + @protected + void sse_encode_voting_prepared_info( + VotingPreparedInfo self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_payload( + VotingSharePayload self, SseSerializer serializer); + + @protected + void sse_encode_voting_signed_vote_commitment( + VotingSignedVoteCommitment self, SseSerializer serializer); + + @protected + void sse_encode_voting_van_witness( + VotingVanWitness self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_commitments( + VotingVoteCommitments self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_confirmation( + VotingVoteConfirmation self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_payloads( + VotingVotePayloads self, SseSerializer serializer); + + @protected + void sse_encode_voting_vote_submission( + VotingVoteSubmission self, SseSerializer serializer); + @protected void sse_encode_zsa_holding(ZsaHolding self, SseSerializer serializer); } diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index ff87e7ba0..02f94f519 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -24,7 +24,8 @@ mixin _$SyncState { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $SyncStateCopyWith get copyWith => _$SyncStateCopyWithImpl(this as SyncState, _$identity); + $SyncStateCopyWith get copyWith => + _$SyncStateCopyWithImpl(this as SyncState, _$identity); @override bool operator ==(Object other) { @@ -39,7 +40,8 @@ mixin _$SyncState { } @override - int get hashCode => Object.hash(runtimeType, start, end, height, time, const DeepCollectionEquality().hash(accounts)); + int get hashCode => Object.hash(runtimeType, start, end, height, time, + const DeepCollectionEquality().hash(accounts)); @override String toString() { @@ -49,7 +51,8 @@ mixin _$SyncState { /// @nodoc abstract mixin class $SyncStateCopyWith<$Res> { - factory $SyncStateCopyWith(SyncState value, $Res Function(SyncState) _then) = _$SyncStateCopyWithImpl; + factory $SyncStateCopyWith(SyncState value, $Res Function(SyncState) _then) = + _$SyncStateCopyWithImpl; @useResult $Res call({int start, int end, int height, int time, List accounts}); } @@ -188,13 +191,16 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult maybeWhen( - TResult Function(int start, int end, int height, int time, List accounts)? $default, { + TResult Function( + int start, int end, int height, int time, List accounts)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _SyncState() when $default != null: - return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default( + _that.start, _that.end, _that.height, _that.time, _that.accounts); case _: return orElse(); } @@ -215,12 +221,15 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult when( - TResult Function(int start, int end, int height, int time, List accounts) $default, + TResult Function( + int start, int end, int height, int time, List accounts) + $default, ) { final _that = this; switch (_that) { case _SyncState(): - return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default( + _that.start, _that.end, _that.height, _that.time, _that.accounts); } } @@ -238,12 +247,15 @@ extension SyncStatePatterns on SyncState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(int start, int end, int height, int time, List accounts)? $default, + TResult? Function( + int start, int end, int height, int time, List accounts)? + $default, ) { final _that = this; switch (_that) { case _SyncState() when $default != null: - return $default(_that.start, _that.end, _that.height, _that.time, _that.accounts); + return $default( + _that.start, _that.end, _that.height, _that.time, _that.accounts); case _: return null; } @@ -253,7 +265,13 @@ extension SyncStatePatterns on SyncState { /// @nodoc class _SyncState implements SyncState { - _SyncState({required this.start, required this.end, required this.height, required this.time, required final List accounts}) : _accounts = accounts; + _SyncState( + {required this.start, + required this.end, + required this.height, + required this.time, + required final List accounts}) + : _accounts = accounts; @override final int start; @@ -276,7 +294,8 @@ class _SyncState implements SyncState { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SyncStateCopyWith<_SyncState> get copyWith => __$SyncStateCopyWithImpl<_SyncState>(this, _$identity); + _$SyncStateCopyWith<_SyncState> get copyWith => + __$SyncStateCopyWithImpl<_SyncState>(this, _$identity); @override bool operator ==(Object other) { @@ -291,7 +310,8 @@ class _SyncState implements SyncState { } @override - int get hashCode => Object.hash(runtimeType, start, end, height, time, const DeepCollectionEquality().hash(_accounts)); + int get hashCode => Object.hash(runtimeType, start, end, height, time, + const DeepCollectionEquality().hash(_accounts)); @override String toString() { @@ -300,8 +320,11 @@ class _SyncState implements SyncState { } /// @nodoc -abstract mixin class _$SyncStateCopyWith<$Res> implements $SyncStateCopyWith<$Res> { - factory _$SyncStateCopyWith(_SyncState value, $Res Function(_SyncState) _then) = __$SyncStateCopyWithImpl; +abstract mixin class _$SyncStateCopyWith<$Res> + implements $SyncStateCopyWith<$Res> { + factory _$SyncStateCopyWith( + _SyncState value, $Res Function(_SyncState) _then) = + __$SyncStateCopyWithImpl; @override @useResult $Res call({int start, int end, int height, int time, List accounts}); @@ -363,7 +386,8 @@ mixin _$SyncProgressAccount { @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') $SyncProgressAccountCopyWith get copyWith => - _$SyncProgressAccountCopyWithImpl(this as SyncProgressAccount, _$identity); + _$SyncProgressAccountCopyWithImpl( + this as SyncProgressAccount, _$identity); @override bool operator ==(Object other) { @@ -378,7 +402,8 @@ mixin _$SyncProgressAccount { } @override - int get hashCode => Object.hash(runtimeType, account, start, end, height, time); + int get hashCode => + Object.hash(runtimeType, account, start, end, height, time); @override String toString() { @@ -388,7 +413,9 @@ mixin _$SyncProgressAccount { /// @nodoc abstract mixin class $SyncProgressAccountCopyWith<$Res> { - factory $SyncProgressAccountCopyWith(SyncProgressAccount value, $Res Function(SyncProgressAccount) _then) = _$SyncProgressAccountCopyWithImpl; + factory $SyncProgressAccountCopyWith( + SyncProgressAccount value, $Res Function(SyncProgressAccount) _then) = + _$SyncProgressAccountCopyWithImpl; @useResult $Res call({Account account, int start, int end, int height, int time}); @@ -396,7 +423,8 @@ abstract mixin class $SyncProgressAccountCopyWith<$Res> { } /// @nodoc -class _$SyncProgressAccountCopyWithImpl<$Res> implements $SyncProgressAccountCopyWith<$Res> { +class _$SyncProgressAccountCopyWithImpl<$Res> + implements $SyncProgressAccountCopyWith<$Res> { _$SyncProgressAccountCopyWithImpl(this._self, this._then); final SyncProgressAccount _self; @@ -539,13 +567,15 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult maybeWhen( - TResult Function(Account account, int start, int end, int height, int time)? $default, { + TResult Function(Account account, int start, int end, int height, int time)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _SyncProgressAccount() when $default != null: - return $default(_that.account, _that.start, _that.end, _that.height, _that.time); + return $default( + _that.account, _that.start, _that.end, _that.height, _that.time); case _: return orElse(); } @@ -566,12 +596,14 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult when( - TResult Function(Account account, int start, int end, int height, int time) $default, + TResult Function(Account account, int start, int end, int height, int time) + $default, ) { final _that = this; switch (_that) { case _SyncProgressAccount(): - return $default(_that.account, _that.start, _that.end, _that.height, _that.time); + return $default( + _that.account, _that.start, _that.end, _that.height, _that.time); } } @@ -589,12 +621,15 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Account account, int start, int end, int height, int time)? $default, + TResult? Function( + Account account, int start, int end, int height, int time)? + $default, ) { final _that = this; switch (_that) { case _SyncProgressAccount() when $default != null: - return $default(_that.account, _that.start, _that.end, _that.height, _that.time); + return $default( + _that.account, _that.start, _that.end, _that.height, _that.time); case _: return null; } @@ -604,7 +639,13 @@ extension SyncProgressAccountPatterns on SyncProgressAccount { /// @nodoc class _SyncProgressAccount extends SyncProgressAccount { - _SyncProgressAccount({required this.account, required this.start, required this.end, required this.height, required this.time}) : super._(); + _SyncProgressAccount( + {required this.account, + required this.start, + required this.end, + required this.height, + required this.time}) + : super._(); @override final Account account; @@ -622,7 +663,9 @@ class _SyncProgressAccount extends SyncProgressAccount { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$SyncProgressAccountCopyWith<_SyncProgressAccount> get copyWith => __$SyncProgressAccountCopyWithImpl<_SyncProgressAccount>(this, _$identity); + _$SyncProgressAccountCopyWith<_SyncProgressAccount> get copyWith => + __$SyncProgressAccountCopyWithImpl<_SyncProgressAccount>( + this, _$identity); @override bool operator ==(Object other) { @@ -637,7 +680,8 @@ class _SyncProgressAccount extends SyncProgressAccount { } @override - int get hashCode => Object.hash(runtimeType, account, start, end, height, time); + int get hashCode => + Object.hash(runtimeType, account, start, end, height, time); @override String toString() { @@ -646,8 +690,11 @@ class _SyncProgressAccount extends SyncProgressAccount { } /// @nodoc -abstract mixin class _$SyncProgressAccountCopyWith<$Res> implements $SyncProgressAccountCopyWith<$Res> { - factory _$SyncProgressAccountCopyWith(_SyncProgressAccount value, $Res Function(_SyncProgressAccount) _then) = __$SyncProgressAccountCopyWithImpl; +abstract mixin class _$SyncProgressAccountCopyWith<$Res> + implements $SyncProgressAccountCopyWith<$Res> { + factory _$SyncProgressAccountCopyWith(_SyncProgressAccount value, + $Res Function(_SyncProgressAccount) _then) = + __$SyncProgressAccountCopyWithImpl; @override @useResult $Res call({Account account, int start, int end, int height, int time}); @@ -657,7 +704,8 @@ abstract mixin class _$SyncProgressAccountCopyWith<$Res> implements $SyncProgres } /// @nodoc -class __$SyncProgressAccountCopyWithImpl<$Res> implements _$SyncProgressAccountCopyWith<$Res> { +class __$SyncProgressAccountCopyWithImpl<$Res> + implements _$SyncProgressAccountCopyWith<$Res> { __$SyncProgressAccountCopyWithImpl(this._self, this._then); final _SyncProgressAccount _self; @@ -724,7 +772,8 @@ mixin _$AccountData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountDataCopyWith get copyWith => _$AccountDataCopyWithImpl(this as AccountData, _$identity); + $AccountDataCopyWith get copyWith => + _$AccountDataCopyWithImpl(this as AccountData, _$identity); @override bool operator ==(Object other) { @@ -734,16 +783,26 @@ mixin _$AccountData { (identical(other.account, account) || other.account == account) && (identical(other.pool, pool) || other.pool == pool) && (identical(other.balance, balance) || other.balance == balance) && - const DeepCollectionEquality().equals(other.transactions, transactions) && + const DeepCollectionEquality() + .equals(other.transactions, transactions) && const DeepCollectionEquality().equals(other.memos, memos) && const DeepCollectionEquality().equals(other.notes, notes) && const DeepCollectionEquality().equals(other.zsas, zsas) && - (identical(other.frostParams, frostParams) || other.frostParams == frostParams)); + (identical(other.frostParams, frostParams) || + other.frostParams == frostParams)); } @override - int get hashCode => Object.hash(runtimeType, account, pool, balance, const DeepCollectionEquality().hash(transactions), - const DeepCollectionEquality().hash(memos), const DeepCollectionEquality().hash(notes), const DeepCollectionEquality().hash(zsas), frostParams); + int get hashCode => Object.hash( + runtimeType, + account, + pool, + balance, + const DeepCollectionEquality().hash(transactions), + const DeepCollectionEquality().hash(memos), + const DeepCollectionEquality().hash(notes), + const DeepCollectionEquality().hash(zsas), + frostParams); @override String toString() { @@ -753,7 +812,9 @@ mixin _$AccountData { /// @nodoc abstract mixin class $AccountDataCopyWith<$Res> { - factory $AccountDataCopyWith(AccountData value, $Res Function(AccountData) _then) = _$AccountDataCopyWithImpl; + factory $AccountDataCopyWith( + AccountData value, $Res Function(AccountData) _then) = + _$AccountDataCopyWithImpl; @useResult $Res call( {Account account, @@ -942,7 +1003,14 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult maybeWhen( - TResult Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, + TResult Function( + Account account, + int pool, + PoolBalance balance, + List transactions, + List memos, + List notes, + List zsas, FrostParams? frostParams)? $default, { required TResult orElse(), @@ -950,7 +1018,15 @@ extension AccountDataPatterns on AccountData { final _that = this; switch (_that) { case _AccountData() when $default != null: - return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); + return $default( + _that.account, + _that.pool, + _that.balance, + _that.transactions, + _that.memos, + _that.notes, + _that.zsas, + _that.frostParams); case _: return orElse(); } @@ -971,14 +1047,29 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult when( - TResult Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, + TResult Function( + Account account, + int pool, + PoolBalance balance, + List transactions, + List memos, + List notes, + List zsas, FrostParams? frostParams) $default, ) { final _that = this; switch (_that) { case _AccountData(): - return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); + return $default( + _that.account, + _that.pool, + _that.balance, + _that.transactions, + _that.memos, + _that.notes, + _that.zsas, + _that.frostParams); } } @@ -996,14 +1087,29 @@ extension AccountDataPatterns on AccountData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Account account, int pool, PoolBalance balance, List transactions, List memos, List notes, List zsas, + TResult? Function( + Account account, + int pool, + PoolBalance balance, + List transactions, + List memos, + List notes, + List zsas, FrostParams? frostParams)? $default, ) { final _that = this; switch (_that) { case _AccountData() when $default != null: - return $default(_that.account, _that.pool, _that.balance, _that.transactions, _that.memos, _that.notes, _that.zsas, _that.frostParams); + return $default( + _that.account, + _that.pool, + _that.balance, + _that.transactions, + _that.memos, + _that.notes, + _that.zsas, + _that.frostParams); case _: return null; } @@ -1073,7 +1179,8 @@ class _AccountData implements AccountData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountDataCopyWith<_AccountData> get copyWith => __$AccountDataCopyWithImpl<_AccountData>(this, _$identity); + _$AccountDataCopyWith<_AccountData> get copyWith => + __$AccountDataCopyWithImpl<_AccountData>(this, _$identity); @override bool operator ==(Object other) { @@ -1083,16 +1190,26 @@ class _AccountData implements AccountData { (identical(other.account, account) || other.account == account) && (identical(other.pool, pool) || other.pool == pool) && (identical(other.balance, balance) || other.balance == balance) && - const DeepCollectionEquality().equals(other._transactions, _transactions) && + const DeepCollectionEquality() + .equals(other._transactions, _transactions) && const DeepCollectionEquality().equals(other._memos, _memos) && const DeepCollectionEquality().equals(other._notes, _notes) && const DeepCollectionEquality().equals(other._zsas, _zsas) && - (identical(other.frostParams, frostParams) || other.frostParams == frostParams)); + (identical(other.frostParams, frostParams) || + other.frostParams == frostParams)); } @override - int get hashCode => Object.hash(runtimeType, account, pool, balance, const DeepCollectionEquality().hash(_transactions), - const DeepCollectionEquality().hash(_memos), const DeepCollectionEquality().hash(_notes), const DeepCollectionEquality().hash(_zsas), frostParams); + int get hashCode => Object.hash( + runtimeType, + account, + pool, + balance, + const DeepCollectionEquality().hash(_transactions), + const DeepCollectionEquality().hash(_memos), + const DeepCollectionEquality().hash(_notes), + const DeepCollectionEquality().hash(_zsas), + frostParams); @override String toString() { @@ -1101,8 +1218,11 @@ class _AccountData implements AccountData { } /// @nodoc -abstract mixin class _$AccountDataCopyWith<$Res> implements $AccountDataCopyWith<$Res> { - factory _$AccountDataCopyWith(_AccountData value, $Res Function(_AccountData) _then) = __$AccountDataCopyWithImpl; +abstract mixin class _$AccountDataCopyWith<$Res> + implements $AccountDataCopyWith<$Res> { + factory _$AccountDataCopyWith( + _AccountData value, $Res Function(_AccountData) _then) = + __$AccountDataCopyWithImpl; @override @useResult $Res call( @@ -1232,7 +1352,8 @@ mixin _$AppSettings { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AppSettingsCopyWith get copyWith => _$AppSettingsCopyWithImpl(this as AppSettings, _$identity); + $AppSettingsCopyWith get copyWith => + _$AppSettingsCopyWithImpl(this as AppSettings, _$identity); @override bool operator ==(Object other) { @@ -1241,26 +1362,39 @@ mixin _$AppSettings { other is AppSettings && (identical(other.dbName, dbName) || other.dbName == dbName) && (identical(other.net, net) || other.net == net) && - (identical(other.isLightNode, isLightNode) || other.isLightNode == isLightNode) && + (identical(other.isLightNode, isLightNode) || + other.isLightNode == isLightNode) && (identical(other.lwd, lwd) || other.lwd == lwd) && - (identical(other.blockExplorer, blockExplorer) || other.blockExplorer == blockExplorer) && - (identical(other.syncInterval, syncInterval) || other.syncInterval == syncInterval) && - (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && + (identical(other.blockExplorer, blockExplorer) || + other.blockExplorer == blockExplorer) && + (identical(other.syncInterval, syncInterval) || + other.syncInterval == syncInterval) && + (identical(other.actionsPerSync, actionsPerSync) || + other.actionsPerSync == actionsPerSync) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy) && - (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && - (identical(other.recovery, recovery) || other.recovery == recovery) && + (identical(other.coingecko, coingecko) || + other.coingecko == coingecko) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && (identical(other.needPin, needPin) || other.needPin == needPin) && - (identical(other.pinUnlockedAt, pinUnlockedAt) || other.pinUnlockedAt == pinUnlockedAt) && + (identical(other.pinUnlockedAt, pinUnlockedAt) || + other.pinUnlockedAt == pinUnlockedAt) && (identical(other.offline, offline) || other.offline == offline) && (identical(other.getFx, getFx) || other.getFx == getFx) && - (identical(other.qrSettings, qrSettings) || other.qrSettings == qrSettings) && + (identical(other.qrSettings, qrSettings) || + other.qrSettings == qrSettings) && (identical(other.vault, vault) || other.vault == vault) && - (identical(other.expertMode, expertMode) || other.expertMode == expertMode) && - (identical(other.paletteName, paletteName) || other.paletteName == paletteName) && - (identical(other.darkMode, darkMode) || other.darkMode == darkMode) && - (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && - (identical(other.currency, currency) || other.currency == currency)); + (identical(other.expertMode, expertMode) || + other.expertMode == expertMode) && + (identical(other.paletteName, paletteName) || + other.paletteName == paletteName) && + (identical(other.darkMode, darkMode) || + other.darkMode == darkMode) && + (identical(other.transactionTableMode, transactionTableMode) || + other.transactionTableMode == transactionTableMode) && + (identical(other.currency, currency) || + other.currency == currency)); } @override @@ -1298,7 +1432,9 @@ mixin _$AppSettings { /// @nodoc abstract mixin class $AppSettingsCopyWith<$Res> { - factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl; + factory $AppSettingsCopyWith( + AppSettings value, $Res Function(AppSettings) _then) = + _$AppSettingsCopyWithImpl; @useResult $Res call( {String dbName, @@ -1831,7 +1967,8 @@ class _AppSettings implements AppSettings { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_AppSettings>(this, _$identity); + _$AppSettingsCopyWith<_AppSettings> get copyWith => + __$AppSettingsCopyWithImpl<_AppSettings>(this, _$identity); @override bool operator ==(Object other) { @@ -1840,26 +1977,39 @@ class _AppSettings implements AppSettings { other is _AppSettings && (identical(other.dbName, dbName) || other.dbName == dbName) && (identical(other.net, net) || other.net == net) && - (identical(other.isLightNode, isLightNode) || other.isLightNode == isLightNode) && + (identical(other.isLightNode, isLightNode) || + other.isLightNode == isLightNode) && (identical(other.lwd, lwd) || other.lwd == lwd) && - (identical(other.blockExplorer, blockExplorer) || other.blockExplorer == blockExplorer) && - (identical(other.syncInterval, syncInterval) || other.syncInterval == syncInterval) && - (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && + (identical(other.blockExplorer, blockExplorer) || + other.blockExplorer == blockExplorer) && + (identical(other.syncInterval, syncInterval) || + other.syncInterval == syncInterval) && + (identical(other.actionsPerSync, actionsPerSync) || + other.actionsPerSync == actionsPerSync) && (identical(other.useTor, useTor) || other.useTor == useTor) && (identical(other.proxy, proxy) || other.proxy == proxy) && - (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && - (identical(other.recovery, recovery) || other.recovery == recovery) && + (identical(other.coingecko, coingecko) || + other.coingecko == coingecko) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && (identical(other.needPin, needPin) || other.needPin == needPin) && - (identical(other.pinUnlockedAt, pinUnlockedAt) || other.pinUnlockedAt == pinUnlockedAt) && + (identical(other.pinUnlockedAt, pinUnlockedAt) || + other.pinUnlockedAt == pinUnlockedAt) && (identical(other.offline, offline) || other.offline == offline) && (identical(other.getFx, getFx) || other.getFx == getFx) && - (identical(other.qrSettings, qrSettings) || other.qrSettings == qrSettings) && + (identical(other.qrSettings, qrSettings) || + other.qrSettings == qrSettings) && (identical(other.vault, vault) || other.vault == vault) && - (identical(other.expertMode, expertMode) || other.expertMode == expertMode) && - (identical(other.paletteName, paletteName) || other.paletteName == paletteName) && - (identical(other.darkMode, darkMode) || other.darkMode == darkMode) && - (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && - (identical(other.currency, currency) || other.currency == currency)); + (identical(other.expertMode, expertMode) || + other.expertMode == expertMode) && + (identical(other.paletteName, paletteName) || + other.paletteName == paletteName) && + (identical(other.darkMode, darkMode) || + other.darkMode == darkMode) && + (identical(other.transactionTableMode, transactionTableMode) || + other.transactionTableMode == transactionTableMode) && + (identical(other.currency, currency) || + other.currency == currency)); } @override @@ -1896,8 +2046,11 @@ class _AppSettings implements AppSettings { } /// @nodoc -abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith<$Res> { - factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl; +abstract mixin class _$AppSettingsCopyWith<$Res> + implements $AppSettingsCopyWith<$Res> { + factory _$AppSettingsCopyWith( + _AppSettings value, $Res Function(_AppSettings) _then) = + __$AppSettingsCopyWithImpl; @override @useResult $Res call( @@ -2076,7 +2229,9 @@ mixin _$MempoolState { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $MempoolStateCopyWith get copyWith => _$MempoolStateCopyWithImpl(this as MempoolState, _$identity); + $MempoolStateCopyWith get copyWith => + _$MempoolStateCopyWithImpl( + this as MempoolState, _$identity); @override bool operator ==(Object other) { @@ -2084,13 +2239,18 @@ mixin _$MempoolState { (other.runtimeType == runtimeType && other is MempoolState && (identical(other.running, running) || other.running == running) && - const DeepCollectionEquality().equals(other.unconfirmedFunds, unconfirmedFunds) && - const DeepCollectionEquality().equals(other.unconfirmedTx, unconfirmedTx)); + const DeepCollectionEquality() + .equals(other.unconfirmedFunds, unconfirmedFunds) && + const DeepCollectionEquality() + .equals(other.unconfirmedTx, unconfirmedTx)); } @override - int get hashCode => - Object.hash(runtimeType, running, const DeepCollectionEquality().hash(unconfirmedFunds), const DeepCollectionEquality().hash(unconfirmedTx)); + int get hashCode => Object.hash( + runtimeType, + running, + const DeepCollectionEquality().hash(unconfirmedFunds), + const DeepCollectionEquality().hash(unconfirmedTx)); @override String toString() { @@ -2100,9 +2260,14 @@ mixin _$MempoolState { /// @nodoc abstract mixin class $MempoolStateCopyWith<$Res> { - factory $MempoolStateCopyWith(MempoolState value, $Res Function(MempoolState) _then) = _$MempoolStateCopyWithImpl; + factory $MempoolStateCopyWith( + MempoolState value, $Res Function(MempoolState) _then) = + _$MempoolStateCopyWithImpl; @useResult - $Res call({bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx}); + $Res call( + {bool running, + Map unconfirmedFunds, + List<(String, String, int)> unconfirmedTx}); } /// @nodoc @@ -2229,13 +2394,16 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult maybeWhen( - TResult Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx)? $default, { + TResult Function(bool running, Map unconfirmedFunds, + List<(String, String, int)> unconfirmedTx)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _MempoolState() when $default != null: - return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default( + _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); case _: return orElse(); } @@ -2256,12 +2424,15 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult when( - TResult Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx) $default, + TResult Function(bool running, Map unconfirmedFunds, + List<(String, String, int)> unconfirmedTx) + $default, ) { final _that = this; switch (_that) { case _MempoolState(): - return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default( + _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); } } @@ -2279,12 +2450,15 @@ extension MempoolStatePatterns on MempoolState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx)? $default, + TResult? Function(bool running, Map unconfirmedFunds, + List<(String, String, int)> unconfirmedTx)? + $default, ) { final _that = this; switch (_that) { case _MempoolState() when $default != null: - return $default(_that.running, _that.unconfirmedFunds, _that.unconfirmedTx); + return $default( + _that.running, _that.unconfirmedFunds, _that.unconfirmedTx); case _: return null; } @@ -2294,7 +2468,10 @@ extension MempoolStatePatterns on MempoolState { /// @nodoc class _MempoolState implements MempoolState { - _MempoolState({required this.running, required this.unconfirmedFunds, required this.unconfirmedTx}); + _MempoolState( + {required this.running, + required this.unconfirmedFunds, + required this.unconfirmedTx}); @override final bool running; @@ -2308,7 +2485,8 @@ class _MempoolState implements MempoolState { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$MempoolStateCopyWith<_MempoolState> get copyWith => __$MempoolStateCopyWithImpl<_MempoolState>(this, _$identity); + _$MempoolStateCopyWith<_MempoolState> get copyWith => + __$MempoolStateCopyWithImpl<_MempoolState>(this, _$identity); @override bool operator ==(Object other) { @@ -2316,13 +2494,18 @@ class _MempoolState implements MempoolState { (other.runtimeType == runtimeType && other is _MempoolState && (identical(other.running, running) || other.running == running) && - const DeepCollectionEquality().equals(other.unconfirmedFunds, unconfirmedFunds) && - const DeepCollectionEquality().equals(other.unconfirmedTx, unconfirmedTx)); + const DeepCollectionEquality() + .equals(other.unconfirmedFunds, unconfirmedFunds) && + const DeepCollectionEquality() + .equals(other.unconfirmedTx, unconfirmedTx)); } @override - int get hashCode => - Object.hash(runtimeType, running, const DeepCollectionEquality().hash(unconfirmedFunds), const DeepCollectionEquality().hash(unconfirmedTx)); + int get hashCode => Object.hash( + runtimeType, + running, + const DeepCollectionEquality().hash(unconfirmedFunds), + const DeepCollectionEquality().hash(unconfirmedTx)); @override String toString() { @@ -2331,15 +2514,22 @@ class _MempoolState implements MempoolState { } /// @nodoc -abstract mixin class _$MempoolStateCopyWith<$Res> implements $MempoolStateCopyWith<$Res> { - factory _$MempoolStateCopyWith(_MempoolState value, $Res Function(_MempoolState) _then) = __$MempoolStateCopyWithImpl; +abstract mixin class _$MempoolStateCopyWith<$Res> + implements $MempoolStateCopyWith<$Res> { + factory _$MempoolStateCopyWith( + _MempoolState value, $Res Function(_MempoolState) _then) = + __$MempoolStateCopyWithImpl; @override @useResult - $Res call({bool running, Map unconfirmedFunds, List<(String, String, int)> unconfirmedTx}); + $Res call( + {bool running, + Map unconfirmedFunds, + List<(String, String, int)> unconfirmedTx}); } /// @nodoc -class __$MempoolStateCopyWithImpl<$Res> implements _$MempoolStateCopyWith<$Res> { +class __$MempoolStateCopyWithImpl<$Res> + implements _$MempoolStateCopyWith<$Res> { __$MempoolStateCopyWithImpl(this._self, this._then); final _MempoolState _self; @@ -2382,21 +2572,26 @@ mixin _$AccountsPageData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountsPageDataCopyWith get copyWith => _$AccountsPageDataCopyWithImpl(this as AccountsPageData, _$identity); + $AccountsPageDataCopyWith get copyWith => + _$AccountsPageDataCopyWithImpl( + this as AccountsPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is AccountsPageData && - (identical(other.settings, settings) || other.settings == settings) && + (identical(other.settings, settings) || + other.settings == settings) && const DeepCollectionEquality().equals(other.accounts, accounts) && (identical(other.price, price) || other.price == price) && - (identical(other.selectedFolder, selectedFolder) || other.selectedFolder == selectedFolder)); + (identical(other.selectedFolder, selectedFolder) || + other.selectedFolder == selectedFolder)); } @override - int get hashCode => Object.hash(runtimeType, settings, const DeepCollectionEquality().hash(accounts), price, selectedFolder); + int get hashCode => Object.hash(runtimeType, settings, + const DeepCollectionEquality().hash(accounts), price, selectedFolder); @override String toString() { @@ -2406,16 +2601,23 @@ mixin _$AccountsPageData { /// @nodoc abstract mixin class $AccountsPageDataCopyWith<$Res> { - factory $AccountsPageDataCopyWith(AccountsPageData value, $Res Function(AccountsPageData) _then) = _$AccountsPageDataCopyWithImpl; + factory $AccountsPageDataCopyWith( + AccountsPageData value, $Res Function(AccountsPageData) _then) = + _$AccountsPageDataCopyWithImpl; @useResult - $Res call({AppSettings settings, List accounts, double? price, Folder? selectedFolder}); + $Res call( + {AppSettings settings, + List accounts, + double? price, + Folder? selectedFolder}); $AppSettingsCopyWith<$Res> get settings; $FolderCopyWith<$Res>? get selectedFolder; } /// @nodoc -class _$AccountsPageDataCopyWithImpl<$Res> implements $AccountsPageDataCopyWith<$Res> { +class _$AccountsPageDataCopyWithImpl<$Res> + implements $AccountsPageDataCopyWith<$Res> { _$AccountsPageDataCopyWithImpl(this._self, this._then); final AccountsPageData _self; @@ -2567,13 +2769,16 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder)? $default, { + TResult Function(AppSettings settings, List accounts, + double? price, Folder? selectedFolder)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountsPageData() when $default != null: - return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default( + _that.settings, _that.accounts, _that.price, _that.selectedFolder); case _: return orElse(); } @@ -2594,12 +2799,15 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult when( - TResult Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder) $default, + TResult Function(AppSettings settings, List accounts, + double? price, Folder? selectedFolder) + $default, ) { final _that = this; switch (_that) { case _AccountsPageData(): - return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default( + _that.settings, _that.accounts, _that.price, _that.selectedFolder); } } @@ -2617,12 +2825,15 @@ extension AccountsPageDataPatterns on AccountsPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(AppSettings settings, List accounts, double? price, Folder? selectedFolder)? $default, + TResult? Function(AppSettings settings, List accounts, + double? price, Folder? selectedFolder)? + $default, ) { final _that = this; switch (_that) { case _AccountsPageData() when $default != null: - return $default(_that.settings, _that.accounts, _that.price, _that.selectedFolder); + return $default( + _that.settings, _that.accounts, _that.price, _that.selectedFolder); case _: return null; } @@ -2632,7 +2843,11 @@ extension AccountsPageDataPatterns on AccountsPageData { /// @nodoc class _AccountsPageData implements AccountsPageData { - const _AccountsPageData({required this.settings, required final List accounts, required this.price, required this.selectedFolder}) + const _AccountsPageData( + {required this.settings, + required final List accounts, + required this.price, + required this.selectedFolder}) : _accounts = accounts; @override @@ -2655,21 +2870,25 @@ class _AccountsPageData implements AccountsPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountsPageDataCopyWith<_AccountsPageData> get copyWith => __$AccountsPageDataCopyWithImpl<_AccountsPageData>(this, _$identity); + _$AccountsPageDataCopyWith<_AccountsPageData> get copyWith => + __$AccountsPageDataCopyWithImpl<_AccountsPageData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _AccountsPageData && - (identical(other.settings, settings) || other.settings == settings) && + (identical(other.settings, settings) || + other.settings == settings) && const DeepCollectionEquality().equals(other._accounts, _accounts) && (identical(other.price, price) || other.price == price) && - (identical(other.selectedFolder, selectedFolder) || other.selectedFolder == selectedFolder)); + (identical(other.selectedFolder, selectedFolder) || + other.selectedFolder == selectedFolder)); } @override - int get hashCode => Object.hash(runtimeType, settings, const DeepCollectionEquality().hash(_accounts), price, selectedFolder); + int get hashCode => Object.hash(runtimeType, settings, + const DeepCollectionEquality().hash(_accounts), price, selectedFolder); @override String toString() { @@ -2678,11 +2897,18 @@ class _AccountsPageData implements AccountsPageData { } /// @nodoc -abstract mixin class _$AccountsPageDataCopyWith<$Res> implements $AccountsPageDataCopyWith<$Res> { - factory _$AccountsPageDataCopyWith(_AccountsPageData value, $Res Function(_AccountsPageData) _then) = __$AccountsPageDataCopyWithImpl; +abstract mixin class _$AccountsPageDataCopyWith<$Res> + implements $AccountsPageDataCopyWith<$Res> { + factory _$AccountsPageDataCopyWith( + _AccountsPageData value, $Res Function(_AccountsPageData) _then) = + __$AccountsPageDataCopyWithImpl; @override @useResult - $Res call({AppSettings settings, List accounts, double? price, Folder? selectedFolder}); + $Res call( + {AppSettings settings, + List accounts, + double? price, + Folder? selectedFolder}); @override $AppSettingsCopyWith<$Res> get settings; @@ -2691,7 +2917,8 @@ abstract mixin class _$AccountsPageDataCopyWith<$Res> implements $AccountsPageDa } /// @nodoc -class __$AccountsPageDataCopyWithImpl<$Res> implements _$AccountsPageDataCopyWith<$Res> { +class __$AccountsPageDataCopyWithImpl<$Res> + implements _$AccountsPageDataCopyWith<$Res> { __$AccountsPageDataCopyWithImpl(this._self, this._then); final _AccountsPageData _self; @@ -2761,19 +2988,24 @@ mixin _$BasicAccountData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $BasicAccountDataCopyWith get copyWith => _$BasicAccountDataCopyWithImpl(this as BasicAccountData, _$identity); + $BasicAccountDataCopyWith get copyWith => + _$BasicAccountDataCopyWithImpl( + this as BasicAccountData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is BasicAccountData && - const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount)); + const DeepCollectionEquality() + .equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount); + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(allAccounts), currentAccount); @override String toString() { @@ -2783,7 +3015,9 @@ mixin _$BasicAccountData { /// @nodoc abstract mixin class $BasicAccountDataCopyWith<$Res> { - factory $BasicAccountDataCopyWith(BasicAccountData value, $Res Function(BasicAccountData) _then) = _$BasicAccountDataCopyWithImpl; + factory $BasicAccountDataCopyWith( + BasicAccountData value, $Res Function(BasicAccountData) _then) = + _$BasicAccountDataCopyWithImpl; @useResult $Res call({List allAccounts, AccountData? currentAccount}); @@ -2791,7 +3025,8 @@ abstract mixin class $BasicAccountDataCopyWith<$Res> { } /// @nodoc -class _$BasicAccountDataCopyWithImpl<$Res> implements $BasicAccountDataCopyWith<$Res> { +class _$BasicAccountDataCopyWithImpl<$Res> + implements $BasicAccountDataCopyWith<$Res> { _$BasicAccountDataCopyWithImpl(this._self, this._then); final BasicAccountData _self; @@ -2923,7 +3158,8 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult maybeWhen( - TResult Function(List allAccounts, AccountData? currentAccount)? $default, { + TResult Function(List allAccounts, AccountData? currentAccount)? + $default, { required TResult orElse(), }) { final _that = this; @@ -2950,7 +3186,8 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount) $default, + TResult Function(List allAccounts, AccountData? currentAccount) + $default, ) { final _that = this; switch (_that) { @@ -2973,7 +3210,8 @@ extension BasicAccountDataPatterns on BasicAccountData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(List allAccounts, AccountData? currentAccount)? $default, + TResult? Function(List allAccounts, AccountData? currentAccount)? + $default, ) { final _that = this; switch (_that) { @@ -2988,7 +3226,9 @@ extension BasicAccountDataPatterns on BasicAccountData { /// @nodoc class _BasicAccountData implements BasicAccountData { - const _BasicAccountData({required final List allAccounts, required this.currentAccount}) : _allAccounts = allAccounts; + const _BasicAccountData( + {required final List allAccounts, required this.currentAccount}) + : _allAccounts = allAccounts; final List _allAccounts; @override @@ -3006,19 +3246,23 @@ class _BasicAccountData implements BasicAccountData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$BasicAccountDataCopyWith<_BasicAccountData> get copyWith => __$BasicAccountDataCopyWithImpl<_BasicAccountData>(this, _$identity); + _$BasicAccountDataCopyWith<_BasicAccountData> get copyWith => + __$BasicAccountDataCopyWithImpl<_BasicAccountData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _BasicAccountData && - const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount)); + const DeepCollectionEquality() + .equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount); + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_allAccounts), currentAccount); @override String toString() { @@ -3027,8 +3271,11 @@ class _BasicAccountData implements BasicAccountData { } /// @nodoc -abstract mixin class _$BasicAccountDataCopyWith<$Res> implements $BasicAccountDataCopyWith<$Res> { - factory _$BasicAccountDataCopyWith(_BasicAccountData value, $Res Function(_BasicAccountData) _then) = __$BasicAccountDataCopyWithImpl; +abstract mixin class _$BasicAccountDataCopyWith<$Res> + implements $BasicAccountDataCopyWith<$Res> { + factory _$BasicAccountDataCopyWith( + _BasicAccountData value, $Res Function(_BasicAccountData) _then) = + __$BasicAccountDataCopyWithImpl; @override @useResult $Res call({List allAccounts, AccountData? currentAccount}); @@ -3038,7 +3285,8 @@ abstract mixin class _$BasicAccountDataCopyWith<$Res> implements $BasicAccountDa } /// @nodoc -class __$BasicAccountDataCopyWithImpl<$Res> implements _$BasicAccountDataCopyWith<$Res> { +class __$BasicAccountDataCopyWithImpl<$Res> + implements _$BasicAccountDataCopyWith<$Res> { __$BasicAccountDataCopyWithImpl(this._self, this._then); final _BasicAccountData _self; @@ -3089,20 +3337,29 @@ mixin _$AccountPageData { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $AccountPageDataCopyWith get copyWith => _$AccountPageDataCopyWithImpl(this as AccountPageData, _$identity); + $AccountPageDataCopyWith get copyWith => + _$AccountPageDataCopyWithImpl( + this as AccountPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is AccountPageData && - const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || other.syncState == syncState)); + const DeepCollectionEquality() + .equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || + other.syncState == syncState)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount, syncState); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(allAccounts), + currentAccount, + syncState); @override String toString() { @@ -3112,16 +3369,22 @@ mixin _$AccountPageData { /// @nodoc abstract mixin class $AccountPageDataCopyWith<$Res> { - factory $AccountPageDataCopyWith(AccountPageData value, $Res Function(AccountPageData) _then) = _$AccountPageDataCopyWithImpl; + factory $AccountPageDataCopyWith( + AccountPageData value, $Res Function(AccountPageData) _then) = + _$AccountPageDataCopyWithImpl; @useResult - $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState}); + $Res call( + {List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState}); $AccountDataCopyWith<$Res>? get currentAccount; $SyncProgressAccountCopyWith<$Res>? get syncState; } /// @nodoc -class _$AccountPageDataCopyWithImpl<$Res> implements $AccountPageDataCopyWith<$Res> { +class _$AccountPageDataCopyWithImpl<$Res> + implements $AccountPageDataCopyWith<$Res> { _$AccountPageDataCopyWithImpl(this._self, this._then); final AccountPageData _self; @@ -3272,13 +3535,16 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState)? $default, { + TResult Function(List allAccounts, AccountData? currentAccount, + SyncProgressAccount? syncState)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _AccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, _that.syncState); + return $default( + _that.allAccounts, _that.currentAccount, _that.syncState); case _: return orElse(); } @@ -3299,12 +3565,15 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState) $default, + TResult Function(List allAccounts, AccountData? currentAccount, + SyncProgressAccount? syncState) + $default, ) { final _that = this; switch (_that) { case _AccountPageData(): - return $default(_that.allAccounts, _that.currentAccount, _that.syncState); + return $default( + _that.allAccounts, _that.currentAccount, _that.syncState); } } @@ -3322,12 +3591,15 @@ extension AccountPageDataPatterns on AccountPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState)? $default, + TResult? Function(List allAccounts, AccountData? currentAccount, + SyncProgressAccount? syncState)? + $default, ) { final _that = this; switch (_that) { case _AccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, _that.syncState); + return $default( + _that.allAccounts, _that.currentAccount, _that.syncState); case _: return null; } @@ -3337,7 +3609,11 @@ extension AccountPageDataPatterns on AccountPageData { /// @nodoc class _AccountPageData implements AccountPageData { - const _AccountPageData({required final List allAccounts, required this.currentAccount, required this.syncState}) : _allAccounts = allAccounts; + const _AccountPageData( + {required final List allAccounts, + required this.currentAccount, + required this.syncState}) + : _allAccounts = allAccounts; final List _allAccounts; @override @@ -3357,20 +3633,28 @@ class _AccountPageData implements AccountPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$AccountPageDataCopyWith<_AccountPageData> get copyWith => __$AccountPageDataCopyWithImpl<_AccountPageData>(this, _$identity); + _$AccountPageDataCopyWith<_AccountPageData> get copyWith => + __$AccountPageDataCopyWithImpl<_AccountPageData>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _AccountPageData && - const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || other.syncState == syncState)); + const DeepCollectionEquality() + .equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || + other.syncState == syncState)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount, syncState); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_allAccounts), + currentAccount, + syncState); @override String toString() { @@ -3379,11 +3663,17 @@ class _AccountPageData implements AccountPageData { } /// @nodoc -abstract mixin class _$AccountPageDataCopyWith<$Res> implements $AccountPageDataCopyWith<$Res> { - factory _$AccountPageDataCopyWith(_AccountPageData value, $Res Function(_AccountPageData) _then) = __$AccountPageDataCopyWithImpl; +abstract mixin class _$AccountPageDataCopyWith<$Res> + implements $AccountPageDataCopyWith<$Res> { + factory _$AccountPageDataCopyWith( + _AccountPageData value, $Res Function(_AccountPageData) _then) = + __$AccountPageDataCopyWithImpl; @override @useResult - $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState}); + $Res call( + {List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState}); @override $AccountDataCopyWith<$Res>? get currentAccount; @@ -3392,7 +3682,8 @@ abstract mixin class _$AccountPageDataCopyWith<$Res> implements $AccountPageData } /// @nodoc -class __$AccountPageDataCopyWithImpl<$Res> implements _$AccountPageDataCopyWith<$Res> { +class __$AccountPageDataCopyWithImpl<$Res> + implements _$AccountPageDataCopyWith<$Res> { __$AccountPageDataCopyWithImpl(this._self, this._then); final _AccountPageData _self; @@ -3465,22 +3756,32 @@ mixin _$FullAccountPageData { @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') $FullAccountPageDataCopyWith get copyWith => - _$FullAccountPageDataCopyWithImpl(this as FullAccountPageData, _$identity); + _$FullAccountPageDataCopyWithImpl( + this as FullAccountPageData, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is FullAccountPageData && - const DeepCollectionEquality().equals(other.allAccounts, allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || other.syncState == syncState) && + const DeepCollectionEquality() + .equals(other.allAccounts, allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || + other.syncState == syncState) && (identical(other.price, price) || other.price == price) && (identical(other.mempool, mempool) || other.mempool == mempool)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(allAccounts), currentAccount, syncState, price, mempool); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(allAccounts), + currentAccount, + syncState, + price, + mempool); @override String toString() { @@ -3490,9 +3791,16 @@ mixin _$FullAccountPageData { /// @nodoc abstract mixin class $FullAccountPageDataCopyWith<$Res> { - factory $FullAccountPageDataCopyWith(FullAccountPageData value, $Res Function(FullAccountPageData) _then) = _$FullAccountPageDataCopyWithImpl; + factory $FullAccountPageDataCopyWith( + FullAccountPageData value, $Res Function(FullAccountPageData) _then) = + _$FullAccountPageDataCopyWithImpl; @useResult - $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool}); + $Res call( + {List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState, + double? price, + MempoolState mempool}); $AccountDataCopyWith<$Res>? get currentAccount; $SyncProgressAccountCopyWith<$Res>? get syncState; @@ -3500,7 +3808,8 @@ abstract mixin class $FullAccountPageDataCopyWith<$Res> { } /// @nodoc -class _$FullAccountPageDataCopyWithImpl<$Res> implements $FullAccountPageDataCopyWith<$Res> { +class _$FullAccountPageDataCopyWithImpl<$Res> + implements $FullAccountPageDataCopyWith<$Res> { _$FullAccountPageDataCopyWithImpl(this._self, this._then); final FullAccountPageData _self; @@ -3671,13 +3980,20 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult maybeWhen( - TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool)? $default, { + TResult Function( + List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState, + double? price, + MempoolState mempool)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _FullAccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, + _that.syncState, _that.price, _that.mempool); case _: return orElse(); } @@ -3698,12 +4014,15 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult when( - TResult Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool) $default, + TResult Function(List allAccounts, AccountData? currentAccount, + SyncProgressAccount? syncState, double? price, MempoolState mempool) + $default, ) { final _that = this; switch (_that) { case _FullAccountPageData(): - return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, + _that.syncState, _that.price, _that.mempool); } } @@ -3721,12 +4040,19 @@ extension FullAccountPageDataPatterns on FullAccountPageData { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool)? $default, + TResult? Function( + List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState, + double? price, + MempoolState mempool)? + $default, ) { final _that = this; switch (_that) { case _FullAccountPageData() when $default != null: - return $default(_that.allAccounts, _that.currentAccount, _that.syncState, _that.price, _that.mempool); + return $default(_that.allAccounts, _that.currentAccount, + _that.syncState, _that.price, _that.mempool); case _: return null; } @@ -3737,7 +4063,11 @@ extension FullAccountPageDataPatterns on FullAccountPageData { class _FullAccountPageData implements FullAccountPageData { const _FullAccountPageData( - {required final List allAccounts, required this.currentAccount, required this.syncState, required this.price, required this.mempool}) + {required final List allAccounts, + required this.currentAccount, + required this.syncState, + required this.price, + required this.mempool}) : _allAccounts = allAccounts; final List _allAccounts; @@ -3762,22 +4092,33 @@ class _FullAccountPageData implements FullAccountPageData { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$FullAccountPageDataCopyWith<_FullAccountPageData> get copyWith => __$FullAccountPageDataCopyWithImpl<_FullAccountPageData>(this, _$identity); + _$FullAccountPageDataCopyWith<_FullAccountPageData> get copyWith => + __$FullAccountPageDataCopyWithImpl<_FullAccountPageData>( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _FullAccountPageData && - const DeepCollectionEquality().equals(other._allAccounts, _allAccounts) && - (identical(other.currentAccount, currentAccount) || other.currentAccount == currentAccount) && - (identical(other.syncState, syncState) || other.syncState == syncState) && + const DeepCollectionEquality() + .equals(other._allAccounts, _allAccounts) && + (identical(other.currentAccount, currentAccount) || + other.currentAccount == currentAccount) && + (identical(other.syncState, syncState) || + other.syncState == syncState) && (identical(other.price, price) || other.price == price) && (identical(other.mempool, mempool) || other.mempool == mempool)); } @override - int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_allAccounts), currentAccount, syncState, price, mempool); + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_allAccounts), + currentAccount, + syncState, + price, + mempool); @override String toString() { @@ -3786,11 +4127,19 @@ class _FullAccountPageData implements FullAccountPageData { } /// @nodoc -abstract mixin class _$FullAccountPageDataCopyWith<$Res> implements $FullAccountPageDataCopyWith<$Res> { - factory _$FullAccountPageDataCopyWith(_FullAccountPageData value, $Res Function(_FullAccountPageData) _then) = __$FullAccountPageDataCopyWithImpl; +abstract mixin class _$FullAccountPageDataCopyWith<$Res> + implements $FullAccountPageDataCopyWith<$Res> { + factory _$FullAccountPageDataCopyWith(_FullAccountPageData value, + $Res Function(_FullAccountPageData) _then) = + __$FullAccountPageDataCopyWithImpl; @override @useResult - $Res call({List allAccounts, AccountData? currentAccount, SyncProgressAccount? syncState, double? price, MempoolState mempool}); + $Res call( + {List allAccounts, + AccountData? currentAccount, + SyncProgressAccount? syncState, + double? price, + MempoolState mempool}); @override $AccountDataCopyWith<$Res>? get currentAccount; @@ -3801,7 +4150,8 @@ abstract mixin class _$FullAccountPageDataCopyWith<$Res> implements $FullAccount } /// @nodoc -class __$FullAccountPageDataCopyWithImpl<$Res> implements _$FullAccountPageDataCopyWith<$Res> { +class __$FullAccountPageDataCopyWithImpl<$Res> + implements _$FullAccountPageDataCopyWith<$Res> { __$FullAccountPageDataCopyWithImpl(this._self, this._then); final _FullAccountPageData _self; @@ -3893,7 +4243,8 @@ mixin _$QRSettings { /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $QRSettingsCopyWith get copyWith => _$QRSettingsCopyWithImpl(this as QRSettings, _$identity); + $QRSettingsCopyWith get copyWith => + _$QRSettingsCopyWithImpl(this as QRSettings, _$identity); @override bool operator ==(Object other) { @@ -3908,7 +4259,8 @@ mixin _$QRSettings { } @override - int get hashCode => Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); + int get hashCode => + Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); @override String toString() { @@ -3918,7 +4270,9 @@ mixin _$QRSettings { /// @nodoc abstract mixin class $QRSettingsCopyWith<$Res> { - factory $QRSettingsCopyWith(QRSettings value, $Res Function(QRSettings) _then) = _$QRSettingsCopyWithImpl; + factory $QRSettingsCopyWith( + QRSettings value, $Res Function(QRSettings) _then) = + _$QRSettingsCopyWithImpl; @useResult $Res call({bool enabled, double size, int ecLevel, int delay, int repair}); } @@ -4057,13 +4411,16 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult maybeWhen( - TResult Function(bool enabled, double size, int ecLevel, int delay, int repair)? $default, { + TResult Function( + bool enabled, double size, int ecLevel, int delay, int repair)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _QRSettings() when $default != null: - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, + _that.repair); case _: return orElse(); } @@ -4084,12 +4441,15 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult when( - TResult Function(bool enabled, double size, int ecLevel, int delay, int repair) $default, + TResult Function( + bool enabled, double size, int ecLevel, int delay, int repair) + $default, ) { final _that = this; switch (_that) { case _QRSettings(): - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, + _that.repair); } } @@ -4107,12 +4467,15 @@ extension QRSettingsPatterns on QRSettings { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(bool enabled, double size, int ecLevel, int delay, int repair)? $default, + TResult? Function( + bool enabled, double size, int ecLevel, int delay, int repair)? + $default, ) { final _that = this; switch (_that) { case _QRSettings() when $default != null: - return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, _that.repair); + return $default(_that.enabled, _that.size, _that.ecLevel, _that.delay, + _that.repair); case _: return null; } @@ -4122,7 +4485,12 @@ extension QRSettingsPatterns on QRSettings { /// @nodoc class _QRSettings implements QRSettings { - _QRSettings({required this.enabled, required this.size, required this.ecLevel, required this.delay, required this.repair}); + _QRSettings( + {required this.enabled, + required this.size, + required this.ecLevel, + required this.delay, + required this.repair}); @override final bool enabled; @@ -4140,7 +4508,8 @@ class _QRSettings implements QRSettings { @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$QRSettingsCopyWith<_QRSettings> get copyWith => __$QRSettingsCopyWithImpl<_QRSettings>(this, _$identity); + _$QRSettingsCopyWith<_QRSettings> get copyWith => + __$QRSettingsCopyWithImpl<_QRSettings>(this, _$identity); @override bool operator ==(Object other) { @@ -4155,7 +4524,8 @@ class _QRSettings implements QRSettings { } @override - int get hashCode => Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); + int get hashCode => + Object.hash(runtimeType, enabled, size, ecLevel, delay, repair); @override String toString() { @@ -4164,8 +4534,11 @@ class _QRSettings implements QRSettings { } /// @nodoc -abstract mixin class _$QRSettingsCopyWith<$Res> implements $QRSettingsCopyWith<$Res> { - factory _$QRSettingsCopyWith(_QRSettings value, $Res Function(_QRSettings) _then) = __$QRSettingsCopyWithImpl; +abstract mixin class _$QRSettingsCopyWith<$Res> + implements $QRSettingsCopyWith<$Res> { + factory _$QRSettingsCopyWith( + _QRSettings value, $Res Function(_QRSettings) _then) = + __$QRSettingsCopyWithImpl; @override @useResult $Res call({bool enabled, double size, int ecLevel, int delay, int repair}); diff --git a/lib/store.g.dart b/lib/store.g.dart index bbacee2c9..d88e47547 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -49,7 +49,8 @@ abstract class _$HasDb extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, bool, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, bool, Object?, Object?>; element.handleValue(ref, created); } } @@ -57,7 +58,8 @@ abstract class _$HasDb extends $Notifier { @ProviderFor(SelectedAccountId) const selectedAccountIdProvider = SelectedAccountIdProvider._(); -final class SelectedAccountIdProvider extends $NotifierProvider { +final class SelectedAccountIdProvider + extends $NotifierProvider { const SelectedAccountIdProvider._() : super( from: null, @@ -94,7 +96,8 @@ abstract class _$SelectedAccountId extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, int, Object?, Object?>; + final element = ref.element + as $ClassProviderElement, int, Object?, Object?>; element.handleValue(ref, created); } } @@ -102,8 +105,10 @@ abstract class _$SelectedAccountId extends $Notifier { @ProviderFor(SyncStateAccount) const syncStateAccountProvider = SyncStateAccountFamily._(); -final class SyncStateAccountProvider extends $AsyncNotifierProvider { - const SyncStateAccountProvider._({required SyncStateAccountFamily super.from, required int super.argument}) +final class SyncStateAccountProvider + extends $AsyncNotifierProvider { + const SyncStateAccountProvider._( + {required SyncStateAccountFamily super.from, required int super.argument}) : super( retry: null, name: r'syncStateAccountProvider', @@ -140,7 +145,9 @@ final class SyncStateAccountProvider extends $AsyncNotifierProvider r'cb3d58d81b59192492c0aab60de138055b823f7f'; final class SyncStateAccountFamily extends $Family - with $ClassFamilyOverride, SyncProgressAccount, FutureOr, int> { + with + $ClassFamilyOverride, + SyncProgressAccount, FutureOr, int> { const SyncStateAccountFamily._() : super( retry: null, @@ -172,9 +179,13 @@ abstract class _$SyncStateAccount extends $AsyncNotifier { final created = build( _$args, ); - final ref = this.ref as $Ref, SyncProgressAccount>; - final element = ref.element - as $ClassProviderElement, SyncProgressAccount>, AsyncValue, Object?, Object?>; + final ref = + this.ref as $Ref, SyncProgressAccount>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, SyncProgressAccount>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -182,7 +193,8 @@ abstract class _$SyncStateAccount extends $AsyncNotifier { @ProviderFor(selectedAccount) const selectedAccountProvider = SelectedAccountProvider._(); -final class SelectedAccountProvider extends $FunctionalProvider, Account?, FutureOr> +final class SelectedAccountProvider extends $FunctionalProvider< + AsyncValue, Account?, FutureOr> with $FutureModifier, $FutureProvider { const SelectedAccountProvider._() : super( @@ -200,7 +212,8 @@ final class SelectedAccountProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -213,7 +226,8 @@ String _$selectedAccountHash() => r'8fe4c0fb33769599d1a69f1efc302dd70f6b7aa7'; @ProviderFor(SelectedFolder) const selectedFolderProvider = SelectedFolderProvider._(); -final class SelectedFolderProvider extends $NotifierProvider { +final class SelectedFolderProvider + extends $NotifierProvider { const SelectedFolderProvider._() : super( from: null, @@ -250,7 +264,8 @@ abstract class _$SelectedFolder extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, Folder?, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, Folder?, Object?, Object?>; element.handleValue(ref, created); } } @@ -258,7 +273,8 @@ abstract class _$SelectedFolder extends $Notifier { @ProviderFor(getAccounts) const getAccountsProvider = GetAccountsProvider._(); -final class GetAccountsProvider extends $FunctionalProvider>, List, FutureOr>> +final class GetAccountsProvider extends $FunctionalProvider< + AsyncValue>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetAccountsProvider._() : super( @@ -276,7 +292,9 @@ final class GetAccountsProvider extends $FunctionalProvider> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -289,7 +307,8 @@ String _$getAccountsHash() => r'4628dce465555f59311a5f3232bb00fbfb6e428c'; @ProviderFor(getFolders) const getFoldersProvider = GetFoldersProvider._(); -final class GetFoldersProvider extends $FunctionalProvider>, List, FutureOr>> +final class GetFoldersProvider extends $FunctionalProvider< + AsyncValue>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetFoldersProvider._() : super( @@ -307,7 +326,9 @@ final class GetFoldersProvider extends $FunctionalProvider> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -320,7 +341,8 @@ String _$getFoldersHash() => r'2458237b23db05d19a7b49856e9987542680249e'; @ProviderFor(getCategories) const getCategoriesProvider = GetCategoriesProvider._(); -final class GetCategoriesProvider extends $FunctionalProvider>, List, FutureOr>> +final class GetCategoriesProvider extends $FunctionalProvider< + AsyncValue>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetCategoriesProvider._() : super( @@ -338,7 +360,9 @@ final class GetCategoriesProvider extends $FunctionalProvider> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -351,7 +375,8 @@ String _$getCategoriesHash() => r'b936c571d89ff2ede483f5239881ba90219af321'; @ProviderFor(getContacts) const getContactsProvider = GetContactsProvider._(); -final class GetContactsProvider extends $FunctionalProvider>, List, FutureOr>> +final class GetContactsProvider extends $FunctionalProvider< + AsyncValue>, List, FutureOr>> with $FutureModifier>, $FutureProvider> { const GetContactsProvider._() : super( @@ -369,7 +394,9 @@ final class GetContactsProvider extends $FunctionalProvider> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -382,9 +409,16 @@ String _$getContactsHash() => r'e751c15648be7db79565969c43b1be3a0ac566de'; @ProviderFor(contactsForAddress) const contactsForAddressProvider = ContactsForAddressFamily._(); -final class ContactsForAddressProvider extends $FunctionalProvider>, List, FutureOr>> - with $FutureModifier>, $FutureProvider> { - const ContactsForAddressProvider._({required ContactsForAddressFamily super.from, required String super.argument}) +final class ContactsForAddressProvider extends $FunctionalProvider< + AsyncValue>, + List, + FutureOr>> + with + $FutureModifier>, + $FutureProvider> { + const ContactsForAddressProvider._( + {required ContactsForAddressFamily super.from, + required String super.argument}) : super( retry: null, name: r'contactsForAddressProvider', @@ -405,7 +439,9 @@ final class ContactsForAddressProvider extends $FunctionalProvider> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -427,9 +463,11 @@ final class ContactsForAddressProvider extends $FunctionalProvider r'3154c6f4ddf9d4e141da6f70d5a086d79afdc348'; +String _$contactsForAddressHash() => + r'3154c6f4ddf9d4e141da6f70d5a086d79afdc348'; -final class ContactsForAddressFamily extends $Family with $FunctionalFamilyOverride>, String> { +final class ContactsForAddressFamily extends $Family + with $FunctionalFamilyOverride>, String> { const ContactsForAddressFamily._() : super( retry: null, @@ -451,9 +489,11 @@ final class ContactsForAddressFamily extends $Family with $FunctionalFamilyOverr @ProviderFor(account) const accountProvider = AccountFamily._(); -final class AccountProvider extends $FunctionalProvider, AccountData, FutureOr> +final class AccountProvider extends $FunctionalProvider, + AccountData, FutureOr> with $FutureModifier, $FutureProvider { - const AccountProvider._({required AccountFamily super.from, required int super.argument}) + const AccountProvider._( + {required AccountFamily super.from, required int super.argument}) : super( retry: null, name: r'accountProvider', @@ -474,7 +514,9 @@ final class AccountProvider extends $FunctionalProvider, @$internal @override - $FutureProviderElement $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -498,7 +540,8 @@ final class AccountProvider extends $FunctionalProvider, String _$accountHash() => r'b5b61dba595b61fd82e1ba3777a9084c1c546457'; -final class AccountFamily extends $Family with $FunctionalFamilyOverride, int> { +final class AccountFamily extends $Family + with $FunctionalFamilyOverride, int> { const AccountFamily._() : super( retry: null, @@ -520,7 +563,8 @@ final class AccountFamily extends $Family with $FunctionalFamilyOverride, AccountData?, FutureOr> +final class GetCurrentAccountProvider extends $FunctionalProvider< + AsyncValue, AccountData?, FutureOr> with $FutureModifier, $FutureProvider { const GetCurrentAccountProvider._() : super( @@ -538,7 +582,9 @@ final class GetCurrentAccountProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -551,7 +597,8 @@ String _$getCurrentAccountHash() => r'fb9e03f8c767fe77e0f33e71495c3bf0c167c7a1'; @ProviderFor(AppSettingsNotifier) const appSettingsProvider = AppSettingsNotifierProvider._(); -final class AppSettingsNotifierProvider extends $AsyncNotifierProvider { +final class AppSettingsNotifierProvider + extends $AsyncNotifierProvider { const AppSettingsNotifierProvider._() : super( from: null, @@ -571,7 +618,8 @@ final class AppSettingsNotifierProvider extends $AsyncNotifierProvider AppSettingsNotifier(); } -String _$appSettingsNotifierHash() => r'bc2222bf4d3206176cf3b8888aee624034d51fe8'; +String _$appSettingsNotifierHash() => + r'bc2222bf4d3206176cf3b8888aee624034d51fe8'; abstract class _$AppSettingsNotifier extends $AsyncNotifier { FutureOr build(); @@ -580,7 +628,11 @@ abstract class _$AppSettingsNotifier extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, AppSettings>; - final element = ref.element as $ClassProviderElement, AppSettings>, AsyncValue, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, AppSettings>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -588,7 +640,8 @@ abstract class _$AppSettingsNotifier extends $AsyncNotifier { @ProviderFor(PriceNotifier) const priceProvider = PriceNotifierProvider._(); -final class PriceNotifierProvider extends $NotifierProvider { +final class PriceNotifierProvider + extends $NotifierProvider { const PriceNotifierProvider._() : super( from: null, @@ -625,7 +678,8 @@ abstract class _$PriceNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, double?, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, double?, Object?, Object?>; element.handleValue(ref, created); } } @@ -633,7 +687,8 @@ abstract class _$PriceNotifier extends $Notifier { @ProviderFor(SupportedCurrenciesNotifier) const supportedCurrenciesProvider = SupportedCurrenciesNotifierProvider._(); -final class SupportedCurrenciesNotifierProvider extends $AsyncNotifierProvider> { +final class SupportedCurrenciesNotifierProvider + extends $AsyncNotifierProvider> { const SupportedCurrenciesNotifierProvider._() : super( from: null, @@ -653,16 +708,22 @@ final class SupportedCurrenciesNotifierProvider extends $AsyncNotifierProvider SupportedCurrenciesNotifier(); } -String _$supportedCurrenciesNotifierHash() => r'6f0ef88efa8e2e0b124b8880bea1e8620df43f27'; +String _$supportedCurrenciesNotifierHash() => + r'6f0ef88efa8e2e0b124b8880bea1e8620df43f27'; -abstract class _$SupportedCurrenciesNotifier extends $AsyncNotifier> { +abstract class _$SupportedCurrenciesNotifier + extends $AsyncNotifier> { FutureOr> build(); @$mustCallSuper @override void runBuild() { final created = build(); final ref = this.ref as $Ref>, List>; - final element = ref.element as $ClassProviderElement>, List>, AsyncValue>, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier>, List>, + AsyncValue>, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -670,7 +731,8 @@ abstract class _$SupportedCurrenciesNotifier extends $AsyncNotifier @ProviderFor(LogNotifier) const logProvider = LogNotifierProvider._(); -final class LogNotifierProvider extends $NotifierProvider> { +final class LogNotifierProvider + extends $NotifierProvider> { const LogNotifierProvider._() : super( from: null, @@ -707,7 +769,11 @@ abstract class _$LogNotifier extends $Notifier> { void runBuild() { final created = build(); final ref = this.ref as $Ref, List>; - final element = ref.element as $ClassProviderElement, List>, List, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, List>, + List, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -715,7 +781,8 @@ abstract class _$LogNotifier extends $Notifier> { @ProviderFor(CurrentHeight) const currentHeightProvider = CurrentHeightProvider._(); -final class CurrentHeightProvider extends $AsyncNotifierProvider { +final class CurrentHeightProvider + extends $AsyncNotifierProvider { const CurrentHeightProvider._() : super( from: null, @@ -744,7 +811,11 @@ abstract class _$CurrentHeight extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, int?>; - final element = ref.element as $ClassProviderElement, int?>, AsyncValue, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, int?>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -752,7 +823,8 @@ abstract class _$CurrentHeight extends $AsyncNotifier { @ProviderFor(MempoolNotifier) const mempoolProvider = MempoolNotifierProvider._(); -final class MempoolNotifierProvider extends $NotifierProvider { +final class MempoolNotifierProvider + extends $NotifierProvider { const MempoolNotifierProvider._() : super( from: null, @@ -789,7 +861,11 @@ abstract class _$MempoolNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, MempoolState, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, + MempoolState, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -797,7 +873,8 @@ abstract class _$MempoolNotifier extends $Notifier { @ProviderFor(SynchronizerNotifier) const synchronizerProvider = SynchronizerNotifierProvider._(); -final class SynchronizerNotifierProvider extends $NotifierProvider { +final class SynchronizerNotifierProvider + extends $NotifierProvider { const SynchronizerNotifierProvider._() : super( from: null, @@ -825,7 +902,8 @@ final class SynchronizerNotifierProvider extends $NotifierProvider r'3bab6681ff1ee0f1161575e4690f143aa9e72f7b'; +String _$synchronizerNotifierHash() => + r'e1255e0b5231ffed2b73cb13d94c43f9d1c365b4'; abstract class _$SynchronizerNotifier extends $Notifier { SyncState build(); @@ -834,7 +912,8 @@ abstract class _$SynchronizerNotifier extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, SyncState, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, SyncState, Object?, Object?>; element.handleValue(ref, created); } } @@ -842,7 +921,8 @@ abstract class _$SynchronizerNotifier extends $Notifier { @ProviderFor(TransparentScan) const transparentScanProvider = TransparentScanProvider._(); -final class TransparentScanProvider extends $NotifierProvider { +final class TransparentScanProvider + extends $NotifierProvider { const TransparentScanProvider._() : super( from: null, @@ -879,7 +959,8 @@ abstract class _$TransparentScan extends $Notifier { void runBuild() { final created = build(); final ref = this.ref as $Ref; - final element = ref.element as $ClassProviderElement, String, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, String, Object?, Object?>; element.handleValue(ref, created); } } @@ -887,8 +968,10 @@ abstract class _$TransparentScan extends $Notifier { @ProviderFor(GetTxDetails) const getTxDetailsProvider = GetTxDetailsFamily._(); -final class GetTxDetailsProvider extends $AsyncNotifierProvider { - const GetTxDetailsProvider._({required GetTxDetailsFamily super.from, required int super.argument}) +final class GetTxDetailsProvider + extends $AsyncNotifierProvider { + const GetTxDetailsProvider._( + {required GetTxDetailsFamily super.from, required int super.argument}) : super( retry: null, name: r'getTxDetailsProvider', @@ -924,7 +1007,10 @@ final class GetTxDetailsProvider extends $AsyncNotifierProvider r'67175e914e53d2de8944db85e0f9225374cba276'; -final class GetTxDetailsFamily extends $Family with $ClassFamilyOverride, TxAccount, FutureOr, int> { +final class GetTxDetailsFamily extends $Family + with + $ClassFamilyOverride, TxAccount, + FutureOr, int> { const GetTxDetailsFamily._() : super( retry: null, @@ -957,7 +1043,11 @@ abstract class _$GetTxDetails extends $AsyncNotifier { _$args, ); final ref = this.ref as $Ref, TxAccount>; - final element = ref.element as $ClassProviderElement, TxAccount>, AsyncValue, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, TxAccount>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -994,7 +1084,11 @@ abstract class _$Lifecycle extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, bool>; - final element = ref.element as $ClassProviderElement, bool>, AsyncValue, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, bool>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -1002,7 +1096,10 @@ abstract class _$Lifecycle extends $AsyncNotifier { @ProviderFor(accountsPageData) const accountsPageDataProvider = AccountsPageDataProvider._(); -final class AccountsPageDataProvider extends $FunctionalProvider, AccountsPageData, FutureOr> +final class AccountsPageDataProvider extends $FunctionalProvider< + AsyncValue, + AccountsPageData, + FutureOr> with $FutureModifier, $FutureProvider { const AccountsPageDataProvider._() : super( @@ -1020,7 +1117,9 @@ final class AccountsPageDataProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1033,7 +1132,10 @@ String _$accountsPageDataHash() => r'e37b6e048a3a3938c9c2b03ae41328036271956d'; @ProviderFor(basicAccountData) const basicAccountDataProvider = BasicAccountDataProvider._(); -final class BasicAccountDataProvider extends $FunctionalProvider, BasicAccountData, FutureOr> +final class BasicAccountDataProvider extends $FunctionalProvider< + AsyncValue, + BasicAccountData, + FutureOr> with $FutureModifier, $FutureProvider { const BasicAccountDataProvider._() : super( @@ -1051,7 +1153,9 @@ final class BasicAccountDataProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1064,7 +1168,8 @@ String _$basicAccountDataHash() => r'5f755167b7edd069b07888af935e53d49e425a16'; @ProviderFor(accountPageData) const accountPageDataProvider = AccountPageDataProvider._(); -final class AccountPageDataProvider extends $FunctionalProvider, AccountPageData, FutureOr> +final class AccountPageDataProvider extends $FunctionalProvider< + AsyncValue, AccountPageData, FutureOr> with $FutureModifier, $FutureProvider { const AccountPageDataProvider._() : super( @@ -1082,7 +1187,9 @@ final class AccountPageDataProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1095,8 +1202,13 @@ String _$accountPageDataHash() => r'be356fdedbc8bf660c5ff2d19eaec87577045d47'; @ProviderFor(fullAccountPageData) const fullAccountPageDataProvider = FullAccountPageDataProvider._(); -final class FullAccountPageDataProvider extends $FunctionalProvider, FullAccountPageData, FutureOr> - with $FutureModifier, $FutureProvider { +final class FullAccountPageDataProvider extends $FunctionalProvider< + AsyncValue, + FullAccountPageData, + FutureOr> + with + $FutureModifier, + $FutureProvider { const FullAccountPageDataProvider._() : super( from: null, @@ -1113,7 +1225,9 @@ final class FullAccountPageDataProvider extends $FunctionalProvider $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr create(Ref ref) { @@ -1121,12 +1235,14 @@ final class FullAccountPageDataProvider extends $FunctionalProvider r'742c766717c6b4f146d1f6fa7c6a5aa2512fa0b6'; +String _$fullAccountPageDataHash() => + r'742c766717c6b4f146d1f6fa7c6a5aa2512fa0b6'; @ProviderFor(VaultNotifier) const vaultProvider = VaultNotifierProvider._(); -final class VaultNotifierProvider extends $AsyncNotifierProvider { +final class VaultNotifierProvider + extends $AsyncNotifierProvider { const VaultNotifierProvider._() : super( from: null, @@ -1155,7 +1271,11 @@ abstract class _$VaultNotifier extends $AsyncNotifier { void runBuild() { final created = build(); final ref = this.ref as $Ref, Vault>; - final element = ref.element as $ClassProviderElement, Vault>, AsyncValue, Object?, Object?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, Vault>, + AsyncValue, + Object?, + Object?>; element.handleValue(ref, created); } } @@ -1163,9 +1283,13 @@ abstract class _$VaultNotifier extends $AsyncNotifier { @ProviderFor(pluginList) const pluginListProvider = PluginListProvider._(); -final class PluginListProvider - extends $FunctionalProvider>, List, FutureOr>> - with $FutureModifier>, $FutureProvider> { +final class PluginListProvider extends $FunctionalProvider< + AsyncValue>, + List, + FutureOr>> + with + $FutureModifier>, + $FutureProvider> { const PluginListProvider._() : super( from: null, @@ -1182,7 +1306,9 @@ final class PluginListProvider @$internal @override - $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -1195,9 +1321,13 @@ String _$pluginListHash() => r'f396f236f61820f586848210e153f83881ad09c1'; @ProviderFor(pluginMemoSections) const pluginMemoSectionsProvider = PluginMemoSectionsFamily._(); -final class PluginMemoSectionsProvider - extends $FunctionalProvider>, List, FutureOr>> - with $FutureModifier>, $FutureProvider> { +final class PluginMemoSectionsProvider extends $FunctionalProvider< + AsyncValue>, + List, + FutureOr>> + with + $FutureModifier>, + $FutureProvider> { const PluginMemoSectionsProvider._( {required PluginMemoSectionsFamily super.from, required ( @@ -1225,7 +1355,9 @@ final class PluginMemoSectionsProvider @$internal @override - $FutureProviderElement> $createElement($ProviderPointer pointer) => $FutureProviderElement(pointer); + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); @override FutureOr> create(Ref ref) { @@ -1251,7 +1383,8 @@ final class PluginMemoSectionsProvider } } -String _$pluginMemoSectionsHash() => r'ecd47c3bc96fdf29a00b04a6d8b8f97742208824'; +String _$pluginMemoSectionsHash() => + r'ecd47c3bc96fdf29a00b04a6d8b8f97742208824'; final class PluginMemoSectionsFamily extends $Family with diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a9a639064..0e528ebd4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,6 +13,7 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fd4362b097579782565de553b7b8c5a612cda1e2", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index d926119e0..80c6ad13d 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -18,4 +18,5 @@ pub mod sweep; pub mod sync; pub mod transaction; pub mod vault; +pub mod voting; pub mod zsa; diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs new file mode 100644 index 000000000..b063f02a3 --- /dev/null +++ b/rust/src/api/voting.rs @@ -0,0 +1,615 @@ +//! FRB wrappers for the shielded voting flow (ZIP 262 delegation + cast votes). +//! +//! The fork's `zcash_voting` types are not FRB-visible, so this module defines +//! JSON-serializable mirror structs and converts at the boundary. State +//! transitions follow the plan: prepare → setup → sign/prove/submit → confirm, +//! then van witness → commit → payloads → record execution → confirm. + +use anyhow::{anyhow, Result}; +use serde::{Deserialize, Serialize}; +use zcash_voting::prelude::{BundlePolicy, NoopProgressReporter, TxEvent}; +use zcash_voting::VotingRoundParams; +#[cfg(feature = "flutter")] +use flutter_rust_bridge::frb; + +use crate::{api::coin::Coin, voting}; + +// --------------------------------------------------------------------------- +// Mirror types +// --------------------------------------------------------------------------- + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingPreparedInfo { + pub round_id: String, + pub bundle_index: u32, + pub eligible_weight_zatoshi: u64, + pub delegated_weight_zatoshi: u64, + pub round_name: String, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingPirLayout { + pub pir_depth: u32, + pub tier0_layers: u32, + pub tier1_layers: u32, + pub poly_len: u32, +} + +impl VotingPirLayout { + fn to_fork(self) -> zcash_voting::config::PirLayout { + zcash_voting::config::PirLayout { + pir_depth: self.pir_depth, + tier0_layers: self.tier0_layers, + tier1_layers: self.tier1_layers, + poly_len: self.poly_len, + } + } +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationSetup { + pub pczt_bytes: Vec, + pub pczt_sighash: Vec, + pub rk: Vec, + pub action_index: u32, + pub action_bytes: Vec, + pub tx1_effects: Vec, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationSubmission { + pub proof: Vec, + pub rk: Vec, + pub nf_signed: Vec, + pub cmx_new: Vec, + pub gov_comm: Vec, + pub gov_nullifiers: Vec>, + pub alpha: Vec, + pub vote_round_id: String, + pub spend_auth_sig: Vec, + pub sighash: Vec, + pub tx1_effects: Vec, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationConfirmation { + pub tx_hash: String, + pub van_leaf_position: u32, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVoteConfirmation { + pub tx_hash: String, + pub van_leaf_position: u32, + pub vc_tree_position: u64, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVanWitness { + pub auth_path: Vec>, + pub position: u32, + pub anchor_height: u32, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingSignedVoteCommitment { + pub proposal_id: u32, + pub choice: u32, + pub vote_round_id: String, + pub van_nullifier: Vec, + pub vote_authority_note_new: Vec, + pub vote_commitment: Vec, + pub proof: Vec, + pub anchor_height: u32, + pub r_vpk: Vec, + pub vote_auth_sig: Vec, + pub commitment_bundle_json: String, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVoteCommitments { + pub bundle_index: u32, + pub commitments: Vec, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingEncryptedShare { + pub c1: Vec, + pub c2: Vec, + pub share_index: u32, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingSharePayload { + pub shares_hash: Vec, + pub proposal_id: u32, + pub vote_decision: u32, + pub enc_share: VotingEncryptedShare, + pub tree_position: u64, + pub all_enc_shares: Vec, + pub share_comms: Vec>, + pub primary_blind: Vec, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVoteSubmission { + pub vote_round_id: String, + pub proposal_id: u32, + pub van_nullifier: Vec, + pub vote_authority_note_new: Vec, + pub vote_commitment: Vec, + pub proof: Vec, + pub r_vpk: Vec, + pub vote_auth_sig: Vec, + pub anchor_height: u32, +} + +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVotePayloads { + pub submission: VotingVoteSubmission, + pub share_payloads: Vec, +} + +/// One helper-share delivery result for `voting_record_execution`. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingShareDelivery { + pub share_index: u32, + pub sent_to_urls: Vec, + pub submit_at: u64, + pub confirmed: bool, +} + +// --------------------------------------------------------------------------- +// Conversions +// --------------------------------------------------------------------------- + +impl From for VotingDelegationSetup { + fn from(setup: zcash_voting::prelude::DelegationSetup) -> Self { + Self { + pczt_bytes: setup.pczt_bytes, + pczt_sighash: setup.pczt_sighash.to_vec(), + rk: setup.rk.to_vec(), + action_index: setup.action_index as u32, + action_bytes: setup.action_bytes, + tx1_effects: setup.tx1_effects, + } + } +} + +impl From for VotingDelegationSubmission { + fn from(submission: zcash_voting::prelude::DelegationSubmission) -> Self { + Self { + proof: submission.proof, + rk: submission.rk.to_vec(), + nf_signed: submission.nf_signed.to_vec(), + cmx_new: submission.cmx_new.to_vec(), + gov_comm: submission.gov_comm.to_vec(), + gov_nullifiers: submission.gov_nullifiers.into_iter().map(|v| v.to_vec()).collect(), + alpha: submission.alpha.to_vec(), + vote_round_id: submission.vote_round_id, + spend_auth_sig: submission.spend_auth_sig.to_vec(), + sighash: submission.sighash.to_vec(), + tx1_effects: submission.tx1_effects, + } + } +} + +impl From for VotingDelegationConfirmation { + fn from(confirmation: zcash_voting::prelude::DelegationConfirmation) -> Self { + Self { + tx_hash: confirmation.tx_hash, + van_leaf_position: confirmation.van_leaf_position, + } + } +} + +impl From for VotingVoteConfirmation { + fn from(confirmation: zcash_voting::prelude::VoteConfirmation) -> Self { + Self { + tx_hash: confirmation.tx_hash, + van_leaf_position: confirmation.van_leaf_position, + vc_tree_position: confirmation.vc_tree_position, + } + } +} + +impl From for VotingVanWitness { + fn from(witness: zcash_voting::prelude::VanWitness) -> Self { + Self { + auth_path: witness.auth_path, + position: witness.position, + anchor_height: witness.anchor_height, + } + } +} + +impl From for VotingVoteCommitments { + fn from(commitments: zcash_voting::prelude::SignedVoteCommitments) -> Self { + Self { + bundle_index: commitments.bundle_index, + commitments: commitments + .commitments + .into_iter() + .map(|c| VotingSignedVoteCommitment { + proposal_id: c.proposal_id, + choice: c.choice, + vote_round_id: c.vote_round_id, + van_nullifier: c.van_nullifier.to_vec(), + vote_authority_note_new: c.vote_authority_note_new.to_vec(), + vote_commitment: c.vote_commitment.to_vec(), + proof: c.proof, + anchor_height: c.anchor_height, + r_vpk: c.r_vpk.to_vec(), + vote_auth_sig: c.vote_auth_sig.to_vec(), + commitment_bundle_json: c.commitment_bundle_json, + }) + .collect(), + } + } +} + +impl From<&zcash_voting::WireEncryptedShare> for VotingEncryptedShare { + fn from(share: &zcash_voting::WireEncryptedShare) -> Self { + Self { + c1: share.c1.clone(), + c2: share.c2.clone(), + share_index: share.share_index, + } + } +} + +impl From<&zcash_voting::prelude::SharePayload> for VotingSharePayload { + fn from(payload: &zcash_voting::prelude::SharePayload) -> Self { + Self { + shares_hash: payload.shares_hash.clone(), + proposal_id: payload.proposal_id, + vote_decision: payload.vote_decision, + enc_share: (&payload.enc_share).into(), + tree_position: payload.tree_position, + all_enc_shares: payload.all_enc_shares.iter().map(Into::into).collect(), + share_comms: payload.share_comms.clone(), + primary_blind: payload.primary_blind.clone(), + } + } +} + +impl From for VotingVoteSubmission { + fn from(submission: zcash_voting::prelude::VoteSubmission) -> Self { + Self { + vote_round_id: submission.vote_round_id, + proposal_id: submission.proposal_id, + van_nullifier: submission.van_nullifier.to_vec(), + vote_authority_note_new: submission.vote_authority_note_new.to_vec(), + vote_commitment: submission.vote_commitment.to_vec(), + proof: submission.proof, + r_vpk: submission.r_vpk.to_vec(), + vote_auth_sig: submission.vote_auth_sig.to_vec(), + anchor_height: submission.anchor_height, + } + } +} + +// --------------------------------------------------------------------------- +// Delegation flow +// --------------------------------------------------------------------------- + +/// Creates and persists a fresh app-owned voting hotkey (hex stored secret). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_hotkey_create(c: &Coin) -> Result { + let network = voting::voting_network(&c.network())?; + let mut connection = c.get_connection().await?; + let hotkey = voting::voting_hotkey_create(&mut connection, network).await?; + Ok(hex::encode(hotkey.stored_secret())) +} + +/// Returns the persisted voting hotkey stored secret (hex), if any. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_hotkey_get(c: &Coin) -> Result { + let network = voting::voting_network(&c.network())?; + let mut connection = c.get_connection().await?; + let hotkey = voting::voting_hotkey_load(&mut connection, network).await?; + Ok(hex::encode(hotkey.stored_secret())) +} + +/// Prepares one delegation bundle from the wallet's own Ironwood notes. +/// +/// `round_params_json` is the JSON-serialized `VotingRoundParams` from the +/// vote chain. The wallet must be synced through the round snapshot height; +/// witnesses are rooted at the snapshot's Ironwood `nc_root`. +#[cfg_attr(feature = "flutter", frb)] +#[allow(clippy::too_many_arguments)] +pub async fn delegation_prepare( + round_params_json: &str, + round_name: &str, + session_json: Option, + bundle_index: u32, + max_real_notes_per_bundle: Option, + lightwalletd_url: &str, + c: &Coin, +) -> Result { + let account = c.account; + let wallet_network = &c.network(); + let network = voting::voting_network(wallet_network)?; + let round_params: VotingRoundParams = serde_json::from_str(round_params_json)?; + let snapshot_height = u32::try_from(round_params.snapshot_height) + .map_err(|_| anyhow!("snapshot height {} does not fit u32", round_params.snapshot_height))?; + + let mut connection = c.get_connection().await?; + let mut client = c.client().await?; + + let lwd = + voting::gather_lwd_inputs(lightwalletd_url, network, &round_params, round_name).await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let inputs = voting::load_round_inputs( + wallet_network, + &mut connection, + &mut client, + account, + snapshot_height, + &round_params.nc_root, + ) + .await?; + let identity = + voting::load_voting_identity(&mut connection, account, network, &lwd.resolved_round_name) + .await?; + let bundle_policy = BundlePolicy::from_optional_max_real_notes_per_bundle( + max_real_notes_per_bundle, + )?; + + let prepared = voting::prepare_delegation_bundle( + c.get_pool()?, + &wallet_id, + lwd, + session_json.as_deref(), + inputs.note_infos, + identity.delegation_keys, + inputs.witnesses, + bundle_index, + bundle_policy, + ) + .await?; + + let info = VotingPreparedInfo { + round_id: prepared.round_id.clone(), + bundle_index: prepared.bundle_index, + eligible_weight_zatoshi: prepared.eligible_weight_zatoshi(), + delegated_weight_zatoshi: prepared.delegated_weight_zatoshi()?, + round_name: prepared.round_name.clone(), + }; + voting::cache_prepared_bundle(&wallet_id, prepared); + Ok(info) +} + +/// Builds and persists the governance PCZT setup for a prepared bundle. +#[cfg_attr(feature = "flutter", frb)] +pub async fn delegation_setup( + round_id: &str, + bundle_index: u32, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + + let setup = prepared.setup(&db, &NoopProgressReporter).await?; + Ok(setup.into()) +} + +/// Signs with the wallet seed, proves against the PIR server, and assembles +/// the chain-ready delegation submission for the vote chain. +#[cfg_attr(feature = "flutter", frb)] +#[allow(clippy::too_many_arguments)] +pub async fn delegation_sign_and_submit( + round_id: &str, + bundle_index: u32, + pczt_bytes: Vec, + pir_layout: VotingPirLayout, + pir_server_url: &str, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; + let seed = voting::account_seed(&mut connection, c.account).await?; + + let submission = voting::prove_and_submit_delegation( + c.get_pool()?, + &wallet_id, + &prepared, + &seed, + pczt_bytes, + pir_layout.to_fork(), + pir_server_url, + ) + .await?; + Ok(submission.into()) +} + +/// Records a confirmed delegation transaction and persists the bundle's VAN +/// position (required before any vote). +#[cfg_attr(feature = "flutter", frb)] +pub async fn delegation_confirm( + round_id: &str, + bundle_index: u32, + tx_hash: &str, + events_json: &str, + c: &Coin, +) -> Result { + let events: Vec = serde_json::from_str(events_json)?; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let confirmation = voting::confirm_delegation( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + tx_hash, + &events, + ) + .await?; + Ok(confirmation.into()) +} + +// --------------------------------------------------------------------------- +// Vote casting flow +// --------------------------------------------------------------------------- + +/// Syncs the vote-authority-note tree and derives this bundle's VAN witness. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_van_witness( + round_id: &str, + bundle_index: u32, + vote_node_url: &str, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let witness = voting::vote_van_witness( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + vote_node_url, + ) + .await?; + Ok(witness.into()) +} + +/// Commits a batch of vote drafts for one bundle (hotkey-signed). +/// +/// Chains the VAN witness derivation internally, so this may be called right +/// after `voting_van_witness` or standalone. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_commit( + round_id: &str, + bundle_index: u32, + drafts_json: &str, + vote_node_url: &str, + c: &Coin, +) -> Result { + let drafts: Vec = serde_json::from_str(drafts_json)?; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let hotkey = voting::voting_hotkey_load( + &mut connection, + voting::voting_network(&c.network())?, + ) + .await?; + + let witness = voting::vote_van_witness( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + vote_node_url, + ) + .await?; + let commitments = voting::commit_votes( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + &drafts, + &witness, + &hotkey, + ) + .await?; + Ok(commitments.into()) +} + +/// Returns the chain-ready vote submission and helper-share payloads for one +/// committed vote. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_payloads( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let (submission, share_payloads) = voting::vote_payloads( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + ) + .await?; + Ok(VotingVotePayloads { + submission: submission.into(), + share_payloads: share_payloads.iter().map(Into::into).collect(), + }) +} + +/// Records successful vote-chain and helper-share submissions for one vote. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_record_execution( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + vote_tx_hash: &str, + vc_tree_position: u64, + share_deliveries_json: &str, + c: &Coin, +) -> Result<()> { + let share_deliveries: Vec = serde_json::from_str(share_deliveries_json)?; + let shares: Vec<(u32, Vec, u64, bool)> = share_deliveries + .into_iter() + .map(|d| (d.share_index, d.sent_to_urls, d.submit_at, d.confirmed)) + .collect(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + voting::record_vote_execution( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + vote_tx_hash, + vc_tree_position, + &shares, + ) + .await +} + +/// Records a confirmed cast-vote transaction. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_confirm( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + tx_hash: &str, + events_json: &str, + c: &Coin, +) -> Result { + let events: Vec = serde_json::from_str(events_json)?; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let confirmation = voting::confirm_vote( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + tx_hash, + &events, + ) + .await?; + Ok(confirmation.into()) +} diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 433c9e52e..764bdc346 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 151776773; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1244747988; // Section: executor @@ -1656,6 +1656,197 @@ fn wire__crate__api__raptor__decode_impl( }, ) } +fn wire__crate__api__voting__delegation_confirm_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_confirm", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_events_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_confirm( + &api_round_id, + api_bundle_index, + &api_tx_hash, + &api_events_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__delegation_prepare_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_prepare", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_params_json = ::sse_decode(&mut deserializer); + let api_round_name = ::sse_decode(&mut deserializer); + let api_session_json = >::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_max_real_notes_per_bundle = >::sse_decode(&mut deserializer); + let api_lightwalletd_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_prepare( + &api_round_params_json, + &api_round_name, + api_session_json, + api_bundle_index, + api_max_real_notes_per_bundle, + &api_lightwalletd_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__delegation_setup_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_setup", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_setup( + &api_round_id, + api_bundle_index, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__delegation_sign_and_submit_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_sign_and_submit", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_pczt_bytes = >::sse_decode(&mut deserializer); + let api_pir_layout = + ::sse_decode(&mut deserializer); + let api_pir_server_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_sign_and_submit( + &api_round_id, + api_bundle_index, + api_pczt_bytes, + api_pir_layout, + &api_pir_server_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__account__delete_account_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -6837,84 +7028,393 @@ fn wire__crate__api__openalias__validate_zcash_address_impl( }, ) } - -// Section: related_funcs - -fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dart_opaque: flutter_rust_bridge::DartOpaque, -) -> impl Fn( - Vec, -) -> flutter_rust_bridge::DartFnFuture< - std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error>, -> { - use flutter_rust_bridge::IntoDart; - - async fn body( - dart_opaque: flutter_rust_bridge::DartOpaque, - arg0: Vec, - ) -> std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error> { - let args = vec![arg0.into_into_dart().into_dart()]; - let message = FLUTTER_RUST_BRIDGE_HANDLER - .dart_fn_invoke(dart_opaque, args) - .await; - - let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let action = deserializer.cursor.read_u8().unwrap(); - let ans = match action { - 0 => std::result::Result::Ok(<()>::sse_decode(&mut deserializer)), - 1 => std::result::Result::Err( - ::sse_decode(&mut deserializer), - ), - _ => unreachable!(), - }; - deserializer.end(); - ans - } - - move |arg0: Vec| { - flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( - dart_opaque.clone(), - arg0, - )) - } -} -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); - -// Section: dart2rust - -impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); - } -} - -impl SseDecode for DartVault { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = , - >>::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); - } +fn wire__crate__api__voting__voting_commit_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_commit", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_drafts_json = ::sse_decode(&mut deserializer); + let api_vote_node_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_commit( + &api_round_id, + api_bundle_index, + &api_drafts_json, + &api_vote_node_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) } - -impl SseDecode for Mempool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_confirm", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_events_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_confirm( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_tx_hash, + &api_events_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_hotkey_create_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_hotkey_create", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_hotkey_create(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_hotkey_get_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_hotkey_get", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_hotkey_get(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_payloads_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_payloads", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_payloads( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_record_execution_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_record_execution", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_vote_tx_hash = ::sse_decode(&mut deserializer); + let api_vc_tree_position = ::sse_decode(&mut deserializer); + let api_share_deliveries_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_record_execution( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_vote_tx_hash, + api_vc_tree_position, + &api_share_deliveries_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_van_witness_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_van_witness", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_vote_node_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_van_witness( + &api_round_id, + api_bundle_index, + &api_vote_node_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} + +// Section: related_funcs + +fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn( + Vec, +) -> flutter_rust_bridge::DartFnFuture< + std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error>, +> { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: Vec, + ) -> std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(<()>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + ans + } + + move |arg0: Vec| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); + +// Section: dart2rust + +impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); + } +} + +impl SseDecode for DartVault { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + +impl SseDecode for Mempool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , >>::sse_decode(deserializer); return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); @@ -7739,25 +8239,65 @@ impl SseDecode for Vec { } } -impl SseDecode for Vec { +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut len_ = ::sse_decode(deserializer); let mut ans_ = Vec::with_capacity(len_ as usize); for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); + ans_.push(::sse_decode( + deserializer, + )); } return ans_; } } -impl SseDecode for Vec { +impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut len_ = ::sse_decode(deserializer); let mut ans_ = Vec::with_capacity(len_ as usize); for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); + ans_.push(::sse_decode(deserializer)); } return ans_; } @@ -8768,6 +9308,252 @@ impl SseDecode for [usize; 4] { } } +impl SseDecode for crate::api::voting::VotingDelegationConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_txHash = ::sse_decode(deserializer); + let mut var_vanLeafPosition = ::sse_decode(deserializer); + return crate::api::voting::VotingDelegationConfirmation { + tx_hash: var_txHash, + van_leaf_position: var_vanLeafPosition, + }; + } +} + +impl SseDecode for crate::api::voting::VotingDelegationSetup { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_pcztBytes = >::sse_decode(deserializer); + let mut var_pcztSighash = >::sse_decode(deserializer); + let mut var_rk = >::sse_decode(deserializer); + let mut var_actionIndex = ::sse_decode(deserializer); + let mut var_actionBytes = >::sse_decode(deserializer); + let mut var_tx1Effects = >::sse_decode(deserializer); + return crate::api::voting::VotingDelegationSetup { + pczt_bytes: var_pcztBytes, + pczt_sighash: var_pcztSighash, + rk: var_rk, + action_index: var_actionIndex, + action_bytes: var_actionBytes, + tx1_effects: var_tx1Effects, + }; + } +} + +impl SseDecode for crate::api::voting::VotingDelegationSubmission { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_proof = >::sse_decode(deserializer); + let mut var_rk = >::sse_decode(deserializer); + let mut var_nfSigned = >::sse_decode(deserializer); + let mut var_cmxNew = >::sse_decode(deserializer); + let mut var_govComm = >::sse_decode(deserializer); + let mut var_govNullifiers = >>::sse_decode(deserializer); + let mut var_alpha = >::sse_decode(deserializer); + let mut var_voteRoundId = ::sse_decode(deserializer); + let mut var_spendAuthSig = >::sse_decode(deserializer); + let mut var_sighash = >::sse_decode(deserializer); + let mut var_tx1Effects = >::sse_decode(deserializer); + return crate::api::voting::VotingDelegationSubmission { + proof: var_proof, + rk: var_rk, + nf_signed: var_nfSigned, + cmx_new: var_cmxNew, + gov_comm: var_govComm, + gov_nullifiers: var_govNullifiers, + alpha: var_alpha, + vote_round_id: var_voteRoundId, + spend_auth_sig: var_spendAuthSig, + sighash: var_sighash, + tx1_effects: var_tx1Effects, + }; + } +} + +impl SseDecode for crate::api::voting::VotingEncryptedShare { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_c1 = >::sse_decode(deserializer); + let mut var_c2 = >::sse_decode(deserializer); + let mut var_shareIndex = ::sse_decode(deserializer); + return crate::api::voting::VotingEncryptedShare { + c1: var_c1, + c2: var_c2, + share_index: var_shareIndex, + }; + } +} + +impl SseDecode for crate::api::voting::VotingPirLayout { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_pirDepth = ::sse_decode(deserializer); + let mut var_tier0Layers = ::sse_decode(deserializer); + let mut var_tier1Layers = ::sse_decode(deserializer); + let mut var_polyLen = ::sse_decode(deserializer); + return crate::api::voting::VotingPirLayout { + pir_depth: var_pirDepth, + tier0_layers: var_tier0Layers, + tier1_layers: var_tier1Layers, + poly_len: var_polyLen, + }; + } +} + +impl SseDecode for crate::api::voting::VotingPreparedInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_eligibleWeightZatoshi = ::sse_decode(deserializer); + let mut var_delegatedWeightZatoshi = ::sse_decode(deserializer); + let mut var_roundName = ::sse_decode(deserializer); + return crate::api::voting::VotingPreparedInfo { + round_id: var_roundId, + bundle_index: var_bundleIndex, + eligible_weight_zatoshi: var_eligibleWeightZatoshi, + delegated_weight_zatoshi: var_delegatedWeightZatoshi, + round_name: var_roundName, + }; + } +} + +impl SseDecode for crate::api::voting::VotingSharePayload { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_sharesHash = >::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_voteDecision = ::sse_decode(deserializer); + let mut var_encShare = ::sse_decode(deserializer); + let mut var_treePosition = ::sse_decode(deserializer); + let mut var_allEncShares = + >::sse_decode(deserializer); + let mut var_shareComms = >>::sse_decode(deserializer); + let mut var_primaryBlind = >::sse_decode(deserializer); + return crate::api::voting::VotingSharePayload { + shares_hash: var_sharesHash, + proposal_id: var_proposalId, + vote_decision: var_voteDecision, + enc_share: var_encShare, + tree_position: var_treePosition, + all_enc_shares: var_allEncShares, + share_comms: var_shareComms, + primary_blind: var_primaryBlind, + }; + } +} + +impl SseDecode for crate::api::voting::VotingSignedVoteCommitment { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_choice = ::sse_decode(deserializer); + let mut var_voteRoundId = ::sse_decode(deserializer); + let mut var_vanNullifier = >::sse_decode(deserializer); + let mut var_voteAuthorityNoteNew = >::sse_decode(deserializer); + let mut var_voteCommitment = >::sse_decode(deserializer); + let mut var_proof = >::sse_decode(deserializer); + let mut var_anchorHeight = ::sse_decode(deserializer); + let mut var_rVpk = >::sse_decode(deserializer); + let mut var_voteAuthSig = >::sse_decode(deserializer); + let mut var_commitmentBundleJson = ::sse_decode(deserializer); + return crate::api::voting::VotingSignedVoteCommitment { + proposal_id: var_proposalId, + choice: var_choice, + vote_round_id: var_voteRoundId, + van_nullifier: var_vanNullifier, + vote_authority_note_new: var_voteAuthorityNoteNew, + vote_commitment: var_voteCommitment, + proof: var_proof, + anchor_height: var_anchorHeight, + r_vpk: var_rVpk, + vote_auth_sig: var_voteAuthSig, + commitment_bundle_json: var_commitmentBundleJson, + }; + } +} + +impl SseDecode for crate::api::voting::VotingVanWitness { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_authPath = >>::sse_decode(deserializer); + let mut var_position = ::sse_decode(deserializer); + let mut var_anchorHeight = ::sse_decode(deserializer); + return crate::api::voting::VotingVanWitness { + auth_path: var_authPath, + position: var_position, + anchor_height: var_anchorHeight, + }; + } +} + +impl SseDecode for crate::api::voting::VotingVoteCommitments { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_commitments = + >::sse_decode(deserializer); + return crate::api::voting::VotingVoteCommitments { + bundle_index: var_bundleIndex, + commitments: var_commitments, + }; + } +} + +impl SseDecode for crate::api::voting::VotingVoteConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_txHash = ::sse_decode(deserializer); + let mut var_vanLeafPosition = ::sse_decode(deserializer); + let mut var_vcTreePosition = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteConfirmation { + tx_hash: var_txHash, + van_leaf_position: var_vanLeafPosition, + vc_tree_position: var_vcTreePosition, + }; + } +} + +impl SseDecode for crate::api::voting::VotingVotePayloads { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_submission = + ::sse_decode(deserializer); + let mut var_sharePayloads = + >::sse_decode(deserializer); + return crate::api::voting::VotingVotePayloads { + submission: var_submission, + share_payloads: var_sharePayloads, + }; + } +} + +impl SseDecode for crate::api::voting::VotingVoteSubmission { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_voteRoundId = ::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_vanNullifier = >::sse_decode(deserializer); + let mut var_voteAuthorityNoteNew = >::sse_decode(deserializer); + let mut var_voteCommitment = >::sse_decode(deserializer); + let mut var_proof = >::sse_decode(deserializer); + let mut var_rVpk = >::sse_decode(deserializer); + let mut var_voteAuthSig = >::sse_decode(deserializer); + let mut var_anchorHeight = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteSubmission { + vote_round_id: var_voteRoundId, + proposal_id: var_proposalId, + van_nullifier: var_vanNullifier, + vote_authority_note_new: var_voteAuthorityNoteNew, + vote_commitment: var_voteCommitment, + proof: var_proof, + r_vpk: var_rVpk, + vote_auth_sig: var_voteAuthSig, + anchor_height: var_anchorHeight, + }; + } +} + impl SseDecode for crate::api::zsa::ZsaHolding { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8860,570 +9646,929 @@ fn pde_ffi_dispatcher_primary_impl( } 35 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), 36 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), - 37 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), - 38 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), - 39 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), - 40 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), - 41 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__crate__api__sapling__download_sapling_params_impl( + 37 => wire__crate__api__voting__delegation_confirm_impl(port, ptr, rust_vec_len, data_len), + 38 => wire__crate__api__voting__delegation_prepare_impl(port, ptr, rust_vec_len, data_len), + 39 => wire__crate__api__voting__delegation_setup_impl(port, ptr, rust_vec_len, data_len), + 40 => wire__crate__api__voting__delegation_sign_and_submit_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 41 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), + 42 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), + 43 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), + 44 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), + 45 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), + 46 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__sapling__download_sapling_params_impl( port, ptr, rust_vec_len, data_len, ), - 44 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), - 45 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), - 46 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), - 48 => wire__crate__api__contacts__export_contacts_vcard_impl( + 48 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__contacts__export_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 49 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), - 50 => wire__crate__api__account__fetch_address_tx_count_impl( + 53 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__account__fetch_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 51 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), - 52 => wire__crate__api__transaction__fetch_category_amounts_impl( + 55 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), + 56 => wire__crate__api__transaction__fetch_category_amounts_impl( port, ptr, rust_vec_len, data_len, ), - 53 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( + 57 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( port, ptr, rust_vec_len, data_len, ), - 54 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), - 55 => wire__crate__api__transaction__fill_missing_tx_prices_impl( + 58 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), + 59 => wire__crate__api__transaction__fill_missing_tx_prices_impl( port, ptr, rust_vec_len, data_len, ), - 56 => wire__crate__api__contacts__find_contacts_for_address_impl( + 60 => wire__crate__api__contacts__find_contacts_for_address_impl( port, ptr, rust_vec_len, data_len, ), - 57 => wire__crate__api__frost__frost_sign_params_default_impl( + 61 => wire__crate__api__frost__frost_sign_params_default_impl( port, ptr, rust_vec_len, data_len, ), - 58 => wire__crate__api__account__generate_next_change_address_impl( + 62 => wire__crate__api__account__generate_next_change_address_impl( port, ptr, rust_vec_len, data_len, ), - 59 => { + 63 => { wire__crate__api__account__generate_next_dindex_impl(port, ptr, rust_vec_len, data_len) } - 61 => { + 65 => { wire__crate__api__account__get_account_addresses_impl(port, ptr, rust_vec_len, data_len) } - 62 => wire__crate__api__account__get_account_fingerprint_impl( + 66 => wire__crate__api__account__get_account_fingerprint_impl( port, ptr, rust_vec_len, data_len, ), - 63 => wire__crate__api__account__get_account_frost_params_impl( + 67 => wire__crate__api__account__get_account_frost_params_impl( port, ptr, rust_vec_len, data_len, ), - 64 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), - 65 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), - 66 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), - 67 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), - 68 => { + 68 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), + 69 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), + 70 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), + 71 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), + 72 => { wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) } - 69 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), - 70 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), - 71 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 72 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 73 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), - 75 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), - 76 => { + 73 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), + 75 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 76 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 77 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), + 79 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), + 80 => { wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) } - 77 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), - 78 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), - 80 => wire__crate__api__network__get_supported_vs_currencies_impl( + 81 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), + 82 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), + 84 => wire__crate__api__network__get_supported_vs_currencies_impl( port, ptr, rust_vec_len, data_len, ), - 81 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), - 83 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 84 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 85 => wire__crate__api__account__has_transparent_pub_key_impl( + 85 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), + 86 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), + 87 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 88 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__account__has_transparent_pub_key_impl( port, ptr, rust_vec_len, data_len, ), - 86 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), - 87 => wire__crate__api__contacts__import_contacts_vcard_impl( + 90 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__contacts__import_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 88 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), - 89 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), - 90 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 92 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), - 94 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), - 95 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), - 96 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), - 97 => wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len), - 98 => { + 92 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), + 93 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), + 94 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 95 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 96 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), + 98 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), + 99 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), + 100 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), + 101 => { + wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len) + } + 102 => { wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) } - 105 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 106 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 107 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 108 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 109 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 110 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 109 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 110 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 114 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 115 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 125 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 128 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 129 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 136 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 138 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 139 => { + 129 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 138 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 139 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 140 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 141 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 143 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 140 => wire__crate__api__openalias__resolve_openalias_all_impl( + 144 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 141 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 145 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 142 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 144 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 146 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 150 => { + 146 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 153 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 154 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 151 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 153 => wire__crate__api__account__show_ledger_sapling_address_impl( + 155 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 154 => wire__crate__api__account__show_ledger_transparent_address_impl( + 158 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 155 => wire__crate__api__account__sign_ledger_transaction_impl( + 159 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 156 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 159 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 161 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 163 => { + 160 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 161 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 162 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 167 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 164 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 172 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 173 => wire__crate__api__transaction__update_historical_prices_impl( + 168 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 173 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 174 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 175 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 176 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 177 => wire__crate__api__transaction__update_historical_prices_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 180 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 181 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 182 => { + wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) + } + 183 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 184 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 185 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), + 186 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +fn pde_ffi_dispatcher_sync_impl( + func_id: i32, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), + 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), + 13 => { + wire__crate__api__migrate__NoteMigration_update_height_impl(ptr, rust_vec_len, data_len) + } + 24 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), + 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), + 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), + 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), + 64 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), + 78 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), + 83 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), + 97 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), + 103 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), + 104 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), + 105 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), + 106 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), + 107 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 108 => { + wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) + } + 128 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 151 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 152 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 164 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 166 => wire__crate__api__openalias__try_validate_zcash_address_impl( + ptr, + rust_vec_len, + data_len, + ), + 172 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 178 => { + wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) + } + 179 => { + wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) + } _ => unreachable!(), } } - -fn pde_ffi_dispatcher_sync_impl( - func_id: i32, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), - 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), - 13 => { - wire__crate__api__migrate__NoteMigration_update_height_impl(ptr, rust_vec_len, data_len) - } - 24 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), - 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), - 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), - 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), - 60 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), - 74 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), - 79 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), - 93 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), - 99 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), - 100 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), - 101 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), - 102 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 103 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 104 => { - wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) - } - 124 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 147 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 148 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 160 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 162 => wire__crate__api__openalias__try_validate_zcash_address_impl( - ptr, - rust_vec_len, - data_len, - ), - 168 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 174 => { - wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) - } - 175 => { - wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) + +// Section: rust2dart + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for DartVault { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for Mempool { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for NoteMigration { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} + +impl flutter_rust_bridge::IntoIntoDart> for TransparentScanner { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Account { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.seed.into_into_dart().into_dart(), + self.passphrase.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.dindex.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.position.into_into_dart().into_dart(), + self.hidden.into_into_dart().into_dart(), + self.saved.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + self.internal.into_into_dart().into_dart(), + self.hw.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.balance.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Account {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Account +{ + fn into_into_dart(self) -> crate::api::account::Account { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::AccountUpdate { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.hidden.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::AccountUpdate +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::AccountUpdate +{ + fn into_into_dart(self) -> crate::api::account::AccountUpdate { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Addresses { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.taddr.into_into_dart().into_dart(), + self.saddr.into_into_dart().into_dart(), + self.oaddr.into_into_dart().into_dart(), + self.ua.into_into_dart().into_dart(), + self.diversifier_index.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::Addresses +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Addresses +{ + fn into_into_dart(self) -> crate::api::account::Addresses { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Category { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.is_income.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Category {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Category +{ + fn into_into_dart(self) -> crate::api::account::Category { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::coin::Coin { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.db_filepath.into_into_dart().into_dart(), + self.url.into_into_dart().into_dart(), + self.server_type.into_into_dart().into_dart(), + self.use_tor.into_into_dart().into_dart(), + self.proxy.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::coin::Coin {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::coin::Coin { + fn into_into_dart(self) -> crate::api::coin::Coin { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::contacts::Contact { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.addresses.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::contacts::Contact {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::contacts::Contact +{ + fn into_into_dart(self) -> crate::api::contacts::Contact { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::contacts::ContactMatch { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.contact.into_into_dart().into_dart(), + self.matched_address.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::contacts::ContactMatch +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::contacts::ContactMatch +{ + fn into_into_dart(self) -> crate::api::contacts::ContactMatch { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::db::DbAccountPreview { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::db::DbAccountPreview +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::db::DbAccountPreview +{ + fn into_into_dart(self) -> crate::api::db::DbAccountPreview { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::frost::DKGStatus::WaitParams => [0.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitAddresses(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::frost::DKGStatus::PublishRound1Pkg => [2.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound1Pkg => [3.into_dart()].into_dart(), + crate::api::frost::DKGStatus::PublishRound2Pkg => [4.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound2Pkg => [5.into_dart()].into_dart(), + crate::api::frost::DKGStatus::Finalize => [6.into_dart()].into_dart(), + crate::api::frost::DKGStatus::SharedAddress(field0) => { + [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } } - _ => unreachable!(), } } - -// Section: rust2dart - +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::frost::DKGStatus {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::DKGStatus +{ + fn into_into_dart(self) -> crate::api::frost::DKGStatus { + self + } +} // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::network::ExchangeRate { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.from_price.into_into_dart().into_dart(), + self.to_price.into_into_dart().into_dart(), + self.from_currency.into_into_dart().into_dart(), + self.to_currency.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for DartVault { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::network::ExchangeRate +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::network::ExchangeRate +{ + fn into_into_dart(self) -> crate::api::network::ExchangeRate { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::account::Folder { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for Mempool { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Folder {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Folder +{ + fn into_into_dart(self) -> crate::api::account::Folder { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::FrostParams { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.n.into_into_dart().into_dart(), + self.t.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::FrostParams +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::FrostParams +{ + fn into_into_dart(self) -> crate::api::account::FrostParams { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::frost::FrostSignParams { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.account.into_into_dart().into_dart(), + self.coordinator.into_into_dart().into_dart(), + self.funding_account.into_into_dart().into_dart(), + ] + .into_dart() } } - -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() - } +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::frost::FrostSignParams +{ } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for NoteMigration { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::FrostSignParams +{ + fn into_into_dart(self) -> crate::api::frost::FrostSignParams { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::init::LogMessage { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.level.into_into_dart().into_dart(), + self.message.into_into_dart().into_dart(), + self.span.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::init::LogMessage {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::init::LogMessage { -} - -impl flutter_rust_bridge::IntoIntoDart> for TransparentScanner { - fn into_into_dart(self) -> FrbWrapper { - self.into() + fn into_into_dart(self) -> crate::api::init::LogMessage { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Account { +impl flutter_rust_bridge::IntoDart for crate::api::network::LWDInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.coin.into_into_dart().into_dart(), - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.seed.into_into_dart().into_dart(), - self.passphrase.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), - self.dindex.into_into_dart().into_dart(), - self.icon.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.position.into_into_dart().into_dart(), - self.hidden.into_into_dart().into_dart(), - self.saved.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), - self.internal.into_into_dart().into_dart(), - self.hw.into_into_dart().into_dart(), + self.url.into_into_dart().into_dart(), + self.is_tor.into_into_dart().into_dart(), self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.balance.into_into_dart().into_dart(), + self.status.into_into_dart().into_dart(), + self.uptime.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.ping.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Account {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Account +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::network::LWDInfo {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::network::LWDInfo { - fn into_into_dart(self) -> crate::api::account::Account { + fn into_into_dart(self) -> crate::api::network::LWDInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::AccountUpdate { +impl flutter_rust_bridge::IntoDart for crate::api::account::Memo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.coin.into_into_dart().into_dart(), self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.icon.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.hidden.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), + self.id_tx.into_into_dart().into_dart(), + self.id_note.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.vout.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.is_user_memo.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::AccountUpdate -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::AccountUpdate -{ - fn into_into_dart(self) -> crate::api::account::AccountUpdate { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Memo {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Memo { + fn into_into_dart(self) -> crate::api::account::Memo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Addresses { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoCell { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.taddr.into_into_dart().into_dart(), - self.saddr.into_into_dart().into_dart(), - self.oaddr.into_into_dart().into_dart(), - self.ua.into_into_dart().into_dart(), - self.diversifier_index.into_into_dart().into_dart(), + self.cell_type.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::Addresses +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoCell {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoCell { + fn into_into_dart(self) -> crate::api::plugin::MemoCell { + self + } } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Addresses +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoRow { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [self.cells.into_into_dart().into_dart()].into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoRow {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoRow { - fn into_into_dart(self) -> crate::api::account::Addresses { + fn into_into_dart(self) -> crate::api::plugin::MemoRow { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Category { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoSection { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.is_income.into_into_dart().into_dart(), + self.title.into_into_dart().into_dart(), + self.headers.into_into_dart().into_dart(), + self.rows.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Category {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Category +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::plugin::MemoSection { - fn into_into_dart(self) -> crate::api::account::Category { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoSection +{ + fn into_into_dart(self) -> crate::api::plugin::MemoSection { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::coin::Coin { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolAmount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.coin.into_into_dart().into_dart(), self.account.into_into_dart().into_dart(), - self.db_filepath.into_into_dart().into_dart(), - self.url.into_into_dart().into_dart(), - self.server_type.into_into_dart().into_dart(), - self.use_tor.into_into_dart().into_dart(), - self.proxy.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::coin::Coin {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::coin::Coin { - fn into_into_dart(self) -> crate::api::coin::Coin { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::mempool::MempoolAmount +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolAmount +{ + fn into_into_dart(self) -> crate::api::mempool::MempoolAmount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::contacts::Contact { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolMsg { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.addresses.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), - ] - .into_dart() + match self { + crate::api::mempool::MempoolMsg::BlockHeight(field0) => { + [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::mempool::MempoolMsg::TxId(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::contacts::Contact {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::contacts::Contact +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::mempool::MempoolMsg { - fn into_into_dart(self) -> crate::api::contacts::Contact { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolMsg +{ + fn into_into_dart(self) -> crate::api::mempool::MempoolMsg { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::contacts::ContactMatch { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolNote { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.contact.into_into_dart().into_dart(), - self.matched_address.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.diversifier.into_into_dart().into_dart(), + self.diversifier_index.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::contacts::ContactMatch + for crate::api::mempool::MempoolNote { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::contacts::ContactMatch +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolNote { - fn into_into_dart(self) -> crate::api::contacts::ContactMatch { + fn into_into_dart(self) -> crate::api::mempool::MempoolNote { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::db::DbAccountPreview { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolTx { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), + self.txid.into_into_dart().into_dart(), + self.amounts.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + self.size.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::db::DbAccountPreview + for crate::api::mempool::MempoolTx { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::db::DbAccountPreview +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolTx { - fn into_into_dart(self) -> crate::api::db::DbAccountPreview { + fn into_into_dart(self) -> crate::api::mempool::MempoolTx { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { +impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationEvent { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { match self { - crate::api::frost::DKGStatus::WaitParams => [0.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitAddresses(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + crate::api::migrate::MigrationEvent::SplitComplete { fee } => { + [0.into_dart(), fee.into_into_dart().into_dart()].into_dart() + } + crate::api::migrate::MigrationEvent::MigrateComplete { fee } => { + [1.into_dart(), fee.into_into_dart().into_dart()].into_dart() } - crate::api::frost::DKGStatus::PublishRound1Pkg => [2.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound1Pkg => [3.into_dart()].into_dart(), - crate::api::frost::DKGStatus::PublishRound2Pkg => [4.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound2Pkg => [5.into_dart()].into_dart(), - crate::api::frost::DKGStatus::Finalize => [6.into_dart()].into_dart(), - crate::api::frost::DKGStatus::SharedAddress(field0) => { - [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() + crate::api::migrate::MigrationEvent::Complete => [2.into_dart()].into_dart(), + crate::api::migrate::MigrationEvent::NothingToDo => [3.into_dart()].into_dart(), + crate::api::migrate::MigrationEvent::Error { message } => { + [4.into_dart(), message.into_into_dart().into_dart()].into_dart() } _ => { unimplemented!(""); @@ -9431,998 +10576,980 @@ impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { } } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::frost::DKGStatus {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::DKGStatus +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::migrate::MigrationEvent { - fn into_into_dart(self) -> crate::api::frost::DKGStatus { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::migrate::MigrationEvent +{ + fn into_into_dart(self) -> crate::api::migrate::MigrationEvent { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::network::ExchangeRate { +impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.from_price.into_into_dart().into_dart(), - self.to_price.into_into_dart().into_dart(), - self.from_currency.into_into_dart().into_dart(), - self.to_currency.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), + self.split_fees.into_into_dart().into_dart(), + self.migrate_fees.into_into_dart().into_dart(), + self.total_fees.into_into_dart().into_dart(), + self.sd_notes_count.into_into_dart().into_dart(), + self.non_sd_notes_count.into_into_dart().into_dart(), + self.ironwood_sd_count.into_into_dart().into_dart(), + self.progress.into_into_dart().into_dart(), + self.next_action.into_into_dart().into_dart(), + self.work_summary.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::network::ExchangeRate + for crate::api::migrate::MigrationStatus { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::network::ExchangeRate +impl flutter_rust_bridge::IntoIntoDart + for crate::api::migrate::MigrationStatus { - fn into_into_dart(self) -> crate::api::network::ExchangeRate { + fn into_into_dart(self) -> crate::api::migrate::MigrationStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Folder { +impl flutter_rust_bridge::IntoDart for crate::api::account::NewAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), self.name.into_into_dart().into_dart(), + self.restore.into_into_dart().into_dart(), + self.key.into_into_dart().into_dart(), + self.passphrase.into_into_dart().into_dart(), + self.fingerprint.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.pools.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.internal.into_into_dart().into_dart(), + self.ledger.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Folder {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Folder +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::NewAccount { - fn into_into_dart(self) -> crate::api::account::Folder { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::NewAccount +{ + fn into_into_dart(self) -> crate::api::account::NewAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::FrostParams { +impl flutter_rust_bridge::IntoDart for crate::api::openalias::OpenAliasResolution { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.n.into_into_dart().into_dart(), - self.t.into_into_dart().into_dart(), + self.recipients.into_into_dart().into_dart(), + self.dnssec_status.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::FrostParams + for crate::api::openalias::OpenAliasResolution { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::FrostParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::openalias::OpenAliasResolution { - fn into_into_dart(self) -> crate::api::account::FrostParams { + fn into_into_dart(self) -> crate::api::openalias::OpenAliasResolution { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::FrostSignParams { +impl flutter_rust_bridge::IntoDart for crate::api::pay::PaymentOptions { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.coordinator.into_into_dart().into_dart(), - self.funding_account.into_into_dart().into_dart(), + self.src_pools.into_into_dart().into_dart(), + self.recipient_pays_fee.into_into_dart().into_dart(), + self.smart_transparent.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::frost::FrostSignParams + for crate::api::pay::PaymentOptions { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::FrostSignParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::PaymentOptions { - fn into_into_dart(self) -> crate::api::frost::FrostSignParams { + fn into_into_dart(self) -> crate::api::pay::PaymentOptions { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::init::LogMessage { +impl flutter_rust_bridge::IntoDart for crate::api::pay::PcztPackage { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.level.into_into_dart().into_dart(), - self.message.into_into_dart().into_dart(), - self.span.into_into_dart().into_dart(), + self.pczt.into_into_dart().into_dart(), + self.n_spends.into_into_dart().into_dart(), + self.sapling_indices.into_into_dart().into_dart(), + self.orchard_indices.into_into_dart().into_dart(), + self.ironwood_indices.into_into_dart().into_dart(), + self.can_sign.into_into_dart().into_dart(), + self.can_broadcast.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.is_issuance.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::init::LogMessage {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::init::LogMessage +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::PcztPackage {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::PcztPackage { - fn into_into_dart(self) -> crate::api::init::LogMessage { + fn into_into_dart(self) -> crate::api::pay::PcztPackage { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::network::LWDInfo { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::PluginInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.url.into_into_dart().into_dart(), - self.is_tor.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.status.into_into_dart().into_dart(), - self.uptime.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), self.version.into_into_dart().into_dart(), - self.ping.into_into_dart().into_dart(), + self.author.into_into_dart().into_dart(), + self.description.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + self.types.into_into_dart().into_dart(), + self.memo_prefixes.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::network::LWDInfo {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::network::LWDInfo +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::plugin::PluginInfo { - fn into_into_dart(self) -> crate::api::network::LWDInfo { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Memo { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.id.into_into_dart().into_dart(), - self.id_tx.into_into_dart().into_dart(), - self.id_note.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.vout.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.is_user_memo.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Memo {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Memo { - fn into_into_dart(self) -> crate::api::account::Memo { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoCell { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.cell_type.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - ] - .into_dart() - } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoCell {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoCell +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::PluginInfo { - fn into_into_dart(self) -> crate::api::plugin::MemoCell { + fn into_into_dart(self) -> crate::api::plugin::PluginInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoRow { +impl flutter_rust_bridge::IntoDart for crate::api::sync::PoolBalance { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.cells.into_into_dart().into_dart()].into_dart() + [self.0.into_into_dart().into_dart()].into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoRow {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoRow +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::sync::PoolBalance {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sync::PoolBalance { - fn into_into_dart(self) -> crate::api::plugin::MemoRow { + fn into_into_dart(self) -> crate::api::sync::PoolBalance { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoSection { +impl flutter_rust_bridge::IntoDart for crate::api::raptor::RaptorQParams { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.title.into_into_dart().into_dart(), - self.headers.into_into_dart().into_dart(), - self.rows.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.ec_level.into_into_dart().into_dart(), + self.repair.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::plugin::MemoSection + for crate::api::raptor::RaptorQParams { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoSection +impl flutter_rust_bridge::IntoIntoDart + for crate::api::raptor::RaptorQParams { - fn into_into_dart(self) -> crate::api::plugin::MemoSection { + fn into_into_dart(self) -> crate::api::raptor::RaptorQParams { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolAmount { +impl flutter_rust_bridge::IntoDart for crate::api::openalias::RawOpenAliasResolution { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), + self.records.into_into_dart().into_dart(), + self.dnssec_status.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolAmount -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolAmount -{ - fn into_into_dart(self) -> crate::api::mempool::MempoolAmount { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolMsg { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::mempool::MempoolMsg::BlockHeight(field0) => { - [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crate::api::mempool::MempoolMsg::TxId(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolMsg + for crate::api::openalias::RawOpenAliasResolution { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolMsg +impl flutter_rust_bridge::IntoIntoDart + for crate::api::openalias::RawOpenAliasResolution { - fn into_into_dart(self) -> crate::api::mempool::MempoolMsg { + fn into_into_dart(self) -> crate::api::openalias::RawOpenAliasResolution { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolNote { +impl flutter_rust_bridge::IntoDart for crate::api::account::Receivers { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.diversifier.into_into_dart().into_dart(), - self.diversifier_index.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), + self.taddr.into_into_dart().into_dart(), + self.saddr.into_into_dart().into_dart(), + self.oaddr.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolNote + for crate::api::account::Receivers { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolNote +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Receivers { - fn into_into_dart(self) -> crate::api::mempool::MempoolNote { + fn into_into_dart(self) -> crate::api::account::Receivers { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolTx { +impl flutter_rust_bridge::IntoDart for crate::pay::Recipient { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.txid.into_into_dart().into_dart(), - self.amounts.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), - self.size.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.pools.into_into_dart().into_dart(), + self.user_memo.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.asset_base.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolTx -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolTx -{ - fn into_into_dart(self) -> crate::api::mempool::MempoolTx { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::Recipient {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::Recipient { + fn into_into_dart(self) -> crate::pay::Recipient { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationEvent { +impl flutter_rust_bridge::IntoDart for crate::api::vault::RestoredAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::migrate::MigrationEvent::SplitComplete { fee } => { - [0.into_dart(), fee.into_into_dart().into_dart()].into_dart() - } - crate::api::migrate::MigrationEvent::MigrateComplete { fee } => { - [1.into_dart(), fee.into_into_dart().into_dart()].into_dart() - } - crate::api::migrate::MigrationEvent::Complete => [2.into_dart()].into_dart(), - crate::api::migrate::MigrationEvent::NothingToDo => [3.into_dart()].into_dart(), - crate::api::migrate::MigrationEvent::Error { message } => { - [4.into_dart(), message.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.timestamp.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.seed.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.birth_height.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::migrate::MigrationEvent + for crate::api::vault::RestoredAccount { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::migrate::MigrationEvent +impl flutter_rust_bridge::IntoIntoDart + for crate::api::vault::RestoredAccount { - fn into_into_dart(self) -> crate::api::migrate::MigrationEvent { + fn into_into_dart(self) -> crate::api::vault::RestoredAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationStatus { +impl flutter_rust_bridge::IntoDart for crate::api::sapling::SaplingParamsStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.phase.into_into_dart().into_dart(), - self.split_fees.into_into_dart().into_dart(), - self.migrate_fees.into_into_dart().into_dart(), - self.total_fees.into_into_dart().into_dart(), - self.sd_notes_count.into_into_dart().into_dart(), - self.non_sd_notes_count.into_into_dart().into_dart(), - self.ironwood_sd_count.into_into_dart().into_dart(), - self.progress.into_into_dart().into_dart(), - self.next_action.into_into_dart().into_dart(), - self.work_summary.into_into_dart().into_dart(), - ] - .into_dart() + [self.downloaded.into_into_dart().into_dart()].into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::migrate::MigrationStatus + for crate::api::sapling::SaplingParamsStatus { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::migrate::MigrationStatus +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sapling::SaplingParamsStatus { - fn into_into_dart(self) -> crate::api::migrate::MigrationStatus { + fn into_into_dart(self) -> crate::api::sapling::SaplingParamsStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::NewAccount { +impl flutter_rust_bridge::IntoDart for crate::api::account::Seed { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.icon.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.restore.into_into_dart().into_dart(), - self.key.into_into_dart().into_dart(), - self.passphrase.into_into_dart().into_dart(), - self.fingerprint.into_into_dart().into_dart(), + self.mnemonic.into_into_dart().into_dart(), + self.phrase.into_into_dart().into_dart(), self.aindex.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.pools.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.internal.into_into_dart().into_dart(), - self.ledger.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::NewAccount -{ +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Seed {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Seed { + fn into_into_dart(self) -> crate::api::account::Seed { + self + } } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::NewAccount +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::pay::SigningEvent { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::pay::SigningEvent::Progress(field0) => { + [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::pay::SigningEvent::Result(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::SigningEvent {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::SigningEvent { - fn into_into_dart(self) -> crate::api::account::NewAccount { + fn into_into_dart(self) -> crate::api::pay::SigningEvent { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::openalias::OpenAliasResolution { +impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.recipients.into_into_dart().into_dart(), - self.dnssec_status.into_into_dart().into_dart(), - ] - .into_dart() + match self { + crate::api::frost::SigningStatus::SendingCommitment => [0.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForCommitments => [1.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SendingSigningPackage => [2.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForSigningPackage => { + [3.into_dart()].into_dart() + } + crate::api::frost::SigningStatus::SendingSignatureShare => [4.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SigningCompleted => [5.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForSignatureShares => { + [6.into_dart()].into_dart() + } + crate::api::frost::SigningStatus::PreparingTransaction => [7.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SendingTransaction => [8.into_dart()].into_dart(), + crate::api::frost::SigningStatus::TransactionSent(field0) => { + [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::openalias::OpenAliasResolution + for crate::api::frost::SigningStatus { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::openalias::OpenAliasResolution +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::SigningStatus { - fn into_into_dart(self) -> crate::api::openalias::OpenAliasResolution { + fn into_into_dart(self) -> crate::api::frost::SigningStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::PaymentOptions { +impl flutter_rust_bridge::IntoDart for crate::io::SyncHeight { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.src_pools.into_into_dart().into_dart(), - self.recipient_pays_fee.into_into_dart().into_dart(), - self.smart_transparent.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::pay::PaymentOptions -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::PaymentOptions -{ - fn into_into_dart(self) -> crate::api::pay::PaymentOptions { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::io::SyncHeight {} +impl flutter_rust_bridge::IntoIntoDart for crate::io::SyncHeight { + fn into_into_dart(self) -> crate::io::SyncHeight { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::PcztPackage { +impl flutter_rust_bridge::IntoDart for crate::api::sync::SyncProgress { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pczt.into_into_dart().into_dart(), - self.n_spends.into_into_dart().into_dart(), - self.sapling_indices.into_into_dart().into_dart(), - self.orchard_indices.into_into_dart().into_dart(), - self.ironwood_indices.into_into_dart().into_dart(), - self.can_sign.into_into_dart().into_dart(), - self.can_broadcast.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.is_issuance.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::PcztPackage {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::PcztPackage +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::sync::SyncProgress { - fn into_into_dart(self) -> crate::api::pay::PcztPackage { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sync::SyncProgress +{ + fn into_into_dart(self) -> crate::api::sync::SyncProgress { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::PluginInfo { +impl flutter_rust_bridge::IntoDart for crate::api::account::TAddressTxCount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.version.into_into_dart().into_dart(), - self.author.into_into_dart().into_dart(), - self.description.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), - self.types.into_into_dart().into_dart(), - self.memo_prefixes.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.dindex.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.tx_count.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::plugin::PluginInfo + for crate::api::account::TAddressTxCount { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::PluginInfo +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TAddressTxCount { - fn into_into_dart(self) -> crate::api::plugin::PluginInfo { + fn into_into_dart(self) -> crate::api::account::TAddressTxCount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sync::PoolBalance { +impl flutter_rust_bridge::IntoDart for crate::api::account::Tx { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.0.into_into_dart().into_dart()].into_dart() + [ + self.id.into_into_dart().into_dart(), + self.txid.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.tpe.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.zsa_value.into_into_dart().into_dart(), + self.asset_id.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.is_user_memo.into_into_dart().into_dart(), + self.contact_name.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::sync::PoolBalance {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sync::PoolBalance -{ - fn into_into_dart(self) -> crate::api::sync::PoolBalance { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Tx {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Tx { + fn into_into_dart(self) -> crate::api::account::Tx { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::raptor::RaptorQParams { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.version.into_into_dart().into_dart(), - self.ec_level.into_into_dart().into_dart(), - self.repair.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.txid.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + self.spends.into_into_dart().into_dart(), + self.outputs.into_into_dart().into_dart(), + self.memos.into_into_dart().into_dart(), + self.user_memo.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::raptor::RaptorQParams + for crate::api::account::TxAccount { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::raptor::RaptorQParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxAccount { - fn into_into_dart(self) -> crate::api::raptor::RaptorQParams { + fn into_into_dart(self) -> crate::api::account::TxAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::openalias::RawOpenAliasResolution { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxMemo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.records.into_into_dart().into_dart(), - self.dnssec_status.into_into_dart().into_dart(), + self.note.into_into_dart().into_dart(), + self.output.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::openalias::RawOpenAliasResolution -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::openalias::RawOpenAliasResolution +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxMemo {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxMemo { - fn into_into_dart(self) -> crate::api::openalias::RawOpenAliasResolution { + fn into_into_dart(self) -> crate::api::account::TxMemo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Receivers { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxNote { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.taddr.into_into_dart().into_dart(), - self.saddr.into_into_dart().into_dart(), - self.oaddr.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.tx.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.diversifier.into_into_dart().into_dart(), + self.diversifier_index.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.locked.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.id_asset.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::Receivers -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Receivers +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxNote {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxNote { - fn into_into_dart(self) -> crate::api::account::Receivers { + fn into_into_dart(self) -> crate::api::account::TxNote { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::Recipient { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxOutput { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), self.address.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.pools.into_into_dart().into_dart(), - self.user_memo.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.asset_base.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.contact_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::Recipient {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::Recipient { - fn into_into_dart(self) -> crate::pay::Recipient { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxOutput {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxOutput +{ + fn into_into_dart(self) -> crate::api::account::TxOutput { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::vault::RestoredAccount { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlan { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.timestamp.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.seed.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.birth_height.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.inputs.into_into_dart().into_dart(), + self.outputs.into_into_dart().into_dart(), + self.fee.into_into_dart().into_dart(), + self.can_sign.into_into_dart().into_dart(), + self.can_broadcast.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::vault::RestoredAccount -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::vault::RestoredAccount -{ - fn into_into_dart(self) -> crate::api::vault::RestoredAccount { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlan {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlan { + fn into_into_dart(self) -> crate::pay::TxPlan { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sapling::SaplingParamsStatus { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanIn { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.downloaded.into_into_dart().into_dart()].into_dart() + [ + self.pool.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::sapling::SaplingParamsStatus -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sapling::SaplingParamsStatus -{ - fn into_into_dart(self) -> crate::api::sapling::SaplingParamsStatus { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanIn {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanIn { + fn into_into_dart(self) -> crate::pay::TxPlanIn { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Seed { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanOut { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.mnemonic.into_into_dart().into_dart(), - self.phrase.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Seed {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Seed { - fn into_into_dart(self) -> crate::api::account::Seed { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanOut {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanOut { + fn into_into_dart(self) -> crate::pay::TxPlanOut { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::SigningEvent { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxSpend { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::pay::SigningEvent::Progress(field0) => { - [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crate::api::pay::SigningEvent::Result(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.id_asset.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::SigningEvent {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::SigningEvent +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxSpend {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxSpend { - fn into_into_dart(self) -> crate::api::pay::SigningEvent { + fn into_into_dart(self) -> crate::api::account::TxSpend { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationConfirmation { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::frost::SigningStatus::SendingCommitment => [0.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForCommitments => [1.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SendingSigningPackage => [2.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForSigningPackage => { - [3.into_dart()].into_dart() - } - crate::api::frost::SigningStatus::SendingSignatureShare => [4.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SigningCompleted => [5.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForSignatureShares => { - [6.into_dart()].into_dart() - } - crate::api::frost::SigningStatus::PreparingTransaction => [7.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SendingTransaction => [8.into_dart()].into_dart(), - crate::api::frost::SigningStatus::TransactionSent(field0) => { - [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.tx_hash.into_into_dart().into_dart(), + self.van_leaf_position.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::frost::SigningStatus + for crate::api::voting::VotingDelegationConfirmation { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::SigningStatus +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationConfirmation { - fn into_into_dart(self) -> crate::api::frost::SigningStatus { + fn into_into_dart(self) -> crate::api::voting::VotingDelegationConfirmation { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::io::SyncHeight { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSetup { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), + self.pczt_bytes.into_into_dart().into_dart(), + self.pczt_sighash.into_into_dart().into_dart(), + self.rk.into_into_dart().into_dart(), + self.action_index.into_into_dart().into_dart(), + self.action_bytes.into_into_dart().into_dart(), + self.tx1_effects.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::io::SyncHeight {} -impl flutter_rust_bridge::IntoIntoDart for crate::io::SyncHeight { - fn into_into_dart(self) -> crate::io::SyncHeight { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingDelegationSetup +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationSetup +{ + fn into_into_dart(self) -> crate::api::voting::VotingDelegationSetup { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sync::SyncProgress { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSubmission { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), + self.proof.into_into_dart().into_dart(), + self.rk.into_into_dart().into_dart(), + self.nf_signed.into_into_dart().into_dart(), + self.cmx_new.into_into_dart().into_dart(), + self.gov_comm.into_into_dart().into_dart(), + self.gov_nullifiers.into_into_dart().into_dart(), + self.alpha.into_into_dart().into_dart(), + self.vote_round_id.into_into_dart().into_dart(), + self.spend_auth_sig.into_into_dart().into_dart(), + self.sighash.into_into_dart().into_dart(), + self.tx1_effects.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::sync::SyncProgress + for crate::api::voting::VotingDelegationSubmission { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sync::SyncProgress +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationSubmission { - fn into_into_dart(self) -> crate::api::sync::SyncProgress { + fn into_into_dart(self) -> crate::api::voting::VotingDelegationSubmission { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TAddressTxCount { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingEncryptedShare { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.dindex.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.tx_count.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), + self.c1.into_into_dart().into_dart(), + self.c2.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::TAddressTxCount + for crate::api::voting::VotingEncryptedShare { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TAddressTxCount +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingEncryptedShare { - fn into_into_dart(self) -> crate::api::account::TAddressTxCount { + fn into_into_dart(self) -> crate::api::voting::VotingEncryptedShare { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Tx { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPirLayout { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.txid.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.tpe.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.zsa_value.into_into_dart().into_dart(), - self.asset_id.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.is_user_memo.into_into_dart().into_dart(), - self.contact_name.into_into_dart().into_dart(), + self.pir_depth.into_into_dart().into_dart(), + self.tier0_layers.into_into_dart().into_dart(), + self.tier1_layers.into_into_dart().into_dart(), + self.poly_len.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Tx {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Tx { - fn into_into_dart(self) -> crate::api::account::Tx { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingPirLayout +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingPirLayout +{ + fn into_into_dart(self) -> crate::api::voting::VotingPirLayout { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxAccount { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPreparedInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.account.into_into_dart().into_dart(), - self.txid.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), - self.spends.into_into_dart().into_dart(), - self.outputs.into_into_dart().into_dart(), - self.memos.into_into_dart().into_dart(), - self.user_memo.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.eligible_weight_zatoshi.into_into_dart().into_dart(), + self.delegated_weight_zatoshi.into_into_dart().into_dart(), + self.round_name.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::TxAccount + for crate::api::voting::VotingPreparedInfo { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxAccount +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingPreparedInfo { - fn into_into_dart(self) -> crate::api::account::TxAccount { + fn into_into_dart(self) -> crate::api::voting::VotingPreparedInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxMemo { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSharePayload { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.note.into_into_dart().into_dart(), - self.output.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), + self.shares_hash.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.vote_decision.into_into_dart().into_dart(), + self.enc_share.into_into_dart().into_dart(), + self.tree_position.into_into_dart().into_dart(), + self.all_enc_shares.into_into_dart().into_dart(), + self.share_comms.into_into_dart().into_dart(), + self.primary_blind.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxMemo {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxMemo +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingSharePayload { - fn into_into_dart(self) -> crate::api::account::TxMemo { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingSharePayload +{ + fn into_into_dart(self) -> crate::api::voting::VotingSharePayload { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxNote { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSignedVoteCommitment { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.tx.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.diversifier.into_into_dart().into_dart(), - self.diversifier_index.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.locked.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.id_asset.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.choice.into_into_dart().into_dart(), + self.vote_round_id.into_into_dart().into_dart(), + self.van_nullifier.into_into_dart().into_dart(), + self.vote_authority_note_new.into_into_dart().into_dart(), + self.vote_commitment.into_into_dart().into_dart(), + self.proof.into_into_dart().into_dart(), + self.anchor_height.into_into_dart().into_dart(), + self.r_vpk.into_into_dart().into_dart(), + self.vote_auth_sig.into_into_dart().into_dart(), + self.commitment_bundle_json.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxNote {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxNote +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingSignedVoteCommitment { - fn into_into_dart(self) -> crate::api::account::TxNote { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingSignedVoteCommitment +{ + fn into_into_dart(self) -> crate::api::voting::VotingSignedVoteCommitment { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxOutput { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVanWitness { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.contact_name.into_into_dart().into_dart(), + self.auth_path.into_into_dart().into_dart(), + self.position.into_into_dart().into_dart(), + self.anchor_height.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxOutput {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxOutput +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVanWitness { - fn into_into_dart(self) -> crate::api::account::TxOutput { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVanWitness +{ + fn into_into_dart(self) -> crate::api::voting::VotingVanWitness { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlan { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteCommitments { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.height.into_into_dart().into_dart(), - self.inputs.into_into_dart().into_dart(), - self.outputs.into_into_dart().into_dart(), - self.fee.into_into_dart().into_dart(), - self.can_sign.into_into_dart().into_dart(), - self.can_broadcast.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.commitments.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlan {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlan { - fn into_into_dart(self) -> crate::pay::TxPlan { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVoteCommitments +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVoteCommitments +{ + fn into_into_dart(self) -> crate::api::voting::VotingVoteCommitments { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanIn { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteConfirmation { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.tx_hash.into_into_dart().into_dart(), + self.van_leaf_position.into_into_dart().into_dart(), + self.vc_tree_position.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanIn {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanIn { - fn into_into_dart(self) -> crate::pay::TxPlanIn { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVoteConfirmation +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVoteConfirmation +{ + fn into_into_dart(self) -> crate::api::voting::VotingVoteConfirmation { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanOut { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVotePayloads { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.submission.into_into_dart().into_dart(), + self.share_payloads.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanOut {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanOut { - fn into_into_dart(self) -> crate::pay::TxPlanOut { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVotePayloads +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVotePayloads +{ + fn into_into_dart(self) -> crate::api::voting::VotingVotePayloads { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxSpend { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteSubmission { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.id_asset.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), + self.vote_round_id.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.van_nullifier.into_into_dart().into_dart(), + self.vote_authority_note_new.into_into_dart().into_dart(), + self.vote_commitment.into_into_dart().into_dart(), + self.proof.into_into_dart().into_dart(), + self.r_vpk.into_into_dart().into_dart(), + self.vote_auth_sig.into_into_dart().into_dart(), + self.anchor_height.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxSpend {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxSpend +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVoteSubmission { - fn into_into_dart(self) -> crate::api::account::TxSpend { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVoteSubmission +{ + fn into_into_dart(self) -> crate::api::voting::VotingVoteSubmission { self } } @@ -11145,6 +12272,36 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -11873,6 +13030,159 @@ impl SseEncode for [usize; 4] { } } +impl SseEncode for crate::api::voting::VotingDelegationConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.tx_hash, serializer); + ::sse_encode(self.van_leaf_position, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingDelegationSetup { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.pczt_bytes, serializer); + >::sse_encode(self.pczt_sighash, serializer); + >::sse_encode(self.rk, serializer); + ::sse_encode(self.action_index, serializer); + >::sse_encode(self.action_bytes, serializer); + >::sse_encode(self.tx1_effects, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingDelegationSubmission { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.proof, serializer); + >::sse_encode(self.rk, serializer); + >::sse_encode(self.nf_signed, serializer); + >::sse_encode(self.cmx_new, serializer); + >::sse_encode(self.gov_comm, serializer); + >>::sse_encode(self.gov_nullifiers, serializer); + >::sse_encode(self.alpha, serializer); + ::sse_encode(self.vote_round_id, serializer); + >::sse_encode(self.spend_auth_sig, serializer); + >::sse_encode(self.sighash, serializer); + >::sse_encode(self.tx1_effects, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingEncryptedShare { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.c1, serializer); + >::sse_encode(self.c2, serializer); + ::sse_encode(self.share_index, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingPirLayout { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.pir_depth, serializer); + ::sse_encode(self.tier0_layers, serializer); + ::sse_encode(self.tier1_layers, serializer); + ::sse_encode(self.poly_len, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingPreparedInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.eligible_weight_zatoshi, serializer); + ::sse_encode(self.delegated_weight_zatoshi, serializer); + ::sse_encode(self.round_name, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingSharePayload { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.shares_hash, serializer); + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.vote_decision, serializer); + ::sse_encode(self.enc_share, serializer); + ::sse_encode(self.tree_position, serializer); + >::sse_encode( + self.all_enc_shares, + serializer, + ); + >>::sse_encode(self.share_comms, serializer); + >::sse_encode(self.primary_blind, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingSignedVoteCommitment { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.choice, serializer); + ::sse_encode(self.vote_round_id, serializer); + >::sse_encode(self.van_nullifier, serializer); + >::sse_encode(self.vote_authority_note_new, serializer); + >::sse_encode(self.vote_commitment, serializer); + >::sse_encode(self.proof, serializer); + ::sse_encode(self.anchor_height, serializer); + >::sse_encode(self.r_vpk, serializer); + >::sse_encode(self.vote_auth_sig, serializer); + ::sse_encode(self.commitment_bundle_json, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingVanWitness { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(self.auth_path, serializer); + ::sse_encode(self.position, serializer); + ::sse_encode(self.anchor_height, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingVoteCommitments { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.bundle_index, serializer); + >::sse_encode( + self.commitments, + serializer, + ); + } +} + +impl SseEncode for crate::api::voting::VotingVoteConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.tx_hash, serializer); + ::sse_encode(self.van_leaf_position, serializer); + ::sse_encode(self.vc_tree_position, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingVotePayloads { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.submission, serializer); + >::sse_encode(self.share_payloads, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingVoteSubmission { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.vote_round_id, serializer); + ::sse_encode(self.proposal_id, serializer); + >::sse_encode(self.van_nullifier, serializer); + >::sse_encode(self.vote_authority_note_new, serializer); + >::sse_encode(self.vote_commitment, serializer); + >::sse_encode(self.proof, serializer); + >::sse_encode(self.r_vpk, serializer); + >::sse_encode(self.vote_auth_sig, serializer); + ::sse_encode(self.anchor_height, serializer); + } +} + impl SseEncode for crate::api::zsa::ZsaHolding { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 46c224bd6..f83617c7e 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -33,6 +33,7 @@ pub mod plugin; pub mod recover; pub mod sync; pub mod vault; +pub mod voting; pub mod warp; pub type Hash32 = [u8; 32]; diff --git a/rust/src/voting.rs b/rust/src/voting.rs new file mode 100644 index 000000000..d2f948201 --- /dev/null +++ b/rust/src/voting.rs @@ -0,0 +1,550 @@ +//! Zcash shielded voting (ZIP 262): delegation and vote casting. +//! +//! This module integrates the patched `zcash_voting` fork with zkool's own +//! wallet database. The fork's `VotingDb` is embedded in zkool's SQLCipher +//! pool (`voting_*` tables) and all note/witness/seed material comes from +//! zkool's own storage — no `zcash_client_sqlite::WalletDb` is involved. +//! +//! The delegation bundle is broadcast to the vote chain (never to the Zcash +//! network); `zcash_voting::confirmation` turns chain events back into voting +//! DB state before votes can be cast. + +use std::collections::HashMap; +use std::str::FromStr; +use std::sync::{Arc, Mutex, OnceLock}; + +use anyhow::{anyhow, ensure, Context as _, Result}; +use bip39::Mnemonic; +use halo2_proofs::pasta::group::ff::PrimeField as _; +use rand_core::OsRng; +use sqlx::{Row as _, SqliteConnection, SqlitePool}; +use zip32::AccountId; + +use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey}; +use zcash_voting::prelude::{ + confirm_delegation_submission, confirm_vote_submission, generate_random_voting_hotkey, + BundlePolicy, CommittedVote, DelegationConfirmation, DelegationKeys, DelegationSigningRequest, + DelegationSubmission, DraftVote, NoopProgressReporter, NoteInfo, + PrepareDelegationBundleWithInputsParams, PreparedDelegationBundle, PreparedSigner, SharePayload, + SignedVoteCommitments, TxEvent, VanWitness, VoteConfirmation, VoteSigner, VoteSubmission, + VotingDb, VotingHotkey, WitnessData, +}; +use zcash_voting::{Network as VotingNetwork, VotingRoundParams}; + +use crate::api::coin::Network as WalletNetwork; +use crate::warp::hasher::{empty_roots, OrchardHasher}; + +/// Prop key holding the hex-encoded voting hotkey stored secret. +pub const VOTING_HOTKEY_PROP: &str = "voting_hotkey_secret"; + +/// Maps zkool's wallet network to the voting crate's network selector. +pub fn voting_network(network: &WalletNetwork) -> Result { + match network { + WalletNetwork::Main => Ok(VotingNetwork::Mainnet), + WalletNetwork::Test => Ok(VotingNetwork::Testnet), + WalletNetwork::Regtest(_) => Ok(VotingNetwork::Regtest), + WalletNetwork::ZsaRegtest(_) => { + Err(anyhow!("voting is not supported on the ZSA network")) + } + } +} + +/// Opens (or reuses) the voting database embedded in the wallet's SQLCipher pool. +/// +/// Migrations are additive and idempotent; all voting state is scoped to +/// `wallet_id` (the hex-encoded ZIP-32 seed fingerprint). +pub async fn open_voting_db(pool: SqlitePool, wallet_id: &str) -> Result { + let db = VotingDb::from_pool(pool).await?; + db.set_wallet_id(wallet_id); + Ok(db) +} + +/// Wallet identifier for voting state: hex-encoded ZIP-32 seed fingerprint. +pub async fn voting_wallet_id(connection: &mut SqliteConnection, account: u32) -> Result { + let fingerprint = crate::db::get_account_fingerprint(connection, account) + .await? + .ok_or_else(|| anyhow!("account {account} has no seed fingerprint"))?; + ensure!( + fingerprint.len() == 32, + "seed fingerprint must be 32 bytes, got {}", + fingerprint.len() + ); + Ok(hex::encode(fingerprint)) +} + +/// The ZIP-32 seed bytes for an account, derived from its stored mnemonic. +pub async fn account_seed(connection: &mut SqliteConnection, account: u32) -> Result> { + let seed = crate::account::get_account_seed(connection, account) + .await? + .ok_or_else(|| anyhow!("account {account} has no mnemonic seed"))?; + let mnemonic = Mnemonic::from_str(&seed.mnemonic)?; + Ok(mnemonic.to_seed(&seed.phrase).to_vec()) +} + +/// Generates a fresh app-owned voting hotkey and persists its stored secret +/// (hex) in the wallet props table. +pub async fn voting_hotkey_create( + connection: &mut SqliteConnection, + network: VotingNetwork, +) -> Result { + ensure!( + crate::db::get_prop(connection, VOTING_HOTKEY_PROP) + .await? + .is_none(), + "voting hotkey already exists for this wallet" + ); + let hotkey = generate_random_voting_hotkey(network)?; + crate::db::put_prop( + connection, + VOTING_HOTKEY_PROP, + &hex::encode(hotkey.stored_secret()), + ) + .await?; + Ok(hotkey) +} + +/// Loads the persisted voting hotkey from the wallet props table. +pub async fn voting_hotkey_load( + connection: &mut SqliteConnection, + network: VotingNetwork, +) -> Result { + let secret = crate::db::get_prop(connection, VOTING_HOTKEY_PROP) + .await? + .ok_or_else(|| anyhow!("no voting hotkey; create one first"))?; + let secret = hex::decode(secret)?; + Ok(VotingHotkey::from_stored_secret(&secret, network)?) +} + +/// Resolves lightwalletd-derived delegation inputs for a voting round. +pub async fn gather_lwd_inputs( + lightwalletd_url: &str, + network: VotingNetwork, + round_params: &VotingRoundParams, + round_name: &str, +) -> Result { + Ok(zcash_voting::delegate::gather_delegation_lwd_inputs( + zcash_voting::delegate::ResolveDelegationLwdParams { + lightwalletd_url, + network, + round_params: round_params.clone(), + round_name, + }, + ) + .await?) +} + +/// Caller-selected note and witness material for one voting round. +pub struct RoundInputs { + pub note_infos: Vec, + pub witnesses: Vec, +} + +/// Loads eligible Ironwood notes and snapshot-rooted witnesses from the wallet DB. +/// +/// Replicates the sync guard and rewind logic of the send path: the wallet +/// must be synced through the round snapshot height, and each note's witness +/// is rewound to the snapshot-height Ironwood frontier whose root must match +/// the round's `nc_root`. +pub async fn load_round_inputs( + network: &WalletNetwork, + connection: &mut SqliteConnection, + client: &mut crate::Client, + account: u32, + snapshot_height: u32, + nc_root: &[u8], +) -> Result { + // Sync guard: the wallet must be synced through the round snapshot height. + let h = crate::sync::get_db_height(connection, account).await?; + ensure!( + h.height >= snapshot_height, + "wallet is not synced to the round snapshot height {snapshot_height} (current {})", + h.height + ); + + // Select unspent, unlocked Ironwood (pool 3) ZEC notes. + let notes = unspent_ironwood_notes(connection, account).await?; + ensure!( + !notes.is_empty(), + "no unspent Ironwood notes available for voting" + ); + + // Anchor the witnesses at the snapshot-height Ironwood frontier. The fork + // enforces witness.root == nc_root anyway; fail fast here with a clear error. + let (_, _, ironwood_frontier) = + crate::sync::get_tree_state(network, client, snapshot_height).await?; + let edge = ironwood_frontier.to_edge(&OrchardHasher::default()); + let anchor_root = edge.root(&OrchardHasher::default()); + ensure!( + anchor_root.as_slice() == nc_root, + "Ironwood anchor root does not match round nc_root" + ); + let edge = edge.to_auth_path(&OrchardHasher::default()); + let ero = empty_roots(&OrchardHasher::default()); + + let ovk = crate::account::get_orchard_vk(connection, account) + .await? + .ok_or_else(|| anyhow!("account {account} has no Orchard viewing key"))?; + let ufvk = unified_full_viewing_key(network, connection, account).await?; + + let mut note_infos = Vec::with_capacity(notes.len()); + let mut witnesses = Vec::with_capacity(notes.len()); + for (id, scope) in notes { + let (note, merkle_path) = crate::account::get_orchard_note( + connection, + id, + h.height, + &ovk, + &edge, + &ero, + orchard::NoteVersion::V3, + Some(edge.1), + ) + .await + .with_context(|| format!("load Ironwood note {id}"))?; + let position = merkle_path.position() as u64; + let scope = match scope { + 0 => orchard::keys::Scope::External, + 1 => orchard::keys::Scope::Internal, + _ => return Err(anyhow!("unexpected note scope {scope}")), + }; + let info = NoteInfo::from_orchard_note(¬e, position, scope, &ufvk, network)?; + let auth_path = merkle_path + .auth_path() + .iter() + .map(|sibling| sibling.to_bytes().to_vec()) + .collect(); + witnesses.push(WitnessData { + note_commitment: info.commitment.clone(), + position, + root: anchor_root.to_vec(), + auth_path, + }); + note_infos.push(info); + } + + Ok(RoundInputs { + note_infos, + witnesses, + }) +} + +/// Unspent, unlocked Ironwood (pool 3) ZEC notes as `(note_id, scope)`. +async fn unspent_ironwood_notes( + connection: &mut SqliteConnection, + account: u32, +) -> Result> { + let notes = sqlx::query( + "SELECT a.id_note, a.scope + FROM notes a + LEFT JOIN spends b ON a.id_note = b.id_note + LEFT JOIN assets ast ON a.id_asset = ast.id_asset + WHERE b.id_note IS NULL AND a.account = ? + AND a.pool = 3 AND a.locked = 0 + AND COALESCE(ast.asset_base, X'0000000000000000000000000000000000000000000000000000000000000000') = X'0000000000000000000000000000000000000000000000000000000000000000'", + ) + .bind(account) + .map(|row: sqlx::sqlite::SqliteRow| { + let id: u32 = row.get(0); + let scope: Option = row.get(1); + (id, scope.unwrap_or(0)) + }) + .fetch_all(&mut *connection) + .await?; + + Ok(notes) +} + +async fn unified_full_viewing_key( + network: &WalletNetwork, + connection: &mut SqliteConnection, + account: u32, +) -> Result { + let encoded = crate::key::get_account_ufvk(network, connection, account, 4).await?; + UnifiedFullViewingKey::decode(network, &encoded) + .map_err(|e| anyhow!("invalid account UFVK: {e}")) +} + +/// Wallet keys plus the voting hotkey used to build delegation PCZTs. +pub struct VotingIdentity { + pub delegation_keys: DelegationKeys, + pub hotkey: VotingHotkey, +} + +/// Loads the delegation keys and voting hotkey for an account. +/// +/// `round_name` must be the resolved round name so the PCZT display metadata +/// matches the prepared round. +pub async fn load_voting_identity( + connection: &mut SqliteConnection, + account: u32, + network: VotingNetwork, + round_name: &str, +) -> Result { + let fingerprint = crate::db::get_account_fingerprint(connection, account) + .await? + .ok_or_else(|| anyhow!("account {account} has no seed fingerprint"))?; + let seed_fingerprint: [u8; 32] = fingerprint + .try_into() + .map_err(|_| anyhow!("seed fingerprint must be 32 bytes"))?; + let account_index = crate::db::get_account_aindex(connection, account).await?; + let ovk = crate::account::get_orchard_vk(connection, account) + .await? + .ok_or_else(|| anyhow!("account {account} has no Orchard viewing key"))?; + let fvk_bytes = ovk.to_bytes(); + let hotkey = voting_hotkey_load(connection, network).await?; + let delegation_keys = DelegationKeys::with_voting_hotkey( + fvk_bytes.to_vec(), + &hotkey, + seed_fingerprint, + account_index, + round_name.to_string(), + )?; + Ok(VotingIdentity { + delegation_keys, + hotkey, + }) +} + +/// Prepares one delegation bundle from caller-supplied notes and witnesses. +pub async fn prepare_delegation_bundle( + pool: SqlitePool, + wallet_id: &str, + lwd: zcash_voting::delegate::DelegationLwdInputs, + session_json: Option<&str>, + round_note_infos: Vec, + delegation_keys: DelegationKeys, + witnesses: Vec, + bundle_index: u32, + bundle_policy: BundlePolicy, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + Ok(zcash_voting::delegate::prepare_delegation_bundle_with_inputs( + &db, + PrepareDelegationBundleWithInputsParams { + lwd, + session_json, + round_note_infos, + delegation_keys, + witnesses, + bundle_index, + bundle_policy, + }, + ) + .await?) +} + +/// Signs a delegation signing request with the wallet's own ZIP-32 seed. +/// +/// Mirrors the fork's wallet-example signer: verifies the request fingerprint +/// against the seed, derives the account SpendAuth key, randomizes it with the +/// stored alpha, and signs the PCZT sighash. +pub fn sign_delegation_request( + seed: &[u8], + request: DelegationSigningRequest, +) -> Result<([u8; 64], [u8; 32])> { + let seed_fingerprint = zip32::fingerprint::SeedFingerprint::from_seed(seed) + .ok_or_else(|| anyhow!("wallet seed length is not valid for ZIP-32"))?; + ensure!( + seed_fingerprint.to_bytes() == request.seed_fingerprint, + "wallet seed fingerprint does not match delegation signing request" + ); + + let account = AccountId::try_from(request.account_index) + .map_err(|_| anyhow!("invalid account_index {}", request.account_index))?; + let usk = UnifiedSpendingKey::from_seed(&request.network, seed, account)?; + let sk = *usk.orchard(); + let ask = orchard::keys::SpendAuthorizingKey::from(&sk); + let alpha = Option::::from( + halo2_proofs::pasta::pallas::Scalar::from_repr(request.alpha), + ) + .ok_or_else(|| anyhow!("delegation alpha is not a valid Pallas scalar"))?; + let rsk = ask.randomize(&alpha); + let mut rng = OsRng; + let sig = rsk.sign(&mut rng, &request.sighash); + Ok(((&sig).into(), request.sighash)) +} + +/// Proves one prepared delegation bundle and assembles the chain-ready submission. +/// +/// The proof is generated against the PIR server; the bundle's SpendAuth +/// signature comes from the wallet's own seed. `pczt_bytes` is the setup PCZT +/// (empty skips the sighash consistency check, mirroring the fork's Keystone path). +#[allow(clippy::too_many_arguments)] +pub async fn prove_and_submit_delegation( + pool: SqlitePool, + wallet_id: &str, + prepared: &PreparedDelegationBundle, + seed: &[u8], + pczt_bytes: Vec, + pir_layout: zcash_voting::config::PirLayout, + pir_server_url: &str, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + let progress = NoopProgressReporter; + + let _setup = prepared.setup(&db, &progress).await?; + let request = prepared.signing_request(&db).await?; + let (sig, sighash) = sign_delegation_request(seed, request)?; + + let pir_client = zcash_voting::connect_pir_blocking( + pir_layout, + pir_server_url, + Arc::new(zcash_voting::HyperTransport::new()), + )?; + prepared.prove(&db, &pir_client, &progress).await?; + + let bundle = prepared + .signed_bundle(&db, pczt_bytes, PreparedSigner::signature(sig, sighash)) + .await?; + Ok(bundle.submission) +} + +/// Records a confirmed delegation transaction (persists the bundle's public +/// VAN position — required before any vote can be committed). +pub async fn confirm_delegation( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + tx_hash: &str, + events: &[TxEvent], +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + Ok(confirm_delegation_submission(&db, round_id, bundle_index, tx_hash, events).await?) +} + +/// Records a confirmed cast-vote transaction. +pub async fn confirm_vote( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + proposal_id: u32, + tx_hash: &str, + events: &[TxEvent], +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + Ok(confirm_vote_submission(&db, round_id, bundle_index, proposal_id, tx_hash, events).await?) +} + +/// Syncs the vote-authority-note tree and derives this bundle's VAN witness. +/// +/// Requires a confirmed delegation (VAN position persisted). +pub async fn vote_van_witness( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + vote_node_url: &str, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + let anchor_height = zcash_voting::prelude::sync_vote_tree(&db, round_id, vote_node_url).await?; + Ok(zcash_voting::prelude::van_witness(&db, round_id, bundle_index, anchor_height).await?) +} + +/// Builds, hotkey-signs, and persists signed vote commitments for a draft batch. +pub async fn commit_votes( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + drafts: &[DraftVote], + witness: &VanWitness, + hotkey: &VotingHotkey, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + Ok(zcash_voting::prelude::commit_batch( + &db, + round_id, + bundle_index, + drafts, + witness, + VoteSigner::hotkey(hotkey), + &NoopProgressReporter, + ) + .await?) +} + +/// Reconstructs the chain-ready vote submission and helper-share payloads +/// for one committed vote. +pub async fn vote_payloads( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + proposal_id: u32, +) -> Result<(VoteSubmission, Vec)> { + let db = open_voting_db(pool, wallet_id).await?; + let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; + Ok(( + committed.submission(&db).await?, + committed.share_payloads().to_vec(), + )) +} + +/// Records successful vote-chain and helper-share submissions for one vote. +pub async fn record_vote_execution( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + proposal_id: u32, + vote_tx_hash: &str, + vc_tree_position: u64, + shares: &[(u32, Vec, u64, bool)], +) -> Result<()> { + let db = open_voting_db(pool, wallet_id).await?; + let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; + committed.record_submission(&db, vote_tx_hash).await?; + committed.record_vc_position(&db, vc_tree_position).await?; + for (share_index, sent_to_urls, submit_at, confirmed) in shares { + committed + .record_share(&db, *share_index, sent_to_urls, *submit_at) + .await?; + if *confirmed { + committed.confirm_share(&db, *share_index).await?; + } + } + Ok(()) +} + +// --------------------------------------------------------------------------- +// Prepared bundle cache +// +// PreparedDelegationBundle is plain data and the fork persists all durable +// round/bundle/witness state in the voting DB. The cache avoids re-running the +// wallet-side input gathering between FRB steps (single-wallet app). +// --------------------------------------------------------------------------- + +static PREPARED_BUNDLES: OnceLock>> = + OnceLock::new(); + +fn bundle_cache_key(wallet_id: &str, round_id: &str, bundle_index: u32) -> String { + format!("{wallet_id}:{round_id}:{bundle_index}") +} + +pub fn cache_prepared_bundle(wallet_id: &str, prepared: PreparedDelegationBundle) { + let mut cache = PREPARED_BUNDLES + .get_or_init(|| Mutex::new(HashMap::new())) + .lock() + .expect("voting prepared bundle cache poisoned"); + let key = bundle_cache_key(wallet_id, &prepared.round_id, prepared.bundle_index); + cache.insert(key, prepared); +} + +pub fn load_prepared_bundle( + wallet_id: &str, + round_id: &str, + bundle_index: u32, +) -> Result { + let cache = PREPARED_BUNDLES + .get_or_init(|| Mutex::new(HashMap::new())) + .lock() + .expect("voting prepared bundle cache poisoned"); + cache + .get(&bundle_cache_key(wallet_id, round_id, bundle_index)) + .cloned() + .ok_or_else(|| { + anyhow!("delegation bundle not prepared; run delegation_prepare first") + }) +} From 59a5ed8bd187e1ff2645e15448424f07d5a1ca55 Mon Sep 17 00:00:00 2001 From: rachyandco Date: Sat, 15 Aug 2026 00:46:59 +0200 Subject: [PATCH 060/189] feat: add nym mixnet as transport (#1195) * feat: add Nym mixnet as a pluggable transport alongside Tor Replace the use_tor boolean with a 4-way transport selector (Direct / Tor / Nym / Proxy) on Coin and in the settings UI, with automatic migration of the legacy use_tor preference. Nym support is embedded via nym-smolmix: TCP through the mixnet exits via an IPR gateway, and hostnames are resolved with DNS-over-mixnet (hickory-proto over the tunnel's UDP socket) so server names never leak to the local resolver. Resolved addresses are cached for 5 minutes. The shared tunnel is self-healing: transport-level failures discard it and the next attempt bootstraps a fresh one, with bounded timeouts on bootstrap (90s), DNS (10s x2), and TCP connect (30s). Zebra JSON-RPC now selects its stream source explicitly from the transport enum (post_tor generalized to post_stream), instead of implicitly using Tor whenever the global client existed. jwt-simple is patched to a local clone (rand pin relaxed to ^0.8.5) because published versions either conflict with the nym crates' rand requirement or with the librustzcash fork's crypto-common pin. * feat: connect to nym:// lightwalletd services natively over the mixnet A server URL of the form nym://identity.encryption@gateway is a nym-rpc service (github.com/rachyandco/nym-rpc) fronting lightwalletd: gRPC runs end-to-end through the mixnet with no exit gateway, DNS, or clearnet hop. zkool speaks the nym-rpc raw-tunnel protocol using the nym-sdk tcp_proxy wire format (UPSTREAM hint, ordered sessions) via a localhost forwarder, with a pooled mixnet client, one shared lazy gRPC channel per recipient, and 120s stall detection so a lost reply errors out instead of hanging. For nym:// servers the transport selector is forced to Direct and disabled with a warning, and the server picker gains a default Nym entry plus a paste-your-own dialog. --- Cargo.lock | 4799 ++++++++++++++++++++++++++-- Cargo.toml | 7 + lib/pages/lwd_select.dart | 345 +- lib/pages/splash.dart | 2 +- lib/settings.dart | 97 +- lib/src/rust/api/coin.dart | 8 +- lib/src/rust/api/coin.freezed.dart | 60 +- lib/src/rust/api/network.dart | 5 + lib/src/rust/frb_generated.dart | 229 +- lib/store.dart | 13 +- lib/store.freezed.dart | 56 +- lib/store.g.dart | 2 +- rust/Cargo.toml | 7 + rust/src/api/coin.rs | 95 +- rust/src/api/mempool.rs | 4 +- rust/src/api/network.rs | 7 + rust/src/frb_generated.rs | 233 +- rust/src/net/mod.rs | 2 + rust/src/net/nym.rs | 233 ++ rust/src/net/nym_service.rs | 272 ++ rust/src/net/zebra.rs | 92 +- 21 files changed, 5835 insertions(+), 733 deletions(-) create mode 100644 rust/src/net/nym.rs create mode 100644 rust/src/net/nym_service.rs diff --git a/Cargo.lock b/Cargo.lock index 5bd4fff78..b7b724f96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common 0.1.7", - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -39,6 +39,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle 2.6.1", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle 2.6.1", + "zeroize", +] + [[package]] name = "age" version = "0.11.5" @@ -60,7 +89,7 @@ dependencies = [ "rust-embed", "scrypt", "sha2 0.10.9", - "subtle", + "subtle 2.6.1", "x25519-dalek", "zeroize", ] @@ -90,7 +119,7 @@ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if 1.0.4", "const-random", - "getrandom 0.3.4", + "getrandom 0.3.3", "once_cell", "version_check", "zerocopy", @@ -125,6 +154,21 @@ dependencies = [ "backtrace", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -141,7 +185,7 @@ dependencies = [ "amplify_num", "ascii", "getrandom 0.2.17", - "getrandom 0.3.4", + "getrandom 0.3.3", "wasm-bindgen", ] @@ -290,11 +334,132 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", - "blake2", + "blake2 0.10.6", "cpufeatures 0.2.17", "password-hash", ] +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.7", + "rayon", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -317,7 +482,7 @@ dependencies = [ "cfg-if 1.0.4", "derive-deftly", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "educe", "fs-mistrust", "futures", @@ -327,7 +492,7 @@ dependencies = [ "libc", "once_cell", "postage", - "rand 0.9.5", + "rand 0.9.2", "safelog", "serde", "thiserror 2.0.20", @@ -440,6 +605,7 @@ dependencies = [ "compression-core", "futures-io", "pin-project-lite 0.2.17", + "tokio 1.53.1", ] [[package]] @@ -728,7 +894,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -747,6 +913,12 @@ dependencies = [ "safemem", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -810,7 +982,7 @@ dependencies = [ "pairing", "rand_core 0.6.4", "rayon", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -826,6 +998,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bincode" version = "2.0.1" @@ -846,6 +1027,29 @@ dependencies = [ "virtue", ] +[[package]] +name = "binstring" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0669d5a35b64fdb5ab7fb19cae13148b6b5cbdf4b8247faf54ece47f699c8cef" + +[[package]] +name = "bip32" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db40d3dfbeab4e031d78c844642fa0caa0b0db11ce1607ac9d2986dff1405c69" +dependencies = [ + "bs58", + "hmac 0.12.1", + "k256", + "rand_core 0.6.4", + "ripemd 0.1.3", + "secp256k1 0.27.0", + "sha2 0.10.9", + "subtle 2.6.1", + "zeroize", +] + [[package]] name = "bip32" version = "0.6.0-pre.1" @@ -856,9 +1060,9 @@ dependencies = [ "hmac 0.13.0-pre.4", "rand_core 0.6.4", "ripemd 0.2.0-pre.4", - "secp256k1", + "secp256k1 0.29.1", "sha2 0.11.0-pre.4", - "subtle", + "subtle 2.6.1", "zeroize", ] @@ -869,8 +1073,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" dependencies = [ "bitcoin_hashes", + "rand 0.8.7", + "rand_core 0.6.4", "serde", "unicode-normalization", + "zeroize", ] [[package]] @@ -893,6 +1100,9 @@ name = "bitflags" version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] [[package]] name = "bitvec" @@ -906,6 +1116,18 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" +dependencies = [ + "byte-tools", + "crypto-mac", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + [[package]] name = "blake2" version = "0.10.6" @@ -937,6 +1159,21 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake3" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if 1.0.4", + "constant_time_eq", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + [[package]] name = "blanket" version = "0.3.0" @@ -948,13 +1185,22 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -966,6 +1212,15 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "blocking" version = "1.6.2" @@ -989,9 +1244,15 @@ dependencies = [ "group", "pairing", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] +[[package]] +name = "bnum" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" + [[package]] name = "bounded-vec" version = "0.9.0" @@ -1007,6 +1268,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2225b558afc76c596898f5f1b3fc35cfce0eb1b13635cbd7d1b2a7177dc10ccd" +[[package]] +name = "brotli" +version = "8.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bs58" version = "0.5.1" @@ -1046,6 +1328,22 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytecodec" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adf4c9d0bbf32eea58d7c0f812058138ee8edaf0f2802b6d03561b504729a325" +dependencies = [ + "byteorder", + "trackable 0.2.24", +] + [[package]] name = "bytemuck" version = "1.25.2" @@ -1075,6 +1373,18 @@ name = "bytes" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +dependencies = [ + "serde", +] + +[[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] [[package]] name = "caret" @@ -1082,6 +1392,43 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061dc3258f029feaf9ff02b43c6af5ea67a7dfaed5d2aef36204c812e614ef9c" +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.20", +] + [[package]] name = "castaway" version = "0.2.4" @@ -1112,6 +1459,16 @@ dependencies = [ "shlex", ] +[[package]] +name = "celes" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55028d5b1eebb35237512a3838ce5583211434a233c8bb179551a7197ffb7bd4" +dependencies = [ + "phf 0.13.1", + "serde", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -1130,6 +1487,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +[[package]] +name = "chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862" +dependencies = [ + "byteorder", + "keystream", +] + [[package]] name = "chacha20" version = "0.9.1" @@ -1176,7 +1543,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -1275,13 +1642,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] -name = "compact_str" -version = "0.9.1" +name = "colored" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ - "castaway", - "cfg-if 1.0.4", + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes 1.12.1", + "memchr", +] + +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if 1.0.4", "itoa", "rustversion", "ryu", @@ -1294,9 +1681,11 @@ version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" dependencies = [ + "brotli", "compression-core", "flate2", "liblzma", + "memchr", "zstd", "zstd-safe", ] @@ -1358,6 +1747,12 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "const-str" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" + [[package]] name = "constant_time_eq" version = "0.4.2" @@ -1408,12 +1803,143 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-models" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "657f625ff361906f779745d08375ae3cc9fef87a35fba5f22874cf773010daf4" +dependencies = [ + "hax-lib", + "pastey", + "rand 0.9.2", +] + [[package]] name = "corez" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4df6f98652d30167eaeea34d77b730e07c8caba6df17bd4551842b9b8da01deb" +[[package]] +name = "cosmos-sdk-proto" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ac39be7373404accccaede7cc1ec942ccef14f0ca18d209967a756bf1dbb1f" +dependencies = [ + "prost 0.13.5", + "tendermint-proto", +] + +[[package]] +name = "cosmrs" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34e74fa7a22930fe0579bef560f2d64b78415d4c47b9dd976c0635136809471d" +dependencies = [ + "bip32 0.5.3", + "cosmos-sdk-proto", + "ecdsa", + "eyre", + "k256", + "rand_core 0.6.4", + "serde", + "serde_json", + "signature", + "subtle-encoding", + "tendermint", + "tendermint-rpc", + "thiserror 1.0.69", +] + +[[package]] +name = "cosmwasm-core" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9899c6499b006d10e5dc64052e642d365f239ba00339615e2714c50c6aa86389" + +[[package]] +name = "cosmwasm-crypto" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a3f5419d8f6ee9ae698db5a3d5d34ecd4ff82e8b5694bba7a620403c862717" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cosmwasm-core", + "curve25519-dalek", + "digest 0.10.7", + "ecdsa", + "ed25519-zebra", + "k256", + "num-traits", + "p256", + "rand_core 0.6.4", + "rayon", + "sha2 0.10.9", + "thiserror 1.0.69", +] + +[[package]] +name = "cosmwasm-derive" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a625e259b6ab0cae1a758adf9a68a11ecddd023d1ab3d9c5d1785c144663c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cosmwasm-schema" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6984ab21b47a096e17ae4c73cea2123a704d4b6686c39421247ad67020d76f95" +dependencies = [ + "cosmwasm-schema-derive", + "schemars 0.8.22", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01c9214319017f6ebd8e299036e1f717fa9bb6724e758f7d6fb2477599d1a29" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cosmwasm-std" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf82335c14bd94eeb4d3c461b7aa419ecd7ea13c2efe24b97cd972bdb8044e7d" +dependencies = [ + "base64 0.22.1", + "bech32 0.11.1", + "bnum", + "cosmwasm-core", + "cosmwasm-crypto", + "cosmwasm-derive", + "derive_more 1.0.0", + "hex", + "rand_core 0.6.4", + "rmp-serde", + "schemars 0.8.22", + "serde", + "serde-json-wasm", + "sha2 0.10.9", + "static_assertions", + "thiserror 1.0.69", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1517,9 +2043,9 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", "zeroize", ] @@ -1529,7 +2055,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", "typenum", ] @@ -1543,6 +2069,16 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.4", + "subtle 1.0.0", +] + [[package]] name = "csv-async" version = "1.3.1" @@ -1566,6 +2102,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "ct-codecs" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fb0c6640b4507ebd99ff67677009e381ba5eee1d14df78de4a3d16eb123c39" + [[package]] name = "ctr" version = "0.9.2" @@ -1587,7 +2129,8 @@ dependencies = [ "digest 0.10.7", "fiat-crypto", "rustc_version", - "subtle", + "serde", + "subtle 2.6.1", "zeroize", ] @@ -1602,6 +2145,114 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "cw-controllers" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c1804013d21060b994dea28a080f9eab78a3bcb6b617f05e7634b0600bf7b1" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "schemars 0.8.22", + "serde", + "thiserror 1.0.69", +] + +[[package]] +name = "cw-storage-plus" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" +dependencies = [ + "cosmwasm-std", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "cw-utils" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars 0.8.22", + "serde", + "thiserror 1.0.69", +] + +[[package]] +name = "cw2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars 0.8.22", + "semver", + "serde", + "thiserror 1.0.69", +] + +[[package]] +name = "cw20" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42212b6bf29bbdda693743697c621894723f35d3db0d5df930be22903d0e27c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "cw3" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5e53c2057526c65d9c88be8b2a564729ebad7a3d87ee97b97665a71446f913a" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils", + "cw20", + "schemars 0.8.22", + "serde", + "thiserror 1.0.69", +] + +[[package]] +name = "cw4" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d33f5c8a6b6cd1bd24e212d7f44967697bfa3c4f9cc3f9a8e1c58f5fe5db032d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars 0.8.22", + "serde", +] + [[package]] name = "darling" version = "0.14.4" @@ -1691,6 +2342,7 @@ dependencies = [ "lock_api", "once_cell", "parking_lot_core", + "serde", ] [[package]] @@ -1714,6 +2366,15 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f400d0750c0c069e8493f2256cb4da6f604b6d2eeb69a0ca8863acde352f8400" +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.1.1", +] + [[package]] name = "defmt" version = "1.1.1" @@ -1790,6 +2451,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive-deftly" version = "1.0.1" @@ -1813,7 +2485,7 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "strum", + "strum 0.27.2", "syn 2.0.119", "void", ] @@ -1871,13 +2543,34 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + [[package]] name = "derive_more" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl", + "derive_more-impl 2.1.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "unicode-xid", ] [[package]] @@ -1905,6 +2598,24 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "digest" version = "0.10.7" @@ -1914,7 +2625,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common 0.1.7", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -1925,7 +2636,7 @@ checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" dependencies = [ "block-buffer 0.11.0-rc.3", "crypto-common 0.2.0-rc.1", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -2018,6 +2729,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect 0.2.0", "signature", "spki", ] @@ -2029,9 +2741,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", + "serde", "signature", ] +[[package]] +name = "ed25519-compact" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c24599140dc39d7a81e4476e7573d41bbc18e07c803900298e522a5fbcfbfb6" +dependencies = [ + "ct-codecs", + "getrandom 0.4.3", +] + +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "ed25519-dalek" version = "2.2.0" @@ -2044,7 +2780,22 @@ dependencies = [ "rand_core 0.6.4", "serde", "sha2 0.10.9", - "subtle", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core 0.6.4", + "sha2 0.10.9", "zeroize", ] @@ -2079,12 +2830,15 @@ dependencies = [ "crypto-bigint", "digest 0.10.7", "ff", - "generic-array", + "generic-array 0.14.7", "group", + "hkdf", + "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", - "subtle", + "serdect 0.2.0", + "subtle 2.6.1", "zeroize", ] @@ -2193,10 +2947,21 @@ dependencies = [ ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "etcetera" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if 1.0.4", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" @@ -2218,6 +2983,16 @@ dependencies = [ "pin-project-lite 0.2.17", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "f4jumble" version = "0.1.1" @@ -2252,7 +3027,7 @@ checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "bitvec", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -2315,6 +3090,16 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "eyre", + "paste", +] + [[package]] name = "fluent" version = "0.16.1" @@ -2511,7 +3296,7 @@ dependencies = [ "postcard", "rand_core 0.6.4", "serde", - "serdect", + "serdect 0.2.0", "thiserror 2.0.20", "visibility", "zeroize", @@ -2702,12 +3487,22 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ + "serde", "typenum", "version_check", "zeroize", @@ -2722,21 +3517,21 @@ dependencies = [ "cfg-if 1.0.4", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if 1.0.4", "js-sys", "libc", "r-efi 5.3.0", - "wasip2", + "wasi 0.14.7+wasi-0.2.4", "wasm-bindgen", ] @@ -2765,6 +3560,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug 0.3.1", + "polyval", +] + [[package]] name = "gimli" version = "0.32.3" @@ -2783,6 +3588,27 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985c9503b412198aa4197559e9a318524ebc4519c229bfa05a535828c950b9d" +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http 1.5.0", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-timers" version = "0.3.0" @@ -2795,6 +3621,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "group" version = "0.13.0" @@ -2804,7 +3643,7 @@ dependencies = [ "ff", "memuse", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -2830,7 +3669,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f971449e16e799ebbf106d2414c115ff46f2849689c61da3a3271be0884a34" dependencies = [ - "protobuf", + "protobuf 2.18.2", "protobuf-codegen", ] @@ -2842,7 +3681,7 @@ checksum = "2b39e472b8a5bd8344d55473eabda070bc28126cec26ca6a008fa1bbc3d0c4a2" dependencies = [ "bytes 0.5.6", "grpc", - "protobuf", + "protobuf 2.18.2", ] [[package]] @@ -2898,7 +3737,7 @@ dependencies = [ "pasta_curves", "rand 0.8.7", "sinsemilla", - "subtle", + "subtle 2.6.1", "uint", ] @@ -2935,6 +3774,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "handlebars" +version = "3.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" +dependencies = [ + "log", + "pest", + "pest_derive", + "quick-error", + "serde", + "serde_json", +] + [[package]] name = "hash32" version = "0.2.1" @@ -2944,12 +3797,30 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -2957,6 +3828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", + "allocator-api2", ] [[package]] @@ -2994,6 +3866,43 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "hax-lib" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "543f93241d32b3f00569201bfce9d7a93c92c6421b23c77864ac929dc947b9fc" +dependencies = [ + "hax-lib-macros", + "num-bigint", + "num-traits", +] + +[[package]] +name = "hax-lib-macros" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8755751e760b11021765bb04cb4a6c4e24742688d9f3aa14c2079638f537b0f" +dependencies = [ + "hax-lib-macros-types", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "hax-lib-macros-types" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f177c9ae8ea456e2f71ff3c1ea47bf4464f772a05133fcbba56cd5ba169035a2" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "uuid", +] + [[package]] name = "headers" version = "0.4.1" @@ -3025,13 +3934,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", - "hash32", + "hash32 0.2.1", "rustc_version", "serde", "spin 0.9.9", "stable_deref_trait", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32 0.3.1", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -3071,6 +3990,36 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hickory-net" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" +dependencies = [ + "async-trait", + "bytes 1.12.1", + "cfg-if 1.0.4", + "data-encoding", + "futures-channel", + "futures-io", + "futures-util", + "h2 0.4.15", + "hickory-proto 0.26.1", + "http 1.5.0", + "idna", + "ipnet", + "jni", + "rand 0.10.2", + "rustls 0.23.43", + "thiserror 2.0.20", + "tinyvec", + "tokio 1.53.1", + "tokio-rustls 0.26.4", + "tracing", + "url", + "webpki-roots 1.0.9", +] + [[package]] name = "hickory-proto" version = "0.24.4" @@ -3096,6 +4045,26 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-proto" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni", + "once_cell", + "prefix-trie", + "rand 0.10.2", + "ring", + "thiserror 2.0.20", + "tinyvec", + "tracing", + "url", +] + [[package]] name = "hickory-resolver" version = "0.24.4" @@ -3104,7 +4073,7 @@ checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" dependencies = [ "cfg-if 1.0.4", "futures-util", - "hickory-proto", + "hickory-proto 0.24.4", "ipconfig", "lru-cache", "once_cell", @@ -3117,6 +4086,35 @@ dependencies = [ "tracing", ] +[[package]] +name = "hickory-resolver" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" +dependencies = [ + "cfg-if 1.0.4", + "futures-util", + "hickory-net", + "hickory-proto 0.26.1", + "ipconfig", + "ipnet", + "jni", + "moka", + "ndk-context", + "once_cell", + "parking_lot", + "rand 0.10.2", + "resolv-conf", + "rustls 0.23.43", + "smallvec", + "system-configuration 0.7.0", + "thiserror 2.0.20", + "tokio 1.53.1", + "tokio-rustls 0.26.4", + "tracing", + "webpki-roots 1.0.9", +] + [[package]] name = "hidapi" version = "2.6.6" @@ -3159,6 +4157,30 @@ dependencies = [ "digest 0.11.0-pre.9", ] +[[package]] +name = "hmac-sha1-compact" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b3ba31f6dc772cc8221ce81dbbbd64fa1e668255a6737d95eeace59b5a8823" + +[[package]] +name = "hmac-sha256" +version = "1.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9d92d097f4749b64e8cc33d924d9f40a2d4eb91402b458014b781f5733d60f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-sha512" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "019ece39bbefc17f13f677a690328cb978dbf6790e141a3c24e66372cb38588b" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "home" version = "0.5.12" @@ -3254,6 +4276,16 @@ dependencies = [ "void", ] +[[package]] +name = "httpcodec" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f49d64351430cabd543943b79d48aaf0bc95a41d9ccf5b8774c2cfd23422775" +dependencies = [ + "bytecodec", + "trackable 0.2.24", +] + [[package]] name = "httpdate" version = "1.0.3" @@ -3331,6 +4363,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "rustls 0.21.12", + "tokio 1.53.1", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.9" @@ -3342,7 +4388,7 @@ dependencies = [ "hyper-util", "rustls 0.23.43", "tokio 1.53.1", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower-service", "webpki-roots 1.0.9", ] @@ -3474,7 +4520,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -3630,6 +4676,12 @@ dependencies = [ "either", ] +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "indexmap" version = "1.9.3" @@ -3679,7 +4731,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array", + "block-padding", + "generic-array 0.14.7", ] [[package]] @@ -3745,7 +4798,7 @@ dependencies = [ "socket2 0.6.5", "widestring", "windows-registry", - "windows-result", + "windows-result 0.4.1", "windows-sys 0.61.2", ] @@ -3754,6 +4807,9 @@ name = "ipnet" version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +dependencies = [ + "serde", +] [[package]] name = "is_terminal_polyfill" @@ -3761,6 +4817,15 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -3791,7 +4856,7 @@ version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" dependencies = [ - "defmt", + "defmt 1.1.1", "jiff-core", "jiff-static", "jiff-tzdb-platform", @@ -3799,7 +4864,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -3808,7 +4873,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" dependencies = [ - "defmt", + "defmt 1.1.1", ] [[package]] @@ -3839,29 +4904,78 @@ dependencies = [ ] [[package]] -name = "jobserver" -version = "0.1.35" +name = "jni" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "getrandom 0.4.3", - "libc", + "cfg-if 1.0.4", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror 2.0.20", + "walkdir", + "windows-link 0.2.1", ] [[package]] -name = "js-sys" -version = "0.3.104" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "cfg-if 1.0.4", - "futures-util", - "wasm-bindgen", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", ] [[package]] -name = "jsonwebtoken" -version = "10.4.0" +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +dependencies = [ + "cfg-if 1.0.4", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "10.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" dependencies = [ @@ -3869,7 +4983,7 @@ dependencies = [ "base64 0.22.1", "getrandom 0.2.17", "js-sys", - "pem", + "pem 3.0.6", "serde", "serde_json", "signature", @@ -3888,7 +5002,7 @@ dependencies = [ "ff", "group", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -3903,7 +5017,7 @@ dependencies = [ "bigdecimal", "chrono", "compact_str", - "derive_more", + "derive_more 2.1.1", "fnv", "futures", "indexmap 2.14.0", @@ -3922,7 +5036,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8634f500d6d2ec5c91c115b83e15d998d9ea05645aaa43f7afec09e660c483ba" dependencies = [ - "derive_more", + "derive_more 2.1.1", "proc-macro2", "quote", "syn 2.0.119", @@ -3935,7 +5049,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02f74a1d6d28f29edd4e72db014229efef9b3c3baa5cdf64ebc76b82ee146fa5" dependencies = [ - "derive_more", + "derive_more 2.1.1", "juniper", "juniper_subscriptions", "serde", @@ -3958,7 +5072,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb4c06e36e0f572b31d41d12c6e97896dc65e38d599d68f263f5f2bfea1e6ade" dependencies = [ - "derive_more", + "derive_more 2.1.1", "futures", "http-body-util", "juniper", @@ -3969,6 +5083,45 @@ dependencies = [ "warp", ] +[[package]] +name = "jwt-simple" +version = "0.12.12" +source = "git+https://github.com/rachyandco/rust-jwt-simple?rev=e8177eab707d27d7ea94b6799204e48e11b65e19#e8177eab707d27d7ea94b6799204e48e11b65e19" +dependencies = [ + "anyhow", + "binstring", + "blake2b_simd", + "coarsetime", + "ct-codecs", + "ed25519-compact", + "hmac-sha1-compact", + "hmac-sha256", + "hmac-sha512", + "k256", + "p256", + "p384", + "rand 0.8.7", + "serde", + "serde_json", + "superboring", + "thiserror 2.0.20", + "zeroize", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if 1.0.4", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.9", + "signature", +] + [[package]] name = "keccak" version = "0.1.6" @@ -3988,6 +5141,12 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "keystream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" + [[package]] name = "known-folders" version = "1.4.2" @@ -4068,7 +5227,7 @@ dependencies = [ "hex", "ledger-transport", "log", - "protobuf", + "protobuf 2.18.2", "protoc-rust-grpc", "reqwest 0.11.27", "serde", @@ -4081,6 +5240,261 @@ version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libcrux-aesgcm" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f2a019dab4097585a7d4f5b9deebe46cd1e628b16a5bc4cb0ce35e1da334e6" +dependencies = [ + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-secrets", + "libcrux-traits", +] + +[[package]] +name = "libcrux-chacha20poly1305" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc08d044676af21343b32b988411fa98dbb5cf65a03c9df478ced221bbdfdb1b" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-poly1305", + "libcrux-secrets", + "libcrux-traits", +] + +[[package]] +name = "libcrux-curve25519" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1e5fd8476a6ed609d24ef42aee5ab6f99f7c65d054f92412da9f499e423299" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-secrets", + "libcrux-traits", +] + +[[package]] +name = "libcrux-ecdh" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65f73ce79337c762eb38bbac91e4c9b9e60cf318e8501b812750c640814d45e" +dependencies = [ + "libcrux-curve25519", + "libcrux-p256", + "rand 0.9.2", + "tls_codec", +] + +[[package]] +name = "libcrux-ed25519" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835919315b7042fe9e03b6458efe0db94bf2aa7b873934dbee5b5463a8124b43" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-sha2", + "rand_core 0.9.5", + "tls_codec", +] + +[[package]] +name = "libcrux-hacl-rs" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2637dc87d158e1f1b550fd9b226443e84153fded4de69028d897b534d16d22e6" +dependencies = [ + "libcrux-macros", +] + +[[package]] +name = "libcrux-hkdf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1a89ca0c89be3a268a921e47105fb7873badf7267f5e3ebf4ea46baedd73ef" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-hmac", + "libcrux-secrets", +] + +[[package]] +name = "libcrux-hmac" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7a242707d65960770bd7e14e4f18a92bdf0b967777dd404887db8d087a643b" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-sha2", +] + +[[package]] +name = "libcrux-intrinsics" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b5db005ff8001e026b73a6842ee81bbef8ec5ff0e1915a67ae65fd2a9fafa5" +dependencies = [ + "core-models", + "hax-lib", +] + +[[package]] +name = "libcrux-kem" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12631592f491d22fd1a176d32b2c6edfb673998fd3987e9d95f8fa79ad2a737b" +dependencies = [ + "libcrux-curve25519", + "libcrux-ecdh", + "libcrux-ml-kem", + "libcrux-p256", + "libcrux-sha3", + "libcrux-traits", + "rand 0.9.2", + "tls_codec", +] + +[[package]] +name = "libcrux-macros" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd6aa2dcd5be681662001b81d493f1569c6d49a32361f470b0c955465cd0338" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "libcrux-ml-dsa" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a72929ed421cc3bf16a946b3e7d2a58d215b0b5c2a12be26b53629f081bf49b2" +dependencies = [ + "core-models", + "hax-lib", + "libcrux-intrinsics", + "libcrux-macros", + "libcrux-platform", + "libcrux-sha3", + "tls_codec", +] + +[[package]] +name = "libcrux-ml-kem" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a14ab3e477de9df6ee1273a114018ff62c4996ca9220070c4e5cb1743f94a67d" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-secrets", + "libcrux-sha3", + "libcrux-traits", + "rand 0.9.2", + "tls_codec", +] + +[[package]] +name = "libcrux-p256" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4778ba25cb08bb8a96bd100e19ed9aecf78337198fd176036e21042b2dd99bc" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-secrets", + "libcrux-sha2", + "libcrux-traits", +] + +[[package]] +name = "libcrux-platform" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9e21d7ed31a92ac539bd69a8c970b183ee883872d2d19ce27036e24cb8ecc4" +dependencies = [ + "libc", +] + +[[package]] +name = "libcrux-poly1305" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02491808ee5b9db8cb65fad64ae0be812db64beef179d945c00c7787dc7dfcf9" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", +] + +[[package]] +name = "libcrux-psq" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779ade7aa5e1b4b400c716b313cbf69070988dd005f92e961c2da4c3c42fbea4" +dependencies = [ + "libcrux-aesgcm", + "libcrux-chacha20poly1305", + "libcrux-ecdh", + "libcrux-ed25519", + "libcrux-hkdf", + "libcrux-hmac", + "libcrux-kem", + "libcrux-ml-dsa", + "libcrux-ml-kem", + "libcrux-sha2", + "libcrux-traits", + "rand 0.9.2", + "tls_codec", +] + +[[package]] +name = "libcrux-secrets" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce650f3041b44ba40d4263852347d007cd2cd9d1cc856a6f6c8b2e10c3fd40b" +dependencies = [ + "hax-lib", +] + +[[package]] +name = "libcrux-sha2" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d253473f259fc74a280c43f29c464f7e374abdf28b4942234dc707f529d4b7" +dependencies = [ + "libcrux-hacl-rs", + "libcrux-macros", + "libcrux-traits", +] + +[[package]] +name = "libcrux-sha3" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ae0b7d0e1cc4793a609fd0ff2ca3b3a3fabae523770c619a3d4bc86417b0d7" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-traits", +] + +[[package]] +name = "libcrux-traits" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e4fa89f3f5e34b47f928b22b1b78395a0d4ec23b1f583db635f128159d65f" +dependencies = [ + "libcrux-secrets", + "rand 0.9.2", +] + [[package]] name = "liblzma" version = "0.4.8" @@ -4113,7 +5527,10 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa" dependencies = [ + "bitflags 2.13.1", "libc", + "plain", + "redox_syscall 0.9.1", ] [[package]] @@ -4156,6 +5573,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "lioness" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae926706ba42c425c9457121178330d75e273df2e82e28b758faf3de3a9acb9" +dependencies = [ + "arrayref", + "blake2 0.8.1", + "chacha", + "keystream", +] + [[package]] name = "litemap" version = "0.8.2" @@ -4233,6 +5662,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + [[package]] name = "matchers" version = "0.2.0" @@ -4371,7 +5806,7 @@ checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -4398,6 +5833,23 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "moka" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + [[package]] name = "moxcms" version = "0.8.1" @@ -4432,14 +5884,20 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "net2" version = "0.2.39" @@ -4514,6 +5972,15 @@ dependencies = [ "bitflags 2.13.1", ] +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -4617,38 +6084,1588 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.37.3" +name = "num_threads" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ - "memchr", + "libc", ] [[package]] -name = "once_cell" -version = "1.21.4" +name = "nym-api-requests" +version = "1.21.5-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +checksum = "ad583a4982e09e135b977e509c22228bc5760979858ee76af6269611c51d2de4" dependencies = [ - "portable-atomic", + "bs58", + "celes", + "cosmrs", + "cosmwasm-std", + "ecdsa", + "hex", + "humantime-serde", + "nym-coconut-dkg-common", + "nym-compact-ecash", + "nym-config", + "nym-contracts-common", + "nym-credentials-interface", + "nym-crypto", + "nym-ecash-signer-check-types", + "nym-ecash-time", + "nym-kkt-ciphersuite", + "nym-mixnet-contract-common", + "nym-network-defaults", + "nym-node-requests", + "nym-noise-keys", + "nym-serde-helpers", + "nym-ticketbooks-merkle", + "schemars 0.8.22", + "serde", + "serde_json", + "sha2 0.10.9", + "strum 0.28.0", + "strum_macros 0.28.0", + "tendermint", + "tendermint-rpc", + "thiserror 2.0.20", + "time", + "tracing", + "utoipa", ] [[package]] -name = "once_cell_polyfill" -version = "1.70.2" +name = "nym-bandwidth-controller" +version = "1.21.5-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +checksum = "cfbedb26a738ffc237ac40c58803b3a66f82a1a91ecf965b2a136fad14dc40ac" +dependencies = [ + "async-trait", + "log", + "nym-credential-storage", + "nym-credentials", + "nym-credentials-interface", + "nym-crypto", + "nym-ecash-time", + "nym-task", + "nym-validator-client", + "si-scale", + "strum 0.28.0", + "thiserror 2.0.20", + "tokio 1.53.1", + "tracing", + "wasmtimer", +] [[package]] -name = "oneshot-fused-workaround" -version = "0.2.3" +name = "nym-bandwidth-fetcher" +version = "1.21.5-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2948fd2414b613f9a97f8401270bd5d7638265ab940475cdbcfa28a0273d58" +checksum = "2fbc3c00ffd3311e5efd19dfe64594245b1b201896d942e71743c7dc00a0cc32" dependencies = [ - "futures", + "anyhow", + "async-trait", + "log", + "nym-bandwidth-controller", + "nym-credentials", + "nym-crypto", + "nym-ecash-time", + "nym-sqlx-pool-guard", + "nym-validator-client", + "rand 0.8.7", + "sqlx", + "thiserror 2.0.20", + "tokio 1.53.1", + "tracing", + "zeroize", ] +[[package]] +name = "nym-bin-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16cd23ffe9eef2345123e54e6cea2a99f5b8435fcd53dd8352639d36c146ff0" +dependencies = [ + "const-str", + "log", + "schemars 0.8.22", + "serde", + "tracing", + "tracing-subscriber", + "utoipa", + "vergen", +] + +[[package]] +name = "nym-bls12_381-fork" +version = "0.8.0-forked" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce84633751030f960a2fd167b5270ec21da4c40d9b6400e1b56676a682fe6f3d" +dependencies = [ + "digest 0.10.7", + "ff", + "group", + "pairing", + "rand_core 0.6.4", + "serde", + "serdect 0.3.0", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "nym-client-core" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c634e065126883335de04328ce091b4dd75326c8a147f2740a6697311b1404c6" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bs58", + "cfg-if 1.0.4", + "futures", + "getrandom 0.3.3", + "gloo-timers", + "http-body-util", + "humantime", + "hyper 1.11.0", + "hyper-util", + "nym-bandwidth-controller", + "nym-bandwidth-fetcher", + "nym-client-core-config-types", + "nym-client-core-gateways-storage", + "nym-client-core-surb-storage", + "nym-credential-storage", + "nym-credentials-interface", + "nym-crypto", + "nym-ecash-time", + "nym-gateway-client", + "nym-gateway-requests", + "nym-http-api-client", + "nym-id", + "nym-mixnet-client", + "nym-mixnet-contract-common", + "nym-network-defaults", + "nym-nonexhaustive-delayqueue", + "nym-pemstore", + "nym-sphinx", + "nym-statistics-common", + "nym-task", + "nym-topology", + "nym-validator-client", + "nym-wasm-utils", + "rand 0.8.7", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "sha2 0.10.9", + "si-scale", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tokio-stream", + "tokio-tungstenite 0.20.1", + "tokio_with_wasm", + "tracing", + "tungstenite 0.20.1", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "nym-client-core-config-types" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1842589b946491cf3e47073f45c0ef201ad4eef1f438ef413b24046b5e7407fe" +dependencies = [ + "humantime-serde", + "nym-config", + "nym-pemstore", + "nym-sphinx-addressing", + "nym-sphinx-params", + "nym-statistics-common", + "serde", + "thiserror 2.0.20", + "url", +] + +[[package]] +name = "nym-client-core-gateways-storage" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0b4929eba1c5fb58a80820121923cf15f0fd3d1d0364948406a78246cb4266" +dependencies = [ + "anyhow", + "async-trait", + "nym-crypto", + "nym-gateway-client", + "nym-gateway-requests", + "serde", + "sqlx", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "nym-client-core-surb-storage" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629f9c520d48cfd277f3b7e11aa17fc354a893842757f8ffd10021bbd5b93757" +dependencies = [ + "anyhow", + "async-trait", + "dashmap", + "nym-crypto", + "nym-sphinx", + "nym-sqlx-pool-guard", + "nym-task", + "sqlx", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tracing", +] + +[[package]] +name = "nym-coconut-dkg-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda2d594fe60c6b1660d021e0012a08d3fc8ffd7e3382acb7c40af7ac2dc0fed" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils", + "cw2", + "cw4", + "nym-contracts-common", + "nym-multisig-contract-common", +] + +[[package]] +name = "nym-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157fc2f6e626325ab0a972049d501d70d0e96fb498817c8d4bcf9c24456ec5b4" +dependencies = [ + "tracing", + "tracing-test", +] + +[[package]] +name = "nym-compact-ecash" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7b16d668667605e169f8bd3c24e042cceb71ba7fc5a34003968e07c061f526" +dependencies = [ + "bincode 1.3.3", + "bs58", + "cfg-if 1.0.4", + "digest 0.10.7", + "ff", + "group", + "itertools 0.14.0", + "nym-bls12_381-fork", + "nym-network-defaults", + "nym-pemstore", + "rand 0.8.7", + "serde", + "sha2 0.10.9", + "subtle 2.6.1", + "thiserror 2.0.20", + "zeroize", +] + +[[package]] +name = "nym-config" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23121334a10c436687bf245e025d3abefc214333bf944cbef0b3f1e1edc81dde" +dependencies = [ + "dirs", + "handlebars", + "log", + "nym-network-defaults", + "serde", + "thiserror 2.0.20", + "toml 0.8.23", + "url", +] + +[[package]] +name = "nym-contracts-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bbdbc5257fc56ca3517a54416a6f291d8107ef20219aa348db061187d717ae6" +dependencies = [ + "bs58", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars 0.8.22", + "serde", + "thiserror 2.0.20", + "vergen", +] + +[[package]] +name = "nym-credential-storage" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9ccecdc1977edcdd94dcf2b49e95afeb57d9816984cf28127390685a4fd03b4" +dependencies = [ + "anyhow", + "async-trait", + "bincode 1.3.3", + "log", + "nym-compact-ecash", + "nym-credentials", + "nym-ecash-time", + "nym-sqlx-pool-guard", + "serde", + "sqlx", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "zeroize", +] + +[[package]] +name = "nym-credentials" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d5f60c4e2d8270fddd42d17d3c5808894db0a40feaa66e5eb5b245a4a8158c" +dependencies = [ + "bincode 1.3.3", + "cosmrs", + "log", + "nym-api-requests", + "nym-bls12_381-fork", + "nym-credentials-interface", + "nym-crypto", + "nym-ecash-contract-common", + "nym-ecash-time", + "nym-http-api-client", + "nym-network-defaults", + "nym-serde-helpers", + "nym-validator-client", + "serde", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "nym-credentials-interface" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c465a30e5da730d165ced8687b412fd8d9d0000aafbbcfb703d2819e2e153ad7" +dependencies = [ + "nym-bls12_381-fork", + "nym-compact-ecash", + "nym-ecash-time", + "nym-network-defaults", + "nym-upgrade-mode-check", + "rand 0.8.7", + "serde", + "strum 0.28.0", + "strum_macros 0.28.0", + "thiserror 2.0.20", + "time", + "utoipa", +] + +[[package]] +name = "nym-crypto" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68239d34fe7cd2e8a6466fb3ba7e2cf882a142bbb107564e91b37c88d8f7f848" +dependencies = [ + "aead", + "aes", + "aes-gcm-siv", + "base64 0.22.1", + "blake3", + "bs58", + "cipher", + "ctr", + "curve25519-dalek", + "digest 0.10.7", + "ed25519-dalek", + "generic-array 0.14.7", + "hkdf", + "hmac 0.12.1", + "jwt-simple", + "libcrux-curve25519", + "libcrux-psq", + "nym-pemstore", + "nym-sphinx-types", + "rand 0.8.7", + "rand 0.9.2", + "serde", + "serde_bytes", + "sha2 0.10.9", + "subtle-encoding", + "thiserror 2.0.20", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "nym-ecash-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecc5965728a01dea0ee49e509462e2d6af0df64f536c0563533a7c577a20d1e" +dependencies = [ + "bs58", + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "cw-utils", + "nym-multisig-contract-common", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-ecash-signer-check-types" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a03b087f01cd6f3233cfd212125fe43d9d02bc31a93c0a8a8e88de76b70349fc" +dependencies = [ + "nym-coconut-dkg-common", + "nym-crypto", + "semver", + "serde", + "thiserror 2.0.20", + "time", + "tracing", + "url", + "utoipa", +] + +[[package]] +name = "nym-ecash-time" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef78acc74b3937e56a1ff89532bb7008446273ab553c4bc790fd038b9733b125" +dependencies = [ + "nym-compact-ecash", + "time", +] + +[[package]] +name = "nym-exit-policy" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd4a35f55e8827bfef0f8985f853d099c204c2d9ff6dcfdeb6714b418f4b1aa" +dependencies = [ + "serde", + "serde_json", + "thiserror 2.0.20", + "tracing", + "utoipa", +] + +[[package]] +name = "nym-gateway-client" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf02926f89ac4041bf296120555025b83d956b481de92583fe4d101611c5a9d0" +dependencies = [ + "futures", + "getrandom 0.2.17", + "gloo-utils", + "nym-bandwidth-controller", + "nym-credential-storage", + "nym-credentials", + "nym-credentials-interface", + "nym-crypto", + "nym-gateway-requests", + "nym-http-api-client", + "nym-network-defaults", + "nym-pemstore", + "nym-sphinx", + "nym-statistics-common", + "nym-task", + "nym-validator-client", + "nym-wasm-utils", + "rand 0.8.7", + "serde", + "si-scale", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tokio-stream", + "tokio-tungstenite 0.20.1", + "tracing", + "tungstenite 0.20.1", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "nym-gateway-requests" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea2df0c26283ef5a931d5c8152be73256d4244b3cc4942f69a4debd4c4489bd" +dependencies = [ + "bs58", + "futures", + "generic-array 0.14.7", + "nym-credentials", + "nym-credentials-interface", + "nym-crypto", + "nym-pemstore", + "nym-serde-helpers", + "nym-sphinx", + "nym-statistics-common", + "nym-task", + "rand 0.8.7", + "serde", + "serde_json", + "strum 0.28.0", + "subtle 2.6.1", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tracing", + "tungstenite 0.20.1", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "nym-group-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672283855ef91508e9c6691ef9603724bfc4096b213046528ea3c78d334e6621" +dependencies = [ + "cosmwasm-schema", + "cw-controllers", + "cw4", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "nym-http-api-client" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d1771770edc8abc26a263cda72bfe0b593e4a9239e3735283c989dbbc9c813e" +dependencies = [ + "async-trait", + "bincode 1.3.3", + "bytes 1.12.1", + "cfg-if 1.0.4", + "encoding_rs", + "fastrand", + "hickory-resolver 0.26.1", + "http 1.5.0", + "inventory", + "itertools 0.14.0", + "mime", + "nym-bin-common", + "nym-http-api-client-macro", + "nym-http-api-common", + "nym-network-defaults", + "once_cell", + "reqwest 0.13.4", + "rustls 0.23.43", + "serde", + "serde_json", + "serde_plain", + "serde_yaml", + "thiserror 2.0.20", + "tokio 1.53.1", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "nym-http-api-client-macro" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28742422719d105dfcff097b2585d94c04e58765fde4c27565765dc680273c1" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.119", + "uuid", +] + +[[package]] +name = "nym-http-api-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cef7587b22202ea33002ce9193132a5c9b9297b0624f112ba148e4607e8552a" +dependencies = [ + "bincode 1.3.3", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "nym-id" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9671c5f11681ba76f212038a93209f74b2fa66baac33634cb2de109fccab7883" +dependencies = [ + "nym-credential-storage", + "nym-credentials", + "thiserror 2.0.20", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "nym-ip-packet-requests" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9772d0cf96057c947cc86d2ce6b8d56b94d0abae57ea34bd94841f5f257c2f1" +dependencies = [ + "bincode 1.3.3", + "bytes 1.12.1", + "nym-bin-common", + "nym-crypto", + "nym-service-provider-requests-common", + "nym-sphinx", + "rand 0.8.7", + "semver", + "serde", + "thiserror 2.0.20", + "time", + "tokio-util", + "tracing", +] + +[[package]] +name = "nym-kkt-ciphersuite" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bff733d374c2264b60705707fe306c0c231bd256068be932c87ef434d5f54c7" +dependencies = [ + "num_enum", + "semver", + "strum 0.28.0", + "strum_macros 0.28.0", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-lp-data" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc81040291e01350fd6f0371cb551d8b03b69cc7d4e10c6696726835e21c8083" +dependencies = [ + "bytes 1.12.1", + "num_enum", + "nym-common", + "thiserror 2.0.20", + "tracing", +] + +[[package]] +name = "nym-metrics" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24433af60e2abadd0c7a728a6cf2e9b61537714a2fb282457fc9d8eb33183926" +dependencies = [ + "dashmap", + "lazy_static", + "prometheus", + "tracing", +] + +[[package]] +name = "nym-mixnet-client" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afbd687c1a2efbb0b649903fb52142ea8fa98f3ae11347e097cfe321849fa51" +dependencies = [ + "dashmap", + "futures", + "nym-metrics", + "nym-noise", + "nym-sphinx", + "nym-task", + "strum 0.28.0", + "tokio 1.53.1", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "nym-mixnet-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791119f19116035b8da11a370043fe85b27098cdb475dddda8eb5bbf7c15367d" +dependencies = [ + "bs58", + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "cw-storage-plus", + "humantime-serde", + "nym-contracts-common", + "schemars 0.8.22", + "semver", + "serde", + "serde_repr", + "thiserror 2.0.20", + "time", + "utoipa", +] + +[[package]] +name = "nym-multisig-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ec5cffa1114347257dfe85a3ff23ebabc4b867fdb3aac3a124d6ae7d3ed4ee5" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "cw3", + "cw4", + "schemars 0.8.22", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-network-defaults" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c45969d6fc8b30212b0eda5fa56979e0f73fd6c5a484bb3ae5f330ec6d2c2578" +dependencies = [ + "cargo_metadata 0.19.2", + "dotenvy", + "regex", + "schemars 0.8.22", + "serde", + "serde_json", + "tracing", + "url", + "utoipa", +] + +[[package]] +name = "nym-network-monitors-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc60cd2a91f5b1ff5236b568ec5704122c04f455f31c304b7cb8346f3438957a" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "schemars 0.8.22", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-node-families-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b50d4e86876758082b4cc419a07c3c6345a65dcaf6b27c6bd426bd4807245" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "cw-utils", + "nym-contracts-common", + "nym-mixnet-contract-common", + "schemars 0.8.22", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-node-requests" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a4c0f6b105ea8036239e74fabc675ac26fa78812743cc852cf946fe367de6b6" +dependencies = [ + "celes", + "humantime-serde", + "nym-bin-common", + "nym-crypto", + "nym-exit-policy", + "nym-kkt-ciphersuite", + "nym-noise-keys", + "nym-upgrade-mode-check", + "nym-wireguard-types", + "schemars 0.8.22", + "serde", + "serde_json", + "strum 0.28.0", + "strum_macros 0.28.0", + "thiserror 2.0.20", + "time", + "url", + "utoipa", +] + +[[package]] +name = "nym-noise" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef0bd70a07992534ccd86e93beda66833a006b51f0eeb97440c689a61144d301" +dependencies = [ + "arc-swap", + "bytes 1.12.1", + "futures", + "nym-crypto", + "nym-noise-keys", + "pin-project", + "sha2 0.10.9", + "snow", + "strum 0.28.0", + "strum_macros 0.28.0", + "thiserror 2.0.20", + "tokio 1.53.1", + "tokio-util", + "tracing", +] + +[[package]] +name = "nym-noise-keys" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a44e87b9731d1116c9cc53c5bb618d03e2270467b5cd72b0894f95849711246" +dependencies = [ + "nym-crypto", + "schemars 0.8.22", + "serde", + "utoipa", +] + +[[package]] +name = "nym-nonexhaustive-delayqueue" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c223c79726d0dac5f9d109f597b388d09e929f00bcbc6dbbea348aea1a1c5f7" +dependencies = [ + "tokio 1.53.1", + "tokio-stream", + "tokio-util", + "wasmtimer", +] + +[[package]] +name = "nym-ordered-buffer" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc602f0686601988fe173da51560dd8274b3ad26de4127be9000efb304af2ec" +dependencies = [ + "log", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-outfox" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88e213f3edfe77ec6f6fcc19d5dadf953ed8f9b23176c1113817a5c1bde527ee" +dependencies = [ + "blake3", + "chacha20 0.9.1", + "chacha20poly1305", + "sphinx-packet", + "thiserror 2.0.20", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "nym-pemstore" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d50e6593d3576a4d6ea75acf1b18a11fb4b8eb310fdf057c746eb19895db0c6" +dependencies = [ + "pem 0.8.3", + "tracing", + "zeroize", +] + +[[package]] +name = "nym-performance-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3953bbfd384b4996d1a8b69c4277551c07e65eb2877d198c51b1b007eed3d8ca" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "nym-contracts-common", + "schemars 0.8.22", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sdk" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bfd4d9b28599f19ce6b4c4af2c34fdc5dc5ac3f8b8ca6313620bba61e34da92" +dependencies = [ + "anyhow", + "async-trait", + "bincode 1.3.3", + "bip39", + "bytecodec", + "bytes 1.12.1", + "celes", + "clap", + "dashmap", + "dirs", + "futures", + "http 1.5.0", + "httpcodec", + "log", + "nym-bandwidth-controller", + "nym-bandwidth-fetcher", + "nym-bin-common", + "nym-client-core", + "nym-credential-storage", + "nym-credentials", + "nym-credentials-interface", + "nym-crypto", + "nym-gateway-requests", + "nym-http-api-client", + "nym-ip-packet-requests", + "nym-lp-data", + "nym-network-defaults", + "nym-ordered-buffer", + "nym-service-providers-common", + "nym-socks5-client-core", + "nym-socks5-requests", + "nym-sphinx", + "nym-sphinx-addressing", + "nym-statistics-common", + "nym-task", + "nym-topology", + "nym-validator-client", + "rand 0.8.7", + "semver", + "serde", + "tap", + "tempfile", + "thiserror 2.0.20", + "tokio 1.53.1", + "tokio-stream", + "tokio-util", + "toml 0.8.23", + "tracing", + "tracing-subscriber", + "url", + "uuid", + "zeroize", +] + +[[package]] +name = "nym-serde-helpers" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686092ef8dde5c8d2adba23938eb5823aebc87dd03bb64d0b737907b19203219" +dependencies = [ + "base64 0.22.1", + "bs58", + "hex", + "serde", + "time", +] + +[[package]] +name = "nym-service-provider-requests-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eff3b3158a0788e8a8664aac3f3283515df105652b0e2ba6443db18475b2d43" +dependencies = [ + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-service-providers-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f849f42088d287544ed807cf286bafc53d16005756055d2e0dd87e80985255d8" +dependencies = [ + "async-trait", + "log", + "nym-bin-common", + "nym-client-core", + "nym-credential-storage", + "nym-sphinx-anonymous-replies", + "serde", + "serde_json", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-smol-core" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76deaeace70d8d8d13897d3c264e9f086a30e2eef0b254dfe4b9ddfad3e6ff2" +dependencies = [ + "futures", + "hickory-proto 0.26.1", + "rand 0.8.7", + "smoltcp", + "thiserror 2.0.20", + "tokio 1.53.1", + "tokio-smoltcp", + "tracing", +] + +[[package]] +name = "nym-smolmix" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fad2640c1addf9c53ed7746f89a8ca4bc54f03f8b85978048333e6d49148378" +dependencies = [ + "futures", + "nym-ip-packet-requests", + "nym-sdk", + "nym-smol-core", + "thiserror 2.0.20", + "tokio 1.53.1", + "tracing", +] + +[[package]] +name = "nym-socks5-client-core" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabc7a0282b7f4a65dd282e86c7ee187266d68fcfd4587a8f73f396d8eab2676" +dependencies = [ + "anyhow", + "dirs", + "futures", + "log", + "nym-bandwidth-controller", + "nym-client-core", + "nym-config", + "nym-contracts-common", + "nym-credential-storage", + "nym-mixnet-contract-common", + "nym-network-defaults", + "nym-service-providers-common", + "nym-socks5-proxy-helpers", + "nym-socks5-requests", + "nym-sphinx", + "nym-task", + "nym-validator-client", + "pin-project", + "rand 0.8.7", + "reqwest 0.13.4", + "schemars 0.8.22", + "serde", + "tap", + "thiserror 2.0.20", + "tokio 1.53.1", + "url", +] + +[[package]] +name = "nym-socks5-proxy-helpers" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3d364ac72801b0709a66f2f6cd4669e2b15b7fa84db0804ac9b1606bf6b9fa" +dependencies = [ + "bytes 1.12.1", + "futures", + "log", + "nym-ordered-buffer", + "nym-socks5-requests", + "nym-task", + "tokio 1.53.1", + "tokio-util", +] + +[[package]] +name = "nym-socks5-requests" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a5f69e8fd659c1b8dd78f2d8b56116a514e920bd8defd5b17d50e0b3de5a86" +dependencies = [ + "bincode 1.3.3", + "log", + "nym-exit-policy", + "nym-service-providers-common", + "nym-sphinx-addressing", + "serde", + "serde_json", + "tap", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f6408ff12f15464896f441e800871c371e5c0fb6aa67e280d563d327ed1f11" +dependencies = [ + "nym-crypto", + "nym-metrics", + "nym-sphinx-acknowledgements", + "nym-sphinx-addressing", + "nym-sphinx-anonymous-replies", + "nym-sphinx-chunking", + "nym-sphinx-cover", + "nym-sphinx-forwarding", + "nym-sphinx-framing", + "nym-sphinx-params", + "nym-sphinx-routing", + "nym-sphinx-types", + "nym-topology", + "rand 0.8.7", + "rand_chacha 0.3.1", + "rand_distr", + "thiserror 2.0.20", + "tokio 1.53.1", + "tracing", +] + +[[package]] +name = "nym-sphinx-acknowledgements" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87290cfbae2c4d7bd467ecdd3c2d0fd77639e4fba3cec1321249a663c638f4a" +dependencies = [ + "nym-crypto", + "nym-pemstore", + "nym-sphinx-addressing", + "nym-sphinx-params", + "nym-sphinx-routing", + "nym-sphinx-types", + "nym-topology", + "rand 0.8.7", + "thiserror 2.0.20", + "zeroize", +] + +[[package]] +name = "nym-sphinx-addressing" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d4fc0f52f98ca2687fa953c1e662e249a245c7247f63ddfe6673ea5e575f1" +dependencies = [ + "nym-crypto", + "nym-sphinx-types", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx-anonymous-replies" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e179b8cf3e80faab882fc45a8aa62c4b98bb3bfa41929b24480f748ea3d4b07" +dependencies = [ + "bs58", + "nym-crypto", + "nym-sphinx-addressing", + "nym-sphinx-params", + "nym-sphinx-routing", + "nym-sphinx-types", + "nym-topology", + "rand 0.8.7", + "thiserror 2.0.20", + "tracing", + "wasm-bindgen", +] + +[[package]] +name = "nym-sphinx-chunking" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ccdd2f5ea3e01232533c2ea96443167d9ba19739d7123f2e0a3a59a74d3284d" +dependencies = [ + "dashmap", + "log", + "nym-crypto", + "nym-metrics", + "nym-sphinx-addressing", + "nym-sphinx-params", + "nym-sphinx-types", + "rand 0.8.7", + "serde", + "thiserror 2.0.20", + "utoipa", + "wasmtimer", +] + +[[package]] +name = "nym-sphinx-cover" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a140768a4ab46b2cd09e0705176f75092c89dc1d7d8b0f82b6847a9337ca3e1c" +dependencies = [ + "nym-crypto", + "nym-sphinx-acknowledgements", + "nym-sphinx-addressing", + "nym-sphinx-chunking", + "nym-sphinx-forwarding", + "nym-sphinx-params", + "nym-sphinx-routing", + "nym-sphinx-types", + "nym-topology", + "rand 0.8.7", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx-forwarding" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb158025ddd1673386a9720e356cca54cda9616767b7e4b52eed9706f18f713" +dependencies = [ + "nym-sphinx-addressing", + "nym-sphinx-anonymous-replies", + "nym-sphinx-params", + "nym-sphinx-types", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx-framing" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b144b489f064cb975067a20aea444eb8b27a857a20fb4b92d8f3385543dbc1" +dependencies = [ + "bytes 1.12.1", + "cfg-if 1.0.4", + "nym-sphinx-acknowledgements", + "nym-sphinx-addressing", + "nym-sphinx-forwarding", + "nym-sphinx-params", + "nym-sphinx-types", + "thiserror 2.0.20", + "tokio-util", + "tracing", +] + +[[package]] +name = "nym-sphinx-params" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129783e1a323282b6ead73c5b63fdb5f4a91ab3ca9b01086d9a92d09474193b9" +dependencies = [ + "nym-crypto", + "nym-sphinx-types", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx-routing" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0349f3717adb3ca9a04842544b437de96a9344081491fc0090918c4f98f27f3" +dependencies = [ + "nym-sphinx-addressing", + "nym-sphinx-types", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sphinx-types" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61291728c8b76fa51bbe9c79ff59e9a7045a697e85d681cdca626ba88f905b25" +dependencies = [ + "nym-outfox", + "sphinx-packet", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-sqlx-pool-guard" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7a3b0bb293db74c461431dee5a2ec0c3c6aee71ed6bdf36591f7600c3cf179" +dependencies = [ + "proc_pidinfo", + "sqlx", + "tokio 1.53.1", + "tracing", + "windows 0.61.3", +] + +[[package]] +name = "nym-statistics-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b44425af9515a9331c9426b78465927a09b184de2dbf70d6cd6ef8e3d23e9e" +dependencies = [ + "futures", + "log", + "nym-credentials-interface", + "nym-crypto", + "nym-metrics", + "nym-sphinx", + "nym-task", + "serde", + "serde_json", + "sha2 0.10.9", + "si-scale", + "strum 0.28.0", + "strum_macros 0.28.0", + "sysinfo", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "wasmtimer", +] + +[[package]] +name = "nym-task" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd441e77598fabc888f3749f78e14d27afaa7ed739b871cc8caa599c85d1632" +dependencies = [ + "cfg-if 1.0.4", + "futures", + "log", + "thiserror 2.0.20", + "tokio 1.53.1", + "tokio-util", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasmtimer", +] + +[[package]] +name = "nym-ticketbooks-merkle" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f7d68b4028a8a53fc91cbb81faabc3876b9722010a1acd1c4b2e2f113b2c69" +dependencies = [ + "nym-credentials-interface", + "nym-serde-helpers", + "rs_merkle", + "schemars 0.8.22", + "serde", + "sha2 0.10.9", + "time", + "utoipa", +] + +[[package]] +name = "nym-topology" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c50d6ff07fe40c9b5b4868f345abc83114819712fff3636c042593b807bdc27d" +dependencies = [ + "async-trait", + "nym-api-requests", + "nym-crypto", + "nym-mixnet-contract-common", + "nym-sphinx-addressing", + "nym-sphinx-types", + "rand 0.8.7", + "reqwest 0.13.4", + "serde", + "serde_json", + "thiserror 2.0.20", + "time", + "tracing", +] + +[[package]] +name = "nym-upgrade-mode-check" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad735294a4beb9c6ae49d578ac1e2acb130efac72ce59b53284641ee36c96dde" +dependencies = [ + "jwt-simple", + "nym-crypto", + "nym-http-api-client", + "reqwest 0.13.4", + "serde", + "serde_json", + "thiserror 2.0.20", + "time", + "tracing", + "utoipa", +] + +[[package]] +name = "nym-validator-client" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552de46c1189d7c07057ffb0e8170f37e909487ef1002afd463b4a568aed8a11" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bip32 0.5.3", + "bip39", + "colored", + "cosmrs", + "cosmwasm-std", + "cw-controllers", + "cw-utils", + "cw2", + "cw3", + "cw4", + "eyre", + "flate2", + "futures", + "itertools 0.14.0", + "nym-api-requests", + "nym-coconut-dkg-common", + "nym-compact-ecash", + "nym-config", + "nym-contracts-common", + "nym-ecash-contract-common", + "nym-group-contract-common", + "nym-http-api-client", + "nym-mixnet-contract-common", + "nym-multisig-contract-common", + "nym-network-defaults", + "nym-network-monitors-contract-common", + "nym-node-families-contract-common", + "nym-performance-contract-common", + "nym-serde-helpers", + "nym-vesting-contract-common", + "prost 0.13.5", + "reqwest 0.13.4", + "serde", + "serde_json", + "sha2 0.10.9", + "tendermint-rpc", + "thiserror 2.0.20", + "time", + "tokio 1.53.1", + "tracing", + "url", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "nym-vesting-contract-common" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90cde8c1ca94076a741c40af7ccdfc9afd50e100632b8b8fcf42d30f207482" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "nym-contracts-common", + "nym-mixnet-contract-common", + "serde", + "thiserror 2.0.20", +] + +[[package]] +name = "nym-wasm-utils" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e8d1cda1f064e5ebe23e90d69b9b12fc20780f52e6e01033767d262f6a1dcf" +dependencies = [ + "futures", + "getrandom 0.2.17", + "gloo-net", + "gloo-utils", + "js-sys", + "tungstenite 0.20.1", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "nym-wireguard-types" +version = "1.21.5-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2435c1961a0bcf4e240cc3915c13daf815321f6c38ad4f0bbebf6e064f8db29" +dependencies = [ + "base64 0.22.1", + "nym-crypto", + "serde", + "thiserror 2.0.20", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "oneshot-fused-workaround" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2948fd2414b613f9a97f8401270bd5d7638265ab940475cdbcfa28a0273d58" +dependencies = [ + "futures", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -4680,6 +7697,12 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + [[package]] name = "openssl-probe" version = "0.2.1" @@ -4739,10 +7762,10 @@ dependencies = [ "rand 0.8.7", "rand_core 0.6.4", "reddsa", - "secp256k1", + "secp256k1 0.29.1", "serde", "sinsemilla", - "subtle", + "subtle 2.6.1", "tracing", "visibility", "zcash_note_encryption", @@ -4850,9 +7873,9 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if 1.0.4", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -4863,7 +7886,7 @@ checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -4878,7 +7901,7 @@ dependencies = [ "lazy_static", "rand 0.8.7", "static_assertions", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -4887,6 +7910,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "pbkdf2" version = "0.12.2" @@ -4915,7 +7944,7 @@ dependencies = [ "rand_core 0.6.4", "redjubjub", "sapling-crypto", - "secp256k1", + "secp256k1 0.29.1", "serde", "serde_with", "zcash_note_encryption", @@ -4925,6 +7954,44 @@ dependencies = [ "zcash_transparent", ] +[[package]] +name = "peg" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aad070be5b63aa72103f2fcdd70a83adbd5e90112ce5b574171ff1c65501773" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd8ef6825cae95355031ae26a99b616a2a21f22ba2de0197c43dfb05acbe7ee" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7011d97b484a5ebdc4b1fdb3b12d5e4bbbea56e9d22b688f2e79e04b65a7d8a6" + +[[package]] +name = "pem" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64 0.13.1", + "once_cell", + "regex", +] + [[package]] name = "pem" version = "3.0.6" @@ -4950,6 +8017,48 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" +dependencies = [ + "pest", +] + [[package]] name = "petgraph" version = "0.8.3" @@ -4967,8 +8076,19 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_macros", - "phf_shared", + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", ] [[package]] @@ -4977,18 +8097,41 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", "rand 0.8.7", ] +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared 0.13.1", +] + [[package]] name = "phf_macros" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.119", @@ -5003,6 +8146,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.13" @@ -5111,6 +8263,12 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "polling" version = "3.11.0" @@ -5132,7 +8290,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ "cpufeatures 0.2.17", - "opaque-debug", + "opaque-debug 0.3.1", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if 1.0.4", + "cpufeatures 0.2.17", + "opaque-debug 0.3.1", "universal-hash", ] @@ -5175,7 +8345,7 @@ dependencies = [ "cobs", "embedded-io 0.4.0", "embedded-io 0.6.1", - "heapless", + "heapless 0.7.17", "serde", ] @@ -5203,6 +8373,17 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prefix-trie" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -5273,6 +8454,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc_pidinfo" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29492a7b48a00ab80202528e235d2f80a04ccff3747540b4ec6881f2f2bc42d1" +dependencies = [ + "libc", +] + +[[package]] +name = "prometheus" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ca5326d8d0b950a9acd87e6a3f94745394f62e4dae1b1ee22b2bc0c394af43a" +dependencies = [ + "cfg-if 1.0.4", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "protobuf 3.7.2", + "thiserror 2.0.20", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes 1.12.1", + "prost-derive 0.13.5", +] + [[package]] name = "prost" version = "0.14.4" @@ -5280,7 +8495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes 1.12.1", - "prost-derive", + "prost-derive 0.14.4", ] [[package]] @@ -5295,13 +8510,26 @@ dependencies = [ "multimap", "petgraph", "prettyplease", - "prost", + "prost 0.14.4", "prost-types", "regex", "syn 2.0.119", "tempfile", ] +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "prost-derive" version = "0.14.4" @@ -5321,7 +8549,7 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ - "prost", + "prost 0.14.4", ] [[package]] @@ -5333,13 +8561,33 @@ dependencies = [ "bytes 0.5.6", ] +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + [[package]] name = "protobuf-codegen" version = "2.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49782fe28b5ff7d5d51cbfbe8985f3ff863acea663c515ed369c53f72e1d628" dependencies = [ - "protobuf", + "protobuf 2.18.2", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", ] [[package]] @@ -5358,7 +8606,7 @@ version = "2.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1463636fc5884879f810dfe1fa8e07c71fc90369553e9a572213839f175163a4" dependencies = [ - "protobuf", + "protobuf 2.18.2", "protobuf-codegen", "protoc", "tempfile", @@ -5371,7 +8619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41e2bf99ec0d82b0446a9bce1e0e69806dfff6112415c195f997e55a7afbdb6c" dependencies = [ "grpc-compiler", - "protobuf", + "protobuf 2.18.2", "protoc", "protoc-rust", "tempdir", @@ -5404,6 +8652,12 @@ dependencies = [ "image", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quinn" version = "0.11.11" @@ -5430,6 +8684,7 @@ version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ + "aws-lc-rs", "bytes 1.12.1", "getrandom 0.4.3", "lru-slab", @@ -5545,9 +8800,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.5" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -5624,7 +8879,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.3.3", ] [[package]] @@ -5633,6 +8888,16 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.7", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -5794,7 +9059,16 @@ dependencies = [ name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_syscall" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07507be7b4a5f9f26eeb41eeaebb1f5a7ff29dfb29739facc21d35bf8b11c21e" dependencies = [ "bitflags 2.13.1", ] @@ -5889,6 +9163,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", + "hyper-rustls 0.24.2", "hyper-tls", "ipnet", "js-sys", @@ -5898,14 +9173,17 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.17", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio 1.53.1", "tokio-native-tls", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", @@ -5927,7 +9205,7 @@ dependencies = [ "http-body 1.1.0", "http-body-util", "hyper 1.11.0", - "hyper-rustls", + "hyper-rustls 0.27.9", "hyper-util", "js-sys", "log", @@ -5941,7 +9219,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio 1.53.1", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower", "tower-http", "tower-service", @@ -5952,6 +9230,43 @@ dependencies = [ "webpki-roots 1.0.9", ] +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes 1.12.1", + "futures-core", + "http 1.5.0", + "http-body 1.1.0", + "http-body-util", + "hyper 1.11.0", + "hyper-rustls 0.27.9", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite 0.2.17", + "quinn", + "rustls 0.23.43", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper 1.0.2", + "tokio 1.53.1", + "tokio-rustls 0.26.4", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "resolv-conf" version = "0.7.6" @@ -5971,7 +9286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac 0.12.1", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -6046,8 +9361,9 @@ dependencies = [ "arti-client", "bech32 0.11.1", "bigdecimal", - "bincode", - "bip32", + "bincode 1.3.3", + "bincode 2.0.1", + "bip32 0.6.0-pre.1", "bip39", "blake2b_simd", "bs58", @@ -6070,8 +9386,8 @@ dependencies = [ "halo2_gadgets", "halo2_proofs", "hex", - "hickory-proto", - "hickory-resolver", + "hickory-proto 0.24.4", + "hickory-resolver 0.24.4", "hidapi", "hmac 0.12.1", "httparse", @@ -6088,9 +9404,12 @@ dependencies = [ "libsqlite3-sys", "log", "nonempty", + "nym-network-defaults", + "nym-sdk", + "nym-smolmix", "orchard", "pczt", - "prost", + "prost 0.14.4", "qrcode", "rand 0.6.5", "rand_core 0.6.4", @@ -6103,7 +9422,7 @@ dependencies = [ "ripemd 0.1.3", "rustls 0.23.43", "sapling-crypto", - "secp256k1", + "secp256k1 0.29.1", "serde", "serde_json", "serde_with", @@ -6111,7 +9430,7 @@ dependencies = [ "sqlx", "thiserror 2.0.20", "tokio 1.53.1", - "tokio-rustls", + "tokio-rustls 0.26.4", "tokio-socks", "tokio-stream", "tokio-util", @@ -6121,6 +9440,7 @@ dependencies = [ "tower", "tracing", "tracing-subscriber", + "uuid", "vcard4", "warp", "webpki-roots 1.0.9", @@ -6142,6 +9462,34 @@ dependencies = [ "zstd", ] +[[package]] +name = "rmp" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "rmp-serde" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" +dependencies = [ + "rmp", + "serde", +] + +[[package]] +name = "rs_merkle" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb09b49230ba22e8c676e7b75dfe2887dea8121f18b530ae0ba519ce442d2b21" +dependencies = [ + "sha2 0.10.9", +] + [[package]] name = "rsa" version = "0.9.10" @@ -6159,7 +9507,7 @@ dependencies = [ "sha2 0.10.9", "signature", "spki", - "subtle", + "subtle 2.6.1", "zeroize", ] @@ -6298,10 +9646,34 @@ dependencies = [ "ring", "rustls-pki-types", "rustls-webpki 0.103.14", - "subtle", + "subtle 2.6.1", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe 0.1.6", + "rustls-pemfile", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -6321,6 +9693,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.43", + "rustls-native-certs 0.8.4", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.14", + "security-framework 3.7.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -6361,7 +9760,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a4e1c994fbc7521a5003e5c1c54304654ea0458881e777f6e2638520c2de8c5" dependencies = [ - "derive_more", + "derive_more 2.1.1", "educe", "either", "fluid-let", @@ -6426,7 +9825,7 @@ dependencies = [ "rand 0.8.7", "rand_core 0.6.4", "redjubjub", - "subtle", + "subtle 2.6.1", "tracing", "zcash_note_encryption", "zcash_spec", @@ -6442,6 +9841,19 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", +] + [[package]] name = "schemars" version = "0.9.0" @@ -6466,6 +9878,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.119", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -6507,12 +9931,22 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", - "subtle", + "serdect 0.2.0", + "subtle 2.6.1", "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.2", +] + [[package]] name = "secp256k1" version = "0.29.1" @@ -6520,7 +9954,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "rand 0.8.7", - "secp256k1-sys", + "secp256k1-sys 0.10.1", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" +dependencies = [ + "cc", ] [[package]] @@ -6550,6 +9993,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -6593,6 +10049,10 @@ name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "serde" @@ -6604,6 +10064,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-json-wasm" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" +dependencies = [ + "serde", +] + [[package]] name = "serde-value" version = "0.7.0" @@ -6614,6 +10083,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -6634,6 +10113,17 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "serde_ignored" version = "0.1.14" @@ -6657,6 +10147,26 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_plain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "serde_spanned" version = "0.6.9" @@ -6711,6 +10221,19 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.14.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serdect" version = "0.2.0" @@ -6721,6 +10244,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1" version = "0.10.7" @@ -6732,6 +10265,19 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.4", + "cpufeatures 0.2.17", + "digest 0.9.0", + "opaque-debug 0.3.1", +] + [[package]] name = "sha2" version = "0.10.9" @@ -6802,6 +10348,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "si-scale" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa6635fb52805fa49a5798346e553cda9fd7990da8fbb2b3b2b9cf26589b4571" + [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -6828,6 +10380,22 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "simple_asn1" version = "0.6.4" @@ -6847,7 +10415,7 @@ source = "git+https://github.com/zcash/sinsemilla?rev=aabb707e862bc3d7b803c77d14 dependencies = [ "group", "pasta_curves", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -6906,6 +10474,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "smoltcp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if 1.0.4", + "defmt 0.3.100", + "heapless 0.8.0", + "libc", + "log", + "managed", +] + [[package]] name = "snafu" version = "0.7.5" @@ -6928,6 +10512,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "snow" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850948bee068e713b8ab860fe1adc4d109676ab4c3b621fd8147f06b261f2f85" +dependencies = [ + "aes-gcm", + "blake2 0.10.6", + "chacha20poly1305", + "curve25519-dalek", + "rand_core 0.6.4", + "rustc_version", + "sha2 0.10.9", + "subtle 2.6.1", +] + [[package]] name = "socket2" version = "0.5.10" @@ -6948,6 +10548,32 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "sphinx-packet" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c26f0c20d909fdda1c5d0ece3973127ca421984d55b000215df365e93722fc6e" +dependencies = [ + "aes", + "arrayref", + "blake2 0.8.1", + "bs58", + "byteorder", + "chacha", + "ctr", + "curve25519-dalek", + "digest 0.10.7", + "hkdf", + "hmac 0.12.1", + "lioness", + "rand 0.8.7", + "rand_distr", + "sha2 0.10.9", + "subtle 2.6.1", + "x25519-dalek", + "zeroize", +] + [[package]] name = "spin" version = "0.5.2" @@ -6981,6 +10607,8 @@ checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", "sqlx-sqlite", ] @@ -7007,14 +10635,18 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", + "rustls 0.23.43", "serde", + "serde_json", "sha2 0.10.9", "smallvec", "thiserror 2.0.20", + "time", "tokio 1.53.1", "tokio-stream", "tracing", "url", + "webpki-roots 0.26.11", ] [[package]] @@ -7047,12 +10679,95 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", "sqlx-sqlite", "syn 2.0.119", "tokio 1.53.1", "url", ] +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.13.1", + "byteorder", + "bytes 1.12.1", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array 0.14.7", + "hex", + "hkdf", + "hmac 0.12.1", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.7", + "rsa", + "serde", + "sha1", + "sha2 0.10.9", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.20", + "time", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.13.1", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac 0.12.1", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.7", + "serde", + "serde_json", + "sha2 0.10.9", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.20", + "time", + "tracing", + "whoami", +] + [[package]] name = "sqlx-sqlite" version = "0.8.6" @@ -7073,6 +10788,7 @@ dependencies = [ "serde_urlencoded", "sqlx-core", "thiserror 2.0.20", + "time", "tracing", "url", ] @@ -7114,7 +10830,7 @@ dependencies = [ "signature", "ssh-cipher", "ssh-encoding", - "subtle", + "subtle 2.6.1", "zeroize", ] @@ -7130,6 +10846,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.10.0" @@ -7148,7 +10875,16 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "strum_macros", + "strum_macros 0.27.2", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", ] [[package]] @@ -7163,12 +10899,58 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[package]] +name = "superboring" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b18b68ed406060b46bc747143b771e4a1f8ee95b076ac4759a329871b5b427" +dependencies = [ + "getrandom 0.2.17", + "hmac-sha256", + "hmac-sha512", + "rand 0.8.7", + "rsa", +] + [[package]] name = "syn" version = "1.0.109" @@ -7228,6 +11010,20 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "sysinfo" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.62.2", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -7236,7 +11032,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -7249,6 +11056,22 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -7278,6 +11101,98 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tendermint" +version = "0.40.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc997743ecfd4864bbca8170d68d9b2bee24653b034210752c2d883ef4b838b1" +dependencies = [ + "bytes 1.12.1", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256", + "num-traits", + "once_cell", + "prost 0.13.5", + "ripemd 0.1.3", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.9", + "signature", + "subtle 2.6.1", + "subtle-encoding", + "tendermint-proto", + "time", + "zeroize", +] + +[[package]] +name = "tendermint-config" +version = "0.40.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069d1791f9b02a596abcd26eb72003b2e9906c6169a60fa82ffc080dd3a43fda" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint", + "toml 0.8.23", + "url", +] + +[[package]] +name = "tendermint-proto" +version = "0.40.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c40e13d39ca19082d8a7ed22de7595979350319833698f8b1080f29620a094" +dependencies = [ + "bytes 1.12.1", + "flex-error", + "prost 0.13.5", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-rpc" +version = "0.40.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e0569a4b4cc42ff00df5a665be2858a39ff79df4790b176f1cd0e169bc0fc2" +dependencies = [ + "async-trait", + "bytes 1.12.1", + "flex-error", + "futures", + "getrandom 0.2.17", + "peg", + "pin-project", + "rand 0.8.7", + "reqwest 0.11.27", + "semver", + "serde", + "serde_bytes", + "serde_json", + "subtle 2.6.1", + "subtle-encoding", + "tendermint", + "tendermint-config", + "tendermint-proto", + "thiserror 1.0.69", + "time", + "tokio 1.53.1", + "tracing", + "url", + "uuid", + "walkdir", +] + [[package]] name = "thin-vec" version = "0.2.19" @@ -7352,7 +11267,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", + "js-sys", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -7431,6 +11349,27 @@ dependencies = [ "void", ] +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "tokio" version = "0.2.25" @@ -7485,6 +11424,16 @@ dependencies = [ "tokio 1.53.1", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio 1.53.1", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -7495,6 +11444,20 @@ dependencies = [ "tokio 1.53.1", ] +[[package]] +name = "tokio-smoltcp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f5d53da1c3095663a8900d86c2abb0ffe02d3f6aa86527b066148fcb33e65e" +dependencies = [ + "futures", + "parking_lot", + "pin-project-lite 0.2.17", + "smoltcp", + "tokio 1.53.1", + "tokio-util", +] + [[package]] name = "tokio-socks" version = "0.5.3" @@ -7516,6 +11479,22 @@ dependencies = [ "futures-core", "pin-project-lite 0.2.17", "tokio 1.53.1", + "tokio-util", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "tokio 1.53.1", + "tokio-rustls 0.24.1", + "tungstenite 0.20.1", + "webpki-roots 0.25.4", ] [[package]] @@ -7527,7 +11506,7 @@ dependencies = [ "futures-util", "log", "tokio 1.53.1", - "tungstenite", + "tungstenite 0.29.0", ] [[package]] @@ -7540,9 +11519,35 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", + "futures-util", "libc", "pin-project-lite 0.2.17", + "slab", + "tokio 1.53.1", +] + +[[package]] +name = "tokio_with_wasm" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34e40fbbbd95441133fe9483f522db15dbfd26dc636164ebd8f2dd28759a6aa6" +dependencies = [ + "js-sys", "tokio 1.53.1", + "tokio_with_wasm_proc", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "tokio_with_wasm_proc" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" +dependencies = [ + "quote", + "syn 2.0.119", ] [[package]] @@ -7647,7 +11652,7 @@ dependencies = [ "socket2 0.6.5", "sync_wrapper 1.0.2", "tokio 1.53.1", - "tokio-rustls", + "tokio-rustls 0.26.4", "tokio-stream", "tower", "tower-layer", @@ -7675,7 +11680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes 1.12.1", - "prost", + "prost 0.14.4", "tonic", ] @@ -7717,12 +11722,12 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33dafd99d3b6312c08c3f065dc4cffb664b6a507bb8360eb875621b130990489" dependencies = [ - "derive_more", + "derive_more 2.1.1", "hex", "itertools 0.14.0", "libc", "paste", - "rand 0.9.5", + "rand 0.9.2", "rand_chacha 0.9.0", "serde", "slab", @@ -7740,7 +11745,7 @@ dependencies = [ "derive-deftly", "digest 0.10.7", "educe", - "getrandom 0.3.4", + "getrandom 0.3.3", "safelog", "thiserror 2.0.20", "tor-error", @@ -7759,10 +11764,10 @@ dependencies = [ "bytes 1.12.1", "caret", "derive-deftly", - "derive_more", + "derive_more 2.1.1", "educe", "paste", - "rand 0.9.5", + "rand 0.9.2", "smallvec", "thiserror 2.0.20", "tor-basic-utils", @@ -7786,7 +11791,7 @@ checksum = "d74bedc43ceb07c10ad01df76c5a935272877be7044ba5529b05420fa05b223d" dependencies = [ "caret", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "thiserror 2.0.20", "tor-bytes", @@ -7803,12 +11808,12 @@ dependencies = [ "async-trait", "caret", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "educe", "futures", "oneshot-fused-workaround", "postage", - "rand 0.9.5", + "rand 0.9.2", "safelog", "serde", "thiserror 2.0.20", @@ -7852,7 +11857,7 @@ dependencies = [ "bounded-vec-deque", "cfg-if 1.0.4", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "downcast-rs", "dyn-clone", "educe", @@ -7862,7 +11867,7 @@ dependencies = [ "once_cell", "oneshot-fused-workaround", "pin-project", - "rand 0.9.5", + "rand 0.9.2", "retry-error", "safelog", "serde", @@ -7913,7 +11918,7 @@ dependencies = [ "serde", "serde-value", "serde_ignored", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "toml 0.8.23", "tor-basic-utils", @@ -7958,7 +11963,7 @@ checksum = "1ef2209ceb4db6f7586a418570be4927b8f3d1a3ece31b0e128bc198a51ab117" dependencies = [ "async-compression", "base64ct", - "derive_more", + "derive_more 2.1.1", "futures", "hex", "http 1.5.0", @@ -7987,7 +11992,7 @@ dependencies = [ "async-trait", "base64ct", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "educe", "event-listener 5.4.2", @@ -8003,7 +12008,7 @@ dependencies = [ "oneshot-fused-workaround", "paste", "postage", - "rand 0.9.5", + "rand 0.9.2", "rusqlite", "safelog", "scopeguard", @@ -8011,7 +12016,7 @@ dependencies = [ "serde_json", "signature", "static_assertions", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "time", "tor-async-utils", @@ -8039,13 +12044,13 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fcc0b0b90078f705362335aee2ddf10a68108694ee4f063778c14eaf6fcca3" dependencies = [ - "derive_more", + "derive_more 2.1.1", "futures", "once_cell", "paste", "retry-error", "static_assertions", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "tracing", "void", @@ -8057,7 +12062,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be71b2de02947b2f8711881fe7262002b8ac2c7283937c8d7144d0a902ce7fe2" dependencies = [ - "derive_more", + "derive_more 2.1.1", "thiserror 2.0.20", "void", ] @@ -8072,7 +12077,7 @@ dependencies = [ "base64ct", "derive-deftly", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "dyn-clone", "educe", "futures", @@ -8083,10 +12088,10 @@ dependencies = [ "oneshot-fused-workaround", "pin-project", "postage", - "rand 0.9.5", + "rand 0.9.2", "safelog", "serde", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", @@ -8112,18 +12117,18 @@ checksum = "7c01d21f9a290b97fd6fb4b68e5f0eafc92ef61a47dd4fae6f3fbcbe0a2e449f" dependencies = [ "async-trait", "derive-deftly", - "derive_more", + "derive_more 2.1.1", "educe", "either", "futures", "itertools 0.14.0", "oneshot-fused-workaround", "postage", - "rand 0.9.5", + "rand 0.9.2", "retry-error", "safelog", "slotmap-careful", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "tor-async-utils", "tor-basic-utils", @@ -8156,17 +12161,17 @@ checksum = "6bdf871ea7ef6df765f24d79d74b06f7387803f50e36c96015862b2efe5a5f1b" dependencies = [ "data-encoding", "derive-deftly", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "hex", "humantime", "itertools 0.14.0", "paste", - "rand 0.9.5", + "rand 0.9.2", "safelog", "serde", "signature", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", @@ -8185,10 +12190,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59e00ceba887c2441c642354f58cd7bac9efac87107e715d465afa262a9ccdea" dependencies = [ "derive-deftly", - "derive_more", + "derive_more 2.1.1", "downcast-rs", "paste", - "rand 0.9.5", + "rand 0.9.2", "signature", "ssh-key", "thiserror 2.0.20", @@ -8210,7 +12215,7 @@ dependencies = [ "cfg-if 1.0.4", "derive-deftly", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "downcast-rs", "dyn-clone", "fs-mistrust", @@ -8218,7 +12223,7 @@ dependencies = [ "humantime", "inventory", "itertools 0.14.0", - "rand 0.9.5", + "rand 0.9.2", "serde", "signature", "ssh-key", @@ -8248,13 +12253,13 @@ dependencies = [ "caret", "derive-deftly", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "hex", "itertools 0.14.0", "safelog", "serde", "serde_with", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "tor-basic-utils", "tor-bytes", @@ -8276,14 +12281,14 @@ dependencies = [ "curve25519-dalek", "der-parser", "derive-deftly", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "ed25519-dalek", "educe", - "getrandom 0.3.4", + "getrandom 0.3.3", "hex", "once_cell", - "rand 0.9.5", + "rand 0.9.2", "rand_chacha 0.9.0", "rand_core 0.6.4", "rand_core 0.9.5", @@ -8296,7 +12301,7 @@ dependencies = [ "sha2 0.10.9", "sha3", "signature", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "tor-memquota", "visibility", @@ -8327,7 +12332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ee8a33267e80ba58c727fe00e2315a4b98699ea69bd4b1b41121b1346a06f4" dependencies = [ "derive-deftly", - "derive_more", + "derive_more 2.1.1", "dyn-clone", "educe", "futures", @@ -8356,17 +12361,17 @@ checksum = "d02a187a1d620a53f2b05ea5e7f5a02991fa5fd560b1b25a536c931f74e47aa8" dependencies = [ "async-trait", "bitflags 2.13.1", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "futures", "hex", "humantime", "itertools 0.14.0", "num_enum", - "rand 0.9.5", + "rand 0.9.2", "serde", "static_assertions", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "time", "tor-basic-utils", @@ -8392,7 +12397,7 @@ dependencies = [ "bitflags 2.13.1", "cipher", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "educe", "hex", @@ -8400,13 +12405,13 @@ dependencies = [ "itertools 0.14.0", "memchr", "once_cell", - "phf", - "rand 0.9.5", + "phf 0.11.3", + "rand 0.9.2", "serde", "serde_with", "signature", "smallvec", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "time", "tinystr", @@ -8433,7 +12438,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "633386d7a4ff47da9d2e7cac67ac3aa4d0054366d848b2c09d553237bd02b0cb" dependencies = [ "derive-deftly", - "derive_more", + "derive_more 2.1.1", "filetime", "fs-mistrust", "fslock", @@ -8469,7 +12474,7 @@ dependencies = [ "coarsetime", "derive-deftly", "derive_builder_fork_arti", - "derive_more", + "derive_more 2.1.1", "digest 0.10.7", "educe", "futures", @@ -8479,12 +12484,12 @@ dependencies = [ "itertools 0.14.0", "oneshot-fused-workaround", "pin-project", - "rand 0.9.5", + "rand 0.9.2", "rand_core 0.9.5", "safelog", "slotmap-careful", "static_assertions", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "tokio 1.53.1", "tokio-util", @@ -8531,7 +12536,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49c52c8c32ee42b02da8e5e94258b7bc136a41ea944ed20f74764c2deafbc3c3" dependencies = [ - "rand 0.9.5", + "rand 0.9.2", "serde", "tor-basic-utils", "tor-linkspec", @@ -8550,7 +12555,7 @@ dependencies = [ "async_executors", "asynchronous-codec", "coarsetime", - "derive_more", + "derive_more 2.1.1", "dyn-clone", "educe", "futures", @@ -8578,7 +12583,7 @@ dependencies = [ "assert_matches", "async-trait", "derive-deftly", - "derive_more", + "derive_more 2.1.1", "educe", "futures", "humantime", @@ -8587,7 +12592,7 @@ dependencies = [ "pin-project", "priority-queue", "slotmap-careful", - "strum", + "strum 0.27.2", "thiserror 2.0.20", "tor-error", "tor-general-addr", @@ -8608,7 +12613,7 @@ dependencies = [ "derive-deftly", "educe", "safelog", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "tor-bytes", "tor-error", @@ -8621,7 +12626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7acec20a7aafddf9f399bd32e4ff70e25144fcb5da298e0331504522bcb77f0" dependencies = [ "derive-deftly", - "derive_more", + "derive_more 2.1.1", "serde", "thiserror 2.0.20", "tor-memquota", @@ -8652,12 +12657,17 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ + "async-compression", "bitflags 2.13.1", "bytes 1.12.1", + "futures-core", "futures-util", "http 1.5.0", "http-body 1.1.0", + "http-body-util", "pin-project-lite 0.2.17", + "tokio 1.53.1", + "tokio-util", "tower", "tower-layer", "tower-service", @@ -8772,12 +12782,62 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "trackable" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98abb9e7300b9ac902cc04920945a874c1973e08c310627cc4458c04b70dd32" +dependencies = [ + "trackable 1.3.0", + "trackable_derive", +] + +[[package]] +name = "trackable" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15bd114abb99ef8cee977e517c8f37aee63f184f2d08e3e6ceca092373369ae" +dependencies = [ + "trackable_derive", +] + +[[package]] +name = "trackable_derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes 1.12.1", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.7", + "rustls 0.21.12", + "sha1", + "thiserror 1.0.69", + "url", + "utf-8", + "webpki-roots 0.24.0", +] + [[package]] name = "tungstenite" version = "0.29.0" @@ -8789,7 +12849,7 @@ dependencies = [ "http 1.5.0", "httparse", "log", - "rand 0.9.5", + "rand 0.9.2", "sha1", "thiserror 2.0.20", ] @@ -8815,6 +12875,12 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "udev" version = "0.9.3" @@ -8873,6 +12939,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" @@ -8888,6 +12960,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-segmentation" version = "1.13.3" @@ -8907,7 +12985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common 0.1.7", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -8920,6 +12998,12 @@ dependencies = [ "libc", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" @@ -8958,8 +13042,15 @@ dependencies = [ "idna", "percent-encoding", "serde", + "serde_derive", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -8972,6 +13063,41 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "utoipa" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "uuid" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", +] + [[package]] name = "valar-spiral-rs" version = "0.5.2" @@ -8984,7 +13110,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde_json", "sha2 0.10.9", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -9038,6 +13164,21 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "8.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +dependencies = [ + "anyhow", + "cargo_metadata 0.18.1", + "cfg-if 1.0.4", + "regex", + "rustc_version", + "rustversion", + "time", +] + [[package]] name = "version_check" version = "0.9.5" @@ -9161,7 +13302,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio 1.53.1", - "tokio-tungstenite", + "tokio-tungstenite 0.29.0", "tokio-util", "tower-service", "tracing", @@ -9173,6 +13314,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" version = "1.0.4+wasi-0.2.12" @@ -9182,13 +13332,19 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasix" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae86f02046da16a333a9129d31451423e1657737ecdafed4193838a5f54c5cfe" dependencies = [ - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -9246,6 +13402,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "weak-table" version = "0.3.2" @@ -9272,12 +13442,39 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" +dependencies = [ + "rustls-webpki 0.101.7", +] + [[package]] name = "webpki-roots" version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.9", +] + [[package]] name = "webpki-roots" version = "1.0.9" @@ -9308,6 +13505,16 @@ dependencies = [ "libc", ] +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + [[package]] name = "widestring" version = "1.2.1" @@ -9357,6 +13564,62 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections 0.2.0", + "windows-core 0.61.2", + "windows-future 0.2.1", + "windows-link 0.1.3", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -9365,9 +13628,31 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading 0.1.0", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] @@ -9392,21 +13677,56 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", +] + [[package]] name = "windows-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -9415,7 +13735,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -9424,7 +13753,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -9469,7 +13798,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -9509,7 +13838,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -9520,6 +13849,24 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -9764,7 +14111,7 @@ version = "0.1.0" source = "git+https://github.com/hhanh00/zcash-trees.git?rev=1c820645e9116bbdfed5719ba8ff1d89b9be6cb1#1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" dependencies = [ "anyhow", - "bincode", + "bincode 2.0.1", "blake2b_simd", "chacha20 0.9.1", "halo2_gadgets", @@ -9774,7 +14121,7 @@ dependencies = [ "orchard", "rayon", "sapling-crypto", - "secp256k1", + "secp256k1 0.29.1", "thiserror 2.0.20", "zcash_encoding 0.5.0", "zcash_protocol", @@ -9816,13 +14163,13 @@ dependencies = [ "orchard", "pasta_curves", "percent-encoding", - "prost", + "prost 0.14.4", "rand_core 0.6.4", "rayon", "sapling-crypto", "secrecy 0.8.0", "shardtree", - "subtle", + "subtle 2.6.1", "time", "tonic", "tonic-prost", @@ -9868,7 +14215,7 @@ version = "0.16.0" source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ "bech32 0.11.1", - "bip32", + "bip32 0.6.0-pre.1", "blake2b_simd", "bls12_381", "bs58", @@ -9881,7 +14228,7 @@ dependencies = [ "rand_core 0.6.4", "sapling-crypto", "secrecy 0.8.0", - "subtle", + "subtle 2.6.1", "tracing", "zcash_address", "zcash_encoding 0.4.0", @@ -9899,7 +14246,7 @@ dependencies = [ "chacha20poly1305", "cipher", "rand_core 0.6.4", - "subtle", + "subtle 2.6.1", ] [[package]] @@ -9923,7 +14270,7 @@ dependencies = [ "rand_core 0.6.4", "redjubjub", "sapling-crypto", - "secp256k1", + "secp256k1 0.29.1", "sha2 0.10.9", "zcash_encoding 0.4.0", "zcash_note_encryption", @@ -9972,12 +14319,12 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f872800287d118be71bdf6fe8c869c6a6ff6fb0a5762f68fb2af54c97edf0f2" dependencies = [ - "bip32", + "bip32 0.6.0-pre.1", "bitflags 2.13.1", "bounded-vec", "hex", "ripemd 0.1.3", - "secp256k1", + "secp256k1 0.29.1", "sha1", "sha2 0.10.9", "thiserror 2.0.20", @@ -9996,7 +14343,7 @@ name = "zcash_transparent" version = "0.10.0" source = "git+https://github.com/zcash-shielded-assets/librustzcash?rev=3cac2d7ff169c213fcb1ca76f02fb82cc8d87265#3cac2d7ff169c213fcb1ca76f02fb82cc8d87265" dependencies = [ - "bip32", + "bip32 0.6.0-pre.1", "bs58", "corez", "document-features", @@ -10004,9 +14351,9 @@ dependencies = [ "hex", "nonempty", "ripemd 0.1.3", - "secp256k1", + "secp256k1 0.29.1", "sha2 0.10.9", - "subtle", + "subtle 2.6.1", "zcash_address", "zcash_encoding 0.4.0", "zcash_protocol", @@ -10033,7 +14380,7 @@ dependencies = [ "http 1.5.0", "http-body-util", "hyper 1.11.0", - "hyper-rustls", + "hyper-rustls 0.27.9", "hyper-util", "imt-tree", "incrementalmerkletree", @@ -10043,7 +14390,7 @@ dependencies = [ "pczt", "pir-client", "pir-types", - "prost", + "prost 0.14.4", "rand 0.8.7", "rustls 0.23.43", "serde", @@ -10051,7 +14398,7 @@ dependencies = [ "sha2 0.10.9", "sinsemilla", "sqlx", - "subtle", + "subtle 2.6.1", "thiserror 2.0.20", "tokio 1.53.1", "tonic", @@ -10189,7 +14536,7 @@ dependencies = [ "bech32 0.11.1", "blake2b_simd", "memuse", - "subtle", + "subtle 2.6.1", "zcash_spec", ] diff --git a/Cargo.toml b/Cargo.toml index 575abd80e..cf6b0bc46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,13 @@ debug = 1 debug = 0 [patch.crates-io] +# -- Nym transport -- +# jwt-simple <=0.12.15 pins rand =0.8.5, which conflicts with the nym +# crates (rand ^0.8.6); >=0.12.16 conflicts with the librustzcash fork's +# crypto-common =0.2.0-rc.1 pin via superboring/ml-dsa. Fork of 0.12.12 +# with the rand pin relaxed to ^0.8.5. +jwt-simple = { git = "https://github.com/rachyandco/rust-jwt-simple", rev = "e8177eab707d27d7ea94b6799204e48e11b65e19" } + # -- ZSA support branches -- orchard = { git = "https://github.com/zcash-shielded-assets/orchard.git", rev = "4cf06bc19e52d1e8e43438cdbdd703ac2565bff6" } sapling-crypto = { git = "https://github.com/zcash-shielded-assets/sapling-crypto", rev = "4c47c84845436aa1b650bd5367ed4de67421cc0d" } diff --git a/lib/pages/lwd_select.dart b/lib/pages/lwd_select.dart index 1b0b1a7dd..416ac31bd 100644 --- a/lib/pages/lwd_select.dart +++ b/lib/pages/lwd_select.dart @@ -15,6 +15,10 @@ class LWDSelectPage extends ConsumerStatefulWidget { ConsumerState createState() => _LWDSelectPageState(); } +/// Default mixnet-native lightwalletd endpoint (nym-rpc service). +const defaultNymUrl = + "nym://BbTPrU1gNTsPiieXdC58xkp5QFSHhUUM98BP1Rm2adf9.GKiGLNQB116YszFwbuweeL2GsrfpHpuUzq6JuqFQ8EEE@ZXSDhRTKU5HgMpH8ma78FftvLiKyZ6jWL1e2U7GD7gQ"; + class _LWDSelectPageState extends ConsumerState { int _sortColumnIndex = 3; // Uptime bool _sortAscending = false; // descending @@ -31,12 +35,11 @@ class _LWDSelectPageState extends ConsumerState { final scheme = server.isTor ? 'http' : 'https'; url = '$scheme://$url'; } - // Enable Tor for onion addresses + // Enable Tor transport for onion addresses if (server.isTor) { final prefs = SharedPreferencesAsync(); - await prefs.setBool("use_tor", true); - final c = coinContext.coin; - await c.setUseTor(useTor: true); + await prefs.setInt("transport", 1); + coinContext.set(coin: coinContext.coin.setTransport(transport: 1)); ref.invalidate(appSettingsProvider); } if (mounted) { @@ -44,6 +47,81 @@ class _LWDSelectPageState extends ConsumerState { } } + /// Select a mixnet-native (nym://) endpoint: the mixnet is the transport, + /// so the transport setting is forced to Direct. + Future _onSelectNym(String url) async { + final prefs = SharedPreferencesAsync(); + await prefs.setInt("transport", 0); + coinContext.set(coin: coinContext.coin.setTransport(transport: 0)); + ref.invalidate(appSettingsProvider); + if (!mounted) return; + final messenger = ScaffoldMessenger.of(context); + Navigator.of(context).pop(url); + messenger.showSnackBar(const SnackBar( + content: Text("Nym service address selected — traffic is routed natively " + "through the mixnet; transport is forced to Direct."), + )); + } + + Future _onPasteNym() async { + final controller = TextEditingController(); + String? errorText; + final url = await showDialog( + context: context, + builder: (context) => StatefulBuilder( + builder: (context, setState) => AlertDialog( + title: const Text("Nym service address"), + content: TextField( + controller: controller, + autofocus: true, + decoration: InputDecoration( + hintText: "nym://identity.encryption@gateway", + errorText: errorText, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text("Cancel"), + ), + TextButton( + onPressed: () { + var input = controller.text.trim(); + if (!input.startsWith("nym://")) input = "nym://$input"; + if (isValidNymUrl(url: input)) { + Navigator.of(context).pop(input); + } else { + setState(() => errorText = "Not a valid Nym address"); + } + }, + child: const Text("OK"), + ), + ], + ), + ), + ); + if (url != null) await _onSelectNym(url); + } + + Widget _nymSection(BuildContext context) { + final tt = Theme.of(context).textTheme; + final shortAddr = "${defaultNymUrl.substring(0, 14)}…${defaultNymUrl.substring(defaultNymUrl.length - 8)}"; + return Card( + margin: const EdgeInsets.fromLTRB(12, 8, 12, 0), + child: ListTile( + leading: const Icon(Icons.hub, color: Colors.teal), + title: const Text("Zcash over Nym mixnet (nym-rpc)"), + subtitle: Text(shortAddr, style: tt.bodySmall, overflow: TextOverflow.ellipsis), + trailing: IconButton( + tooltip: "Paste a Nym service address", + icon: const Icon(Icons.edit), + onPressed: _onPasteNym, + ), + onTap: () => _onSelectNym(defaultNymUrl), + ), + ); + } + @override void initState() { super.initState(); @@ -77,142 +155,147 @@ class _LWDSelectPageState extends ConsumerState { appBar: AppBar( title: const Text("Select Lightwalletd Server"), ), - body: Builder( - builder: (context) { - if (_loading) { - return const Center(child: CircularProgressIndicator()); - } - if (_error != null) { - return Center( - child: Padding( - padding: const EdgeInsets.all(16), - child: Text( - "Failed to load server list: $_error", - style: tt.bodyLarge, - textAlign: TextAlign.center, - ), - ), - ); - } + body: Column( + children: [ + _nymSection(context), + Expanded(child: _serverList(context, tt)), + ], + ), + ); + } - final servers = _servers!; - if (servers.isEmpty) { - return Center( - child: Text("No servers available", style: tt.bodyLarge), - ); - } + Widget _serverList(BuildContext context, TextTheme tt) { + if (_loading) { + return const Center(child: CircularProgressIndicator()); + } + if (_error != null) { + return Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: Text( + "Failed to load server list: $_error", + style: tt.bodyLarge, + textAlign: TextAlign.center, + ), + ), + ); + } - // Filter - final filtered = servers.where((s) { - if (_onlineFilter == null) return true; - final isOnline = s.status == "online"; - return _onlineFilter! ? isOnline : !isOnline; - }).toList(); + final servers = _servers!; + if (servers.isEmpty) { + return Center( + child: Text("No servers available", style: tt.bodyLarge), + ); + } + + // Filter + final filtered = servers.where((s) { + if (_onlineFilter == null) return true; + final isOnline = s.status == "online"; + return _onlineFilter! ? isOnline : !isOnline; + }).toList(); - // Sort - filtered.sort((a, b) { - int cmp; - switch (_sortColumnIndex) { - case 0: - cmp = a.url.compareTo(b.url); - case 1: - cmp = a.ping.compareTo(b.ping); - case 2: - cmp = a.height.compareTo(b.height); - case 3: - cmp = a.uptime.compareTo(b.uptime); - default: - cmp = 0; - } - return _sortAscending ? cmp : -cmp; - }); + // Sort + filtered.sort((a, b) { + int cmp; + switch (_sortColumnIndex) { + case 0: + cmp = a.url.compareTo(b.url); + case 1: + cmp = a.ping.compareTo(b.ping); + case 2: + cmp = a.height.compareTo(b.height); + case 3: + cmp = a.uptime.compareTo(b.uptime); + default: + cmp = 0; + } + return _sortAscending ? cmp : -cmp; + }); - return Column( + return Column( + children: [ + // Online/offline filter + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( children: [ - // Online/offline filter - Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: Row( - children: [ - SegmentedButton( - segments: const [ - ButtonSegment( - value: null, - label: Text("All"), - ), - ButtonSegment( - value: true, - label: Text("Online"), - icon: Icon(Icons.circle, color: Colors.green, size: 12), - ), - ButtonSegment( - value: false, - label: Text("Offline"), - icon: Icon(Icons.circle, color: Colors.red, size: 12), - ), - ], - selected: {_onlineFilter}, - onSelectionChanged: (selected) { - _applyFilter(selected.first); - }, - style: const ButtonStyle( - visualDensity: VisualDensity.compact, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), - const Spacer(), - Text("${filtered.length} servers", style: tt.bodySmall), - ], - ), - ), - // Paginated DataTable - Expanded( - child: PaginatedDataTable2( - key: ValueKey(_onlineFilter), - sortColumnIndex: _sortColumnIndex, - sortAscending: _sortAscending, - headingRowColor: WidgetStateProperty.all( - Theme.of(context).colorScheme.surfaceContainerHighest, + SegmentedButton( + segments: const [ + ButtonSegment( + value: null, + label: Text("All"), + ), + ButtonSegment( + value: true, + label: Text("Online"), + icon: Icon(Icons.circle, color: Colors.green, size: 12), ), - columnSpacing: 12, - horizontalMargin: 12, - minWidth: 600, - fixedLeftColumns: 1, - rowsPerPage: 10, - availableRowsPerPage: const [10, 20, 50], - onRowsPerPageChanged: (_) {}, - columns: [ - DataColumn2( - label: const Text("Server"), - onSort: (i, asc) => _onSort(i, asc), - size: ColumnSize.L, - ), - DataColumn2( - label: const Text("Ping (ms)"), - numeric: true, - onSort: (i, asc) => _onSort(i, asc), - size: ColumnSize.S, - ), - DataColumn2( - label: const Text("Height"), - numeric: true, - onSort: (i, asc) => _onSort(i, asc), - size: ColumnSize.S, - ), - DataColumn2( - label: const Text("Uptime"), - numeric: true, - onSort: (i, asc) => _onSort(i, asc), - size: ColumnSize.S, - ), - ], - source: _LwdDataSource(filtered, context, _onSelectServer), + ButtonSegment( + value: false, + label: Text("Offline"), + icon: Icon(Icons.circle, color: Colors.red, size: 12), + ), + ], + selected: {_onlineFilter}, + onSelectionChanged: (selected) { + _applyFilter(selected.first); + }, + style: const ButtonStyle( + visualDensity: VisualDensity.compact, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), ), + const Spacer(), + Text("${filtered.length} servers", style: tt.bodySmall), ], - ); - }, - ), + ), + ), + // Paginated DataTable + Expanded( + child: PaginatedDataTable2( + key: ValueKey(_onlineFilter), + sortColumnIndex: _sortColumnIndex, + sortAscending: _sortAscending, + headingRowColor: WidgetStateProperty.all( + Theme.of(context).colorScheme.surfaceContainerHighest, + ), + columnSpacing: 12, + horizontalMargin: 12, + minWidth: 600, + fixedLeftColumns: 1, + rowsPerPage: 10, + availableRowsPerPage: const [10, 20, 50], + onRowsPerPageChanged: (_) {}, + columns: [ + DataColumn2( + label: const Text("Server"), + onSort: (i, asc) => _onSort(i, asc), + size: ColumnSize.L, + ), + DataColumn2( + label: const Text("Ping (ms)"), + numeric: true, + onSort: (i, asc) => _onSort(i, asc), + size: ColumnSize.S, + ), + DataColumn2( + label: const Text("Height"), + numeric: true, + onSort: (i, asc) => _onSort(i, asc), + size: ColumnSize.S, + ), + DataColumn2( + label: const Text("Uptime"), + numeric: true, + onSort: (i, asc) => _onSort(i, asc), + size: ColumnSize.S, + ), + ], + source: _LwdDataSource(filtered, context, _onSelectServer), + ), + ), + ], ); } diff --git a/lib/pages/splash.dart b/lib/pages/splash.dart index 7ef6462c4..19f729676 100644 --- a/lib/pages/splash.dart +++ b/lib/pages/splash.dart @@ -103,7 +103,7 @@ class SplashPageState extends ConsumerState { serverType: settings.isLightNode ? 0 : 1, url: settings.lwd, ); - c = await c.setUseTor(useTor: settings.useTor); + c = c.setTransport(transport: settings.transport); c = c.setProxy(proxy: settings.proxy); coinContext.set(coin: c); final synchronizer = ref.read(synchronizerProvider.notifier); diff --git a/lib/settings.dart b/lib/settings.dart index de55519a2..1f9f14905 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -5,7 +5,6 @@ import 'package:flutter_passkey_service/pigeons/messages.g.dart' show PasskeyExc import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:flutter/services.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:gap/gap.dart'; @@ -15,6 +14,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:zkool/router.dart'; import 'package:zkool/src/rust/api/coin.dart'; +import 'package:zkool/src/rust/api/network.dart' show isValidNymUrl; import 'package:zkool/src/rust/api/db.dart'; import 'package:zkool/src/rust/api/init.dart'; import 'package:zkool/src/rust/api/sapling.dart'; @@ -71,7 +71,7 @@ class SettingsPageState extends ConsumerState with RouteAware { await putProp(key: "sync_interval", value: settings.syncInterval, c: c); await prefs.setBool("pin_lock", settings.needPin); await prefs.setBool("offline", settings.offline); - await prefs.setBool("use_tor", settings.useTor); + await prefs.setInt("transport", settings.transport); await putProp(key: "proxy", value: settings.proxy, c: c); await prefs.setBool("get_fx", settings.getFx); await prefs.setString("coingecko", settings.coingecko); @@ -81,7 +81,7 @@ class SettingsPageState extends ConsumerState with RouteAware { await putProp(key: "qr_delay", value: settings.qrSettings.delay.toString(), c: c); await putProp(key: "qr_repair", value: settings.qrSettings.repair.toString(), c: c); c = c.setLwd(url: settings.lwd, serverType: settings.isLightNode ? 0 : 1); - c = await c.setUseTor(useTor: settings.useTor); + c = c.setTransport(transport: settings.transport); c = c.setProxy(proxy: settings.proxy); await prefs.setBool("vault", settings.vault); await prefs.setBool("expert_mode", settings.expertMode); @@ -190,42 +190,55 @@ class SettingsFormState extends ConsumerState { ], ), ), - Row( - children: [ - IconButton.outlined( - tooltip: settings.useTor ? "Disable Arti Tor" : "Enable Arti Tor (embedded Tor client)", - onPressed: onToggleTor, - icon: SvgPicture.asset( - "assets/tor.svg", - width: 22, - height: 22, - colorFilter: ColorFilter.mode( - settings.useTor ? Colors.green : Theme.of(context).colorScheme.primary, - BlendMode.srcIn, - ), + Tooltip( + message: "Network transport: connect directly, through the embedded " + "Tor (Arti) client, through the Nym mixnet, or via an external proxy", + child: Row( + children: [ + SegmentedButton( + segments: const [ + ButtonSegment(value: 0, label: Text("Direct")), + ButtonSegment(value: 1, label: Text("Tor")), + ButtonSegment(value: 2, label: Text("Nym")), + ButtonSegment(value: 3, label: Text("Proxy")), + ], + selected: {isNymServer ? 0 : settings.transport}, + onSelectionChanged: isNymServer ? null : onChangedTransport, ), - ), - const Gap(4), - Text(settings.useTor ? "Arti Tor enabled" : "Arti Tor disabled"), - const Gap(24), - Expanded( - child: Tooltip( - message: "Route connections through an external proxy. " - "Supports socks5://, socks5h://, http:// and https://. " - "Disabled when Arti Tor is enabled.", - child: FormBuilderTextField( - name: "proxy", - decoration: const InputDecoration( - labelText: "HTTP / SOCKS5 Proxy", - hintText: "socks5h://127.0.0.1:9050", + ], + ), + ), + if (isNymServer) + Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + children: [ + Icon(Icons.info_outline, size: 16, color: Theme.of(context).colorScheme.tertiary), + const Gap(8), + Expanded( + child: Text( + "Nym service address: traffic is routed natively through the " + "Nym mixnet. Transport selection is disabled.", + style: Theme.of(context).textTheme.bodySmall, ), - initialValue: settings.proxy, - enabled: !settings.useTor, - onChanged: onChangedProxy, ), - ), + ], ), - ], + ), + Tooltip( + message: "Route connections through an external proxy. " + "Supports socks5://, socks5h://, http:// and https://. " + "Used when the Proxy transport is selected.", + child: FormBuilderTextField( + name: "proxy", + decoration: const InputDecoration( + labelText: "HTTP / SOCKS5 Proxy", + hintText: "socks5h://127.0.0.1:9050", + ), + initialValue: settings.proxy, + enabled: !isNymServer && settings.transport == 3, + onChanged: onChangedProxy, + ), ), Tooltip( message: "Number actions per synchronization chunk", @@ -447,10 +460,18 @@ class SettingsFormState extends ConsumerState { }); } + /// Mixnet-native server address (nym:// URL): the mixnet is the + /// transport, so the transport selector is forced to Direct. + bool get isNymServer => isValidNymUrl(url: settings.lwd); + void onChangedLWD(String? value) async { if (value == null) return; setState(() { - settings = settings.copyWith(lwd: value); + settings = settings.copyWith( + lwd: value, + // Force Direct when a Nym service address is entered. + transport: isValidNymUrl(url: value) ? 0 : settings.transport, + ); widget.onChanged(settings); }); } @@ -487,9 +508,9 @@ class SettingsFormState extends ConsumerState { }); } - void onToggleTor() async { + void onChangedTransport(Set selection) { setState(() { - settings = settings.copyWith(useTor: !settings.useTor); + settings = settings.copyWith(transport: selection.first); widget.onChanged(settings); }); } diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index 2bffde001..e0fd7cd80 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -8,7 +8,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'coin.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `network`, `open_proxied_stream`, `try_open` +// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_nym`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `network`, `open_proxied_stream`, `try_open` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` Future initDatadir({required String directory}) => @@ -28,7 +28,7 @@ sealed class Coin with _$Coin { required String dbFilepath, required String url, required int serverType, - required bool useTor, + required int transport, required String proxy, }) = _Coin; Future getName() => RustLib.instance.api.crateApiCoinCoinGetName( @@ -52,6 +52,6 @@ sealed class Coin with _$Coin { Coin setProxy({required String proxy}) => RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); - Future setUseTor({required bool useTor}) => RustLib.instance.api - .crateApiCoinCoinSetUseTor(that: this, useTor: useTor); + Coin setTransport({required int transport}) => RustLib.instance.api + .crateApiCoinCoinSetTransport(that: this, transport: transport); } diff --git a/lib/src/rust/api/coin.freezed.dart b/lib/src/rust/api/coin.freezed.dart index a6b9a8d97..f371d6e9b 100644 --- a/lib/src/rust/api/coin.freezed.dart +++ b/lib/src/rust/api/coin.freezed.dart @@ -19,7 +19,7 @@ mixin _$Coin { String get dbFilepath; String get url; int get serverType; - bool get useTor; + int get transport; String get proxy; /// Create a copy of Coin @@ -41,17 +41,18 @@ mixin _$Coin { (identical(other.url, url) || other.url == url) && (identical(other.serverType, serverType) || other.serverType == serverType) && - (identical(other.useTor, useTor) || other.useTor == useTor) && + (identical(other.transport, transport) || + other.transport == transport) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash( - runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, + serverType, transport, proxy); @override String toString() { - return 'Coin(coin: $coin, account: $account, dbFilepath: $dbFilepath, url: $url, serverType: $serverType, useTor: $useTor, proxy: $proxy)'; + return 'Coin(coin: $coin, account: $account, dbFilepath: $dbFilepath, url: $url, serverType: $serverType, transport: $transport, proxy: $proxy)'; } } @@ -66,7 +67,7 @@ abstract mixin class $CoinCopyWith<$Res> { String dbFilepath, String url, int serverType, - bool useTor, + int transport, String proxy}); } @@ -87,7 +88,7 @@ class _$CoinCopyWithImpl<$Res> implements $CoinCopyWith<$Res> { Object? dbFilepath = null, Object? url = null, Object? serverType = null, - Object? useTor = null, + Object? transport = null, Object? proxy = null, }) { return _then(_self.copyWith( @@ -111,10 +112,10 @@ class _$CoinCopyWithImpl<$Res> implements $CoinCopyWith<$Res> { ? _self.serverType : serverType // ignore: cast_nullable_to_non_nullable as int, - useTor: null == useTor - ? _self.useTor - : useTor // ignore: cast_nullable_to_non_nullable - as bool, + transport: null == transport + ? _self.transport + : transport // ignore: cast_nullable_to_non_nullable + as int, proxy: null == proxy ? _self.proxy : proxy // ignore: cast_nullable_to_non_nullable @@ -215,7 +216,7 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult maybeWhen({ TResult Function(int coin, int account, String dbFilepath, String url, - int serverType, bool useTor, String proxy)? + int serverType, int transport, String proxy)? raw, required TResult orElse(), }) { @@ -223,7 +224,7 @@ extension CoinPatterns on Coin { switch (_that) { case _Coin() when raw != null: return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + _that.serverType, _that.transport, _that.proxy); case _: return orElse(); } @@ -245,14 +246,14 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult when({ required TResult Function(int coin, int account, String dbFilepath, - String url, int serverType, bool useTor, String proxy) + String url, int serverType, int transport, String proxy) raw, }) { final _that = this; switch (_that) { case _Coin(): return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + _that.serverType, _that.transport, _that.proxy); } } @@ -271,14 +272,14 @@ extension CoinPatterns on Coin { @optionalTypeArgs TResult? whenOrNull({ TResult? Function(int coin, int account, String dbFilepath, String url, - int serverType, bool useTor, String proxy)? + int serverType, int transport, String proxy)? raw, }) { final _that = this; switch (_that) { case _Coin() when raw != null: return raw(_that.coin, _that.account, _that.dbFilepath, _that.url, - _that.serverType, _that.useTor, _that.proxy); + _that.serverType, _that.transport, _that.proxy); case _: return null; } @@ -294,7 +295,7 @@ class _Coin extends Coin { required this.dbFilepath, required this.url, required this.serverType, - required this.useTor, + required this.transport, required this.proxy}) : super._(); @@ -309,7 +310,7 @@ class _Coin extends Coin { @override final int serverType; @override - final bool useTor; + final int transport; @override final String proxy; @@ -333,17 +334,18 @@ class _Coin extends Coin { (identical(other.url, url) || other.url == url) && (identical(other.serverType, serverType) || other.serverType == serverType) && - (identical(other.useTor, useTor) || other.useTor == useTor) && + (identical(other.transport, transport) || + other.transport == transport) && (identical(other.proxy, proxy) || other.proxy == proxy)); } @override - int get hashCode => Object.hash( - runtimeType, coin, account, dbFilepath, url, serverType, useTor, proxy); + int get hashCode => Object.hash(runtimeType, coin, account, dbFilepath, url, + serverType, transport, proxy); @override String toString() { - return 'Coin.raw(coin: $coin, account: $account, dbFilepath: $dbFilepath, url: $url, serverType: $serverType, useTor: $useTor, proxy: $proxy)'; + return 'Coin.raw(coin: $coin, account: $account, dbFilepath: $dbFilepath, url: $url, serverType: $serverType, transport: $transport, proxy: $proxy)'; } } @@ -359,7 +361,7 @@ abstract mixin class _$CoinCopyWith<$Res> implements $CoinCopyWith<$Res> { String dbFilepath, String url, int serverType, - bool useTor, + int transport, String proxy}); } @@ -380,7 +382,7 @@ class __$CoinCopyWithImpl<$Res> implements _$CoinCopyWith<$Res> { Object? dbFilepath = null, Object? url = null, Object? serverType = null, - Object? useTor = null, + Object? transport = null, Object? proxy = null, }) { return _then(_Coin( @@ -404,10 +406,10 @@ class __$CoinCopyWithImpl<$Res> implements _$CoinCopyWith<$Res> { ? _self.serverType : serverType // ignore: cast_nullable_to_non_nullable as int, - useTor: null == useTor - ? _self.useTor - : useTor // ignore: cast_nullable_to_non_nullable - as bool, + transport: null == transport + ? _self.transport + : transport // ignore: cast_nullable_to_non_nullable + as int, proxy: null == proxy ? _self.proxy : proxy // ignore: cast_nullable_to_non_nullable diff --git a/lib/src/rust/api/network.dart b/lib/src/rust/api/network.dart index 05afff178..3c056c3a7 100644 --- a/lib/src/rust/api/network.dart +++ b/lib/src/rust/api/network.dart @@ -45,6 +45,11 @@ Future getNetworkName({required Coin c}) => Future> queryLwdList({required int coin}) => RustLib.instance.api.crateApiNetworkQueryLwdList(coin: coin); +/// True when `url` is a mixnet-native server address +/// (`nym://.@`). +bool isValidNymUrl({required String url}) => + RustLib.instance.api.crateApiNetworkIsValidNymUrl(url: url); + @freezed sealed class ExchangeRate with _$ExchangeRate { const factory ExchangeRate({ diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 3aa7b2ff8..adcfa3d17 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -1244747988; + int get rustContentHash => 88494436; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -213,8 +213,8 @@ abstract class RustLibApi extends BaseApi { Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}); - Future crateApiCoinCoinSetUseTor( - {required Coin that, required bool useTor}); + Coin crateApiCoinCoinSetTransport( + {required Coin that, required int transport}); Future crateApiContactsCreateContact( {required String name, @@ -425,6 +425,8 @@ abstract class RustLibApi extends BaseApi { bool crateApiKeyIsValidKey({required String key, required Coin c}); + bool crateApiNetworkIsValidNymUrl({required String url}); + bool crateApiKeyIsValidPhrase({required String phrase}); bool crateApiKeyIsValidTransparentAddress( @@ -1669,31 +1671,31 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiCoinCoinSetUseTor( - {required Coin that, required bool useTor}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { + Coin crateApiCoinCoinSetTransport( + {required Coin that, required int transport}) { + return handler.executeSync( + SyncTask( + callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); - sse_encode_bool(useTor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 32, port: port_); + sse_encode_u_8(transport, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32)!; }, codec: SseCodec( decodeSuccessData: sse_decode_coin, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiCoinCoinSetUseTorConstMeta, - argValues: [that, useTor], + constMeta: kCrateApiCoinCoinSetTransportConstMeta, + argValues: [that, transport], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiCoinCoinSetUseTorConstMeta => const TaskConstMeta( - debugName: "coin_set_use_tor", - argNames: ["that", "useTor"], + TaskConstMeta get kCrateApiCoinCoinSetTransportConstMeta => + const TaskConstMeta( + debugName: "coin_set_transport", + argNames: ["that", "transport"], ); @override @@ -3825,6 +3827,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["key", "c"], ); + @override + bool crateApiNetworkIsValidNymUrl({required String url}) { + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(url, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 107)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_bool, + decodeErrorData: null, + ), + constMeta: kCrateApiNetworkIsValidNymUrlConstMeta, + argValues: [url], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiNetworkIsValidNymUrlConstMeta => + const TaskConstMeta( + debugName: "is_valid_nym_url", + argNames: ["url"], + ); + @override bool crateApiKeyIsValidPhrase({required String phrase}) { return handler.executeSync( @@ -3833,7 +3862,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107)!; + funcId: 108)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3861,7 +3890,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108)!; + funcId: 109)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3888,7 +3917,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109, port: port_); + funcId: 110, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3927,7 +3956,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); + funcId: 111, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3969,7 +3998,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); + funcId: 112, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -3996,7 +4025,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); + funcId: 113, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -4023,7 +4052,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); + funcId: 114, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -4051,7 +4080,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); + funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -4077,7 +4106,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -4103,7 +4132,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -4129,7 +4158,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -4155,7 +4184,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -4181,7 +4210,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + funcId: 120, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -4207,7 +4236,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); + funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -4234,7 +4263,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); + funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -4263,7 +4292,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + funcId: 123, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4292,7 +4321,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); + funcId: 124, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4319,7 +4348,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -4348,7 +4377,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4374,7 +4403,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + funcId: 127, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4402,7 +4431,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); + funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4429,7 +4458,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128)!; + funcId: 129)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -4460,7 +4489,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); + funcId: 130, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4491,7 +4520,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); + funcId: 131, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4519,7 +4548,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4548,7 +4577,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4574,7 +4603,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + funcId: 134, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -4600,7 +4629,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); + funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4629,7 +4658,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135)!; + funcId: 136)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4658,7 +4687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); + funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4687,7 +4716,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4715,7 +4744,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4745,7 +4774,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); + funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4775,7 +4804,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + funcId: 141, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4802,7 +4831,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); + funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4829,7 +4858,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4857,7 +4886,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); + funcId: 144, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4885,7 +4914,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); + funcId: 145, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4913,7 +4942,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); + funcId: 146, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4943,7 +4972,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146, port: port_); + funcId: 147, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4972,7 +5001,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147, port: port_); + funcId: 148, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5001,7 +5030,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5030,7 +5059,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5067,7 +5096,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5093,7 +5122,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151)!; + funcId: 152)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5120,7 +5149,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152)!; + funcId: 153)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5150,7 +5179,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); + funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5180,7 +5209,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5210,7 +5239,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5240,7 +5269,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + funcId: 157, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5267,7 +5296,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157, port: port_); + funcId: 158, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5295,7 +5324,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); + funcId: 159, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5327,7 +5356,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159, port: port_); + funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5358,7 +5387,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + funcId: 161, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5384,7 +5413,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5420,7 +5449,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5462,7 +5491,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -5509,7 +5538,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164)!; + funcId: 165)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5535,7 +5564,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); + funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5564,7 +5593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166)!; + funcId: 167)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5590,7 +5619,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); + funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5616,7 +5645,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5642,7 +5671,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + funcId: 170, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5668,7 +5697,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); + funcId: 171, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5694,7 +5723,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); + funcId: 172, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5724,7 +5753,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172)!; + funcId: 173)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5750,7 +5779,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173, port: port_); + funcId: 174, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5777,7 +5806,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 174, port: port_); + funcId: 175, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5806,7 +5835,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 175, port: port_); + funcId: 176, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5842,7 +5871,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 176, port: port_); + funcId: 177, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5874,7 +5903,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 177, port: port_); + funcId: 178, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5901,7 +5930,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 178)!; + funcId: 179)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5930,7 +5959,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 179)!; + funcId: 180)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5966,7 +5995,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 180, port: port_); + funcId: 181, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_commitments, @@ -6003,7 +6032,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(eventsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 181, port: port_); + funcId: 182, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_confirmation, @@ -6037,7 +6066,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 182, port: port_); + funcId: 183, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -6064,7 +6093,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 183, port: port_); + funcId: 184, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -6098,7 +6127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 184, port: port_); + funcId: 185, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_payloads, @@ -6138,7 +6167,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(shareDeliveriesJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 185, port: port_); + funcId: 186, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6188,7 +6217,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 186, port: port_); + funcId: 187, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -6665,7 +6694,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { dbFilepath: dco_decode_String(arr[2]), url: dco_decode_String(arr[3]), serverType: dco_decode_u_8(arr[4]), - useTor: dco_decode_bool(arr[5]), + transport: dco_decode_u_8(arr[5]), proxy: dco_decode_String(arr[6]), ); } @@ -8475,7 +8504,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_dbFilepath = sse_decode_String(deserializer); var var_url = sse_decode_String(deserializer); var var_serverType = sse_decode_u_8(deserializer); - var var_useTor = sse_decode_bool(deserializer); + var var_transport = sse_decode_u_8(deserializer); var var_proxy = sse_decode_String(deserializer); return Coin.raw( coin: var_coin, @@ -8483,7 +8512,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { dbFilepath: var_dbFilepath, url: var_url, serverType: var_serverType, - useTor: var_useTor, + transport: var_transport, proxy: var_proxy); } @@ -10634,7 +10663,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.dbFilepath, serializer); sse_encode_String(self.url, serializer); sse_encode_u_8(self.serverType, serializer); - sse_encode_bool(self.useTor, serializer); + sse_encode_u_8(self.transport, serializer); sse_encode_String(self.proxy, serializer); } diff --git a/lib/store.dart b/lib/store.dart index a931f6d71..bcd0c700e 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -352,8 +352,15 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { String dbName = await prefs.getString("database") ?? appName; final needPin = await prefs.getBool("pin_lock") ?? false; final offline = await prefs.getBool("offline") ?? false; - final useTor = await prefs.getBool("use_tor") ?? false; final proxy = (hasDb ? await getProp(key: "proxy", c: c) : null) ?? ""; + // Transport: 0 = direct, 1 = Tor (arti), 2 = Nym mixnet, 3 = proxy. + // Migrate from the legacy use_tor bool / proxy-implies-proxy behavior. + int transport = await prefs.getInt("transport") ?? + ((await prefs.getBool("use_tor") ?? false) + ? 1 + : proxy.isNotEmpty + ? 3 + : 0); final getFx = await prefs.getBool("get_fx") ?? false; final coingecko = await prefs.getString("coingecko") ?? ""; final recovery = await prefs.getBool("recovery") ?? false; @@ -393,7 +400,7 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { needPin: needPin, pinUnlockedAt: DateTime.now(), offline: offline, - useTor: useTor, + transport: transport, proxy: proxy, getFx: getFx, coingecko: coingecko, @@ -493,7 +500,7 @@ sealed class AppSettings with _$AppSettings { required String blockExplorer, required String syncInterval, // in blocks required String actionsPerSync, - required bool useTor, + required int transport, required String proxy, required String coingecko, required bool recovery, diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index 02f94f519..ad7e227e2 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -1332,7 +1332,7 @@ mixin _$AppSettings { String get blockExplorer; String get syncInterval; // in blocks String get actionsPerSync; - bool get useTor; + int get transport; String get proxy; String get coingecko; bool get recovery; @@ -1371,7 +1371,8 @@ mixin _$AppSettings { other.syncInterval == syncInterval) && (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && - (identical(other.useTor, useTor) || other.useTor == useTor) && + (identical(other.transport, transport) || + other.transport == transport) && (identical(other.proxy, proxy) || other.proxy == proxy) && (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && @@ -1407,7 +1408,7 @@ mixin _$AppSettings { blockExplorer, syncInterval, actionsPerSync, - useTor, + transport, proxy, coingecko, recovery, @@ -1426,7 +1427,7 @@ mixin _$AppSettings { @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, useTor: $useTor, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; } } @@ -1444,7 +1445,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> { String blockExplorer, String syncInterval, String actionsPerSync, - bool useTor, + int transport, String proxy, String coingecko, bool recovery, @@ -1482,7 +1483,7 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { Object? blockExplorer = null, Object? syncInterval = null, Object? actionsPerSync = null, - Object? useTor = null, + Object? transport = null, Object? proxy = null, Object? coingecko = null, Object? recovery = null, @@ -1527,10 +1528,10 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { ? _self.actionsPerSync : actionsPerSync // ignore: cast_nullable_to_non_nullable as String, - useTor: null == useTor - ? _self.useTor - : useTor // ignore: cast_nullable_to_non_nullable - as bool, + transport: null == transport + ? _self.transport + : transport // ignore: cast_nullable_to_non_nullable + as int, proxy: null == proxy ? _self.proxy : proxy // ignore: cast_nullable_to_non_nullable @@ -1700,7 +1701,7 @@ extension AppSettingsPatterns on AppSettings { String blockExplorer, String syncInterval, String actionsPerSync, - bool useTor, + int transport, String proxy, String coingecko, bool recovery, @@ -1729,7 +1730,7 @@ extension AppSettingsPatterns on AppSettings { _that.blockExplorer, _that.syncInterval, _that.actionsPerSync, - _that.useTor, + _that.transport, _that.proxy, _that.coingecko, _that.recovery, @@ -1772,7 +1773,7 @@ extension AppSettingsPatterns on AppSettings { String blockExplorer, String syncInterval, String actionsPerSync, - bool useTor, + int transport, String proxy, String coingecko, bool recovery, @@ -1800,7 +1801,7 @@ extension AppSettingsPatterns on AppSettings { _that.blockExplorer, _that.syncInterval, _that.actionsPerSync, - _that.useTor, + _that.transport, _that.proxy, _that.coingecko, _that.recovery, @@ -1840,7 +1841,7 @@ extension AppSettingsPatterns on AppSettings { String blockExplorer, String syncInterval, String actionsPerSync, - bool useTor, + int transport, String proxy, String coingecko, bool recovery, @@ -1868,7 +1869,7 @@ extension AppSettingsPatterns on AppSettings { _that.blockExplorer, _that.syncInterval, _that.actionsPerSync, - _that.useTor, + _that.transport, _that.proxy, _that.coingecko, _that.recovery, @@ -1900,7 +1901,7 @@ class _AppSettings implements AppSettings { required this.blockExplorer, required this.syncInterval, required this.actionsPerSync, - required this.useTor, + required this.transport, required this.proxy, required this.coingecko, required this.recovery, @@ -1932,7 +1933,7 @@ class _AppSettings implements AppSettings { @override final String actionsPerSync; @override - final bool useTor; + final int transport; @override final String proxy; @override @@ -1986,7 +1987,8 @@ class _AppSettings implements AppSettings { other.syncInterval == syncInterval) && (identical(other.actionsPerSync, actionsPerSync) || other.actionsPerSync == actionsPerSync) && - (identical(other.useTor, useTor) || other.useTor == useTor) && + (identical(other.transport, transport) || + other.transport == transport) && (identical(other.proxy, proxy) || other.proxy == proxy) && (identical(other.coingecko, coingecko) || other.coingecko == coingecko) && @@ -2022,7 +2024,7 @@ class _AppSettings implements AppSettings { blockExplorer, syncInterval, actionsPerSync, - useTor, + transport, proxy, coingecko, recovery, @@ -2041,7 +2043,7 @@ class _AppSettings implements AppSettings { @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, useTor: $useTor, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; } } @@ -2061,7 +2063,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> String blockExplorer, String syncInterval, String actionsPerSync, - bool useTor, + int transport, String proxy, String coingecko, bool recovery, @@ -2100,7 +2102,7 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { Object? blockExplorer = null, Object? syncInterval = null, Object? actionsPerSync = null, - Object? useTor = null, + Object? transport = null, Object? proxy = null, Object? coingecko = null, Object? recovery = null, @@ -2145,10 +2147,10 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { ? _self.actionsPerSync : actionsPerSync // ignore: cast_nullable_to_non_nullable as String, - useTor: null == useTor - ? _self.useTor - : useTor // ignore: cast_nullable_to_non_nullable - as bool, + transport: null == transport + ? _self.transport + : transport // ignore: cast_nullable_to_non_nullable + as int, proxy: null == proxy ? _self.proxy : proxy // ignore: cast_nullable_to_non_nullable diff --git a/lib/store.g.dart b/lib/store.g.dart index d88e47547..ca1dc410f 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -619,7 +619,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'bc2222bf4d3206176cf3b8888aee624034d51fe8'; + r'c8611b3252b3a7ff4c27392a1b5345019eb405aa'; abstract class _$AppSettingsNotifier extends $AsyncNotifier { FutureOr build(); diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0e528ebd4..e42c70616 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -45,6 +45,13 @@ tokio-util = "0.7" webpki-roots = "1.0.2" arti-client = {version = "0.31", features = ["tokio", "native-tls", "onion-service-client"]} +nym-smolmix = "=1.21.5-rc.3" +nym-sdk = "=1.21.5-rc.3" +nym-network-defaults = "=1.21.5-rc.3" +# bincode 1.x for nym-rpc wire compatibility (ProxiedMessage framing); +# the crate also uses bincode 2.x elsewhere, hence the rename. +bincode1 = {package = "bincode", version = "1.3"} +uuid = {version = "1", features = ["v4"]} httparse = "1.10.1" hyper-util = {version = "0.1", features = ["tokio"]} rayon = "1.10" diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index c41992b8d..91a2e0c3b 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -30,7 +30,9 @@ pub struct Coin { pub db_filepath: String, pub url: String, pub server_type: u8, - pub use_tor: bool, + /// Transport: 0 = direct, 1 = Tor (arti), 2 = Nym mixnet, + /// 3 = external proxy (uses `proxy`). + pub transport: u8, /// Optional external proxy URL: socks5://, socks5h://, http://, https://. /// Empty string means a direct connection. pub proxy: String, @@ -149,9 +151,9 @@ impl Coin { Ok(Coin { account, ..self }) } - #[cfg_attr(feature = "flutter", frb)] - pub fn set_use_tor(self, use_tor: bool) -> Result { - Ok(Coin { use_tor, ..self }) + #[cfg_attr(feature = "flutter", frb(sync))] + pub fn set_transport(self, transport: u8) -> Result { + Ok(Coin { transport, ..self }) } #[cfg_attr(feature = "flutter", frb(sync))] @@ -169,32 +171,43 @@ impl Coin { } pub(crate) async fn client(&self) -> Result { - match self.server_type { - // lightwalletd (gRPC). Precedence: Tor (arti) > external proxy > direct. - 0 if self.use_tor => { - let channel = connect_over_tor(&self.url).await?; - let client = CompactTxStreamerClient::new(channel); - Ok(Box::new(client) as Client) - } - - 0 if !self.proxy.is_empty() => { - let channel = connect_over_proxy(&self.url, &self.proxy).await?; - let client = CompactTxStreamerClient::new(channel); - Ok(Box::new(client) as Client) + // Mixnet-native endpoint (nym:// URL, a nym-rpc service): bypasses + // the transport enum entirely — the mixnet IS the transport. + if let Some(recipient) = crate::net::nym_service::parse_nym_url(&self.url) { + if self.server_type != 0 { + anyhow::bail!("Nym service addresses only support lightwalletd (gRPC) servers"); } + let channel = crate::net::nym_service::grpc_channel(recipient).await?; + let client = CompactTxStreamerClient::new(channel); + return Ok(Box::new(client) as Client); + } + match self.server_type { + // lightwalletd (gRPC): transport chosen explicitly by the enum. 0 => { - let mut channel = tonic::transport::Channel::from_shared(self.url.clone())?; - if self.url.starts_with("https") { - let tls = ClientTlsConfig::new().with_enabled_roots(); - channel = channel.tls_config(tls)?; - } - let client = CompactTxStreamerClient::connect(channel).await?; + let channel = match self.transport { + 1 => connect_over_tor(&self.url).await?, + 2 => connect_over_nym(&self.url).await?, + 3 if !self.proxy.is_empty() => { + connect_over_proxy(&self.url, &self.proxy).await? + } + _ => { + let mut endpoint = + tonic::transport::Channel::from_shared(self.url.clone())?; + if self.url.starts_with("https") { + let tls = ClientTlsConfig::new().with_enabled_roots(); + endpoint = endpoint.tls_config(tls)?; + } + endpoint.connect().await? + } + }; + let client = CompactTxStreamerClient::new(channel); Ok(Box::new(client) as Client) } 1 => { - let client = ZebraClient::new(&self.network(), &self.url, &self.proxy)?; + let client = + ZebraClient::new(&self.network(), &self.url, self.transport, &self.proxy)?; Ok(Box::new(client) as Client) } @@ -292,6 +305,40 @@ async fn connect_over_tor(url: &str) -> anyhow::Result { Ok(endpoint.connect_with_connector(connector).await?) } +async fn connect_over_nym(url: &str) -> anyhow::Result { + let uri = url.parse::()?; + + let host = uri + .host() + .ok_or_else(|| anyhow::anyhow!("no host"))? + .to_string(); + let port = uri.port_u16().unwrap_or_else(|| { + if uri.scheme_str() == Some("https") { + 443 + } else { + 80 + } + }); + + let connector = service_fn(move |_dst| { + let host = host.clone(); + async move { + // DNS + TCP both go through the mixnet; TLS (with SNI/cert + // checks against the hostname) runs on top via the endpoint. + let stream = crate::net::nym::nym_connect(&host, port).await?; + Ok::<_, anyhow::Error>(TokioIo::new(stream)) + } + }); + + let mut endpoint = Endpoint::from_shared(url.to_string())?; + if url.starts_with("https") { + let tls = ClientTlsConfig::new().with_enabled_roots(); + endpoint = endpoint.tls_config(tls)?; + } + + Ok(endpoint.connect_with_connector(connector).await?) +} + /// Build a tonic Channel to `url` whose TCP connection is established through an /// external proxy. Supports socks5://, socks5h://, http:// and https:// proxies. async fn connect_over_proxy(url: &str, proxy: &str) -> anyhow::Result { @@ -437,7 +484,7 @@ impl Coin { db_filepath: String::new(), server_type: 0, url: String::new(), - use_tor: false, + transport: 0, proxy: String::new(), } } diff --git a/rust/src/api/mempool.rs b/rust/src/api/mempool.rs index d0a9b496f..20adccf5d 100644 --- a/rust/src/api/mempool.rs +++ b/rust/src/api/mempool.rs @@ -26,7 +26,7 @@ async fn run_mempool( match r { Ok(_) => {} Err(e) => { - tracing::error!("Error running mempool: {}", e); + tracing::error!("Error running mempool: {:#}", e); return Err(e); } } @@ -96,7 +96,7 @@ impl Mempool { self.cancel_token = Some(ct.clone()); self.runtime.spawn(async move { if let Err(e) = run_mempool(mempool_sink, ct, &c).await { - tracing::error!("Error running mempool: {}", e); + tracing::error!("Error running mempool: {:#}", e); } }); Ok(()) diff --git a/rust/src/api/network.rs b/rust/src/api/network.rs index efeb637c1..95cda452c 100644 --- a/rust/src/api/network.rs +++ b/rust/src/api/network.rs @@ -107,6 +107,13 @@ pub async fn query_lwd_list(coin: u8) -> Result> { crate::net::lwd::query_lwd_list(coin).await } +/// True when `url` is a mixnet-native server address +/// (`nym://.@`). +#[cfg_attr(feature = "flutter", frb(sync))] +pub fn is_valid_nym_url(url: String) -> bool { + crate::net::nym_service::parse_nym_url(&url).is_some() +} + #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExchangeRate { diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 764bdc346..89129b65b 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1244747988; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 88494436; // Section: executor @@ -1463,17 +1463,16 @@ fn wire__crate__api__coin__coin_set_proxy_impl( }, ) } -fn wire__crate__api__coin__coin_set_use_tor_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, +fn wire__crate__api__coin__coin_set_transport_impl( ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "coin_set_use_tor", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + debug_name: "coin_set_transport", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, }, move || { let message = unsafe { @@ -1486,16 +1485,14 @@ fn wire__crate__api__coin__coin_set_use_tor_impl( let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); let api_that = ::sse_decode(&mut deserializer); - let api_use_tor = ::sse_decode(&mut deserializer); + let api_transport = ::sse_decode(&mut deserializer); deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::api::coin::Coin::set_use_tor(api_that, api_use_tor)?; - Ok(output_ok) - })(), - ) - } + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::coin::Coin::set_transport(api_that, api_transport)?; + Ok(output_ok) + })(), + ) }, ) } @@ -4296,6 +4293,37 @@ fn wire__crate__api__key__is_valid_key_impl( }, ) } +fn wire__crate__api__network__is_valid_nym_url_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "is_valid_nym_url", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_url = ::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, ()>((move || { + let output_ok = + Result::<_, ()>::Ok(crate::api::network::is_valid_nym_url(api_url))?; + Ok(output_ok) + })()) + }, + ) +} fn wire__crate__api__key__is_valid_phrase_impl( ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7695,7 +7723,7 @@ impl SseDecode for crate::api::coin::Coin { let mut var_dbFilepath = ::sse_decode(deserializer); let mut var_url = ::sse_decode(deserializer); let mut var_serverType = ::sse_decode(deserializer); - let mut var_useTor = ::sse_decode(deserializer); + let mut var_transport = ::sse_decode(deserializer); let mut var_proxy = ::sse_decode(deserializer); return crate::api::coin::Coin { coin: var_coin, @@ -7703,7 +7731,7 @@ impl SseDecode for crate::api::coin::Coin { db_filepath: var_dbFilepath, url: var_url, server_type: var_serverType, - use_tor: var_useTor, + transport: var_transport, proxy: var_proxy, }; } @@ -9639,7 +9667,6 @@ fn pde_ffi_dispatcher_primary_impl( 26 => wire__crate__api__coin__coin_get_name_impl(port, ptr, rust_vec_len, data_len), 28 => wire__crate__api__coin__coin_open_database_impl(port, ptr, rust_vec_len, data_len), 29 => wire__crate__api__coin__coin_set_account_impl(port, ptr, rust_vec_len, data_len), - 32 => wire__crate__api__coin__coin_set_use_tor_impl(port, ptr, rust_vec_len, data_len), 33 => wire__crate__api__contacts__create_contact_impl(port, ptr, rust_vec_len, data_len), 34 => { wire__crate__api__account__create_new_category_impl(port, ptr, rust_vec_len, data_len) @@ -9795,123 +9822,123 @@ fn pde_ffi_dispatcher_primary_impl( 102 => { wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) } - 109 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 110 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 110 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 111 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 112 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 113 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 114 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 115 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 129 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 136 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 138 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 139 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 140 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 141 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 143 => { + 130 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 138 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 139 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 140 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 141 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 144 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 144 => wire__crate__api__openalias__resolve_openalias_all_impl( + 145 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 145 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 146 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 146 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 147 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 150 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 153 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 154 => { + 147 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 151 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 154 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 155 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 155 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__account__show_ledger_sapling_address_impl( + 156 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 158 => wire__crate__api__account__show_ledger_transparent_address_impl( + 159 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 159 => wire__crate__api__account__sign_ledger_transaction_impl( + 160 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 160 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 161 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 162 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 167 => { + 161 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 162 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 164 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 168 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 168 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 173 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 174 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 175 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 176 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 177 => wire__crate__api__transaction__update_historical_prices_impl( + 169 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 170 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 172 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 174 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 175 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 176 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 177 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 178 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, data_len, ), - 180 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), - 181 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 182 => { + 181 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 182 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 183 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 183 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 184 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 185 => wire__crate__api__voting__voting_record_execution_impl( + 184 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 185 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 186 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 186 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 187 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -9933,6 +9960,7 @@ fn pde_ffi_dispatcher_sync_impl( 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), + 32 => wire__crate__api__coin__coin_set_transport_impl(ptr, rust_vec_len, data_len), 64 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), 78 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), 83 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), @@ -9941,25 +9969,26 @@ fn pde_ffi_dispatcher_sync_impl( 104 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), 105 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), 106 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 107 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 108 => { + 107 => wire__crate__api__network__is_valid_nym_url_impl(ptr, rust_vec_len, data_len), + 108 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 109 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 128 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 151 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 152 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 164 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 166 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 129 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 136 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 152 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 153 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 165 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 167 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 172 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 178 => { + 173 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 179 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 179 => { + 180 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -10146,7 +10175,7 @@ impl flutter_rust_bridge::IntoDart for crate::api::coin::Coin { self.db_filepath.into_into_dart().into_dart(), self.url.into_into_dart().into_dart(), self.server_type.into_into_dart().into_dart(), - self.use_tor.into_into_dart().into_dart(), + self.transport.into_into_dart().into_dart(), self.proxy.into_into_dart().into_dart(), ] .into_dart() @@ -11817,7 +11846,7 @@ impl SseEncode for crate::api::coin::Coin { ::sse_encode(self.db_filepath, serializer); ::sse_encode(self.url, serializer); ::sse_encode(self.server_type, serializer); - ::sse_encode(self.use_tor, serializer); + ::sse_encode(self.transport, serializer); ::sse_encode(self.proxy, serializer); } } diff --git a/rust/src/net/mod.rs b/rust/src/net/mod.rs index f14693698..dbecc09d6 100644 --- a/rust/src/net/mod.rs +++ b/rust/src/net/mod.rs @@ -7,6 +7,8 @@ use tonic::async_trait; use crate::{api::coin::Network, lwd::*}; pub mod lwd; +pub mod nym; +pub mod nym_service; pub mod zebra; #[async_trait] diff --git a/rust/src/net/nym.rs b/rust/src/net/nym.rs new file mode 100644 index 000000000..84a1c41a8 --- /dev/null +++ b/rust/src/net/nym.rs @@ -0,0 +1,233 @@ +//! Nym mixnet transport. +//! +//! Provides TCP streams through the Nym mixnet via a shared +//! `nym_smolmix::Tunnel`. Hostname resolution also goes over the tunnel +//! (DNS to 1.1.1.1 via the mixnet UDP socket) so server names are never +//! resolved locally. +//! +//! Mixnet connections can stall or drop (gateway churn, bridge shutdown), +//! so the tunnel is not cached unconditionally: any transport-level failure +//! invalidates the cached tunnel and the next call bootstraps a fresh one. + +use std::collections::HashMap; +use std::net::{IpAddr, SocketAddr}; +use std::sync::Mutex as StdMutex; +use std::time::{Duration, Instant}; + +use anyhow::{Context, Result}; +use hickory_proto::op::{Message, Query}; +use hickory_proto::rr::{Name, RData, RecordType}; +use nym_smolmix::{TcpStream, Tunnel}; +use tokio::sync::Mutex; + +/// Per-attempt DNS query timeout (a fresh socket is used for the retry). +const DNS_TIMEOUT: Duration = Duration::from_secs(10); +const DNS_ATTEMPTS: usize = 2; +/// How long a resolved address may be reused without a new lookup. +const DNS_TTL: Duration = Duration::from_secs(300); +/// Give up on a TCP connect through the mixnet after this long. +const TCP_CONNECT_TIMEOUT: Duration = Duration::from_secs(30); +/// Give up on tunnel bootstrap after this long. The bootstrap holds the +/// tunnel lock, so a hang here would otherwise block every caller forever. +const BOOTSTRAP_TIMEOUT: Duration = Duration::from_secs(90); + +struct TunnelSlot { + tunnel: Option<(u64, Tunnel)>, + next_gen: u64, +} + +static TUNNEL: Mutex = Mutex::const_new(TunnelSlot { + tunnel: None, + next_gen: 0, +}); + +static DNS_CACHE: StdMutex>> = StdMutex::new(None); + +/// Get the shared mixnet tunnel, bootstrapping one if none is cached. +/// The lock is held during bootstrap so concurrent callers wait for the +/// same tunnel instead of racing to build their own. +async fn get_tunnel() -> Result<(u64, Tunnel)> { + let mut slot = TUNNEL.lock().await; + if let Some((gen, tunnel)) = &slot.tunnel { + return Ok((*gen, tunnel.clone())); + } + tracing::info!("bootstrapping Nym mixnet tunnel"); + let start = Instant::now(); + let tunnel = tokio::time::timeout(BOOTSTRAP_TIMEOUT, Tunnel::builder().build()) + .await + .map_err(|_| anyhow::anyhow!("Nym mixnet tunnel bootstrap timed out"))? + .context("failed to bootstrap Nym mixnet tunnel")?; + tracing::info!("Nym mixnet tunnel ready in {:?}", start.elapsed()); + let gen = slot.next_gen; + slot.next_gen += 1; + slot.tunnel = Some((gen, tunnel.clone())); + Ok((gen, tunnel)) +} + +/// Discard the cached tunnel if it is still generation `gen`, so the next +/// call bootstraps a fresh one. The stale tunnel is shut down in the +/// background. +async fn invalidate_tunnel(gen: u64) { + let mut slot = TUNNEL.lock().await; + if let Some((g, tunnel)) = &slot.tunnel { + if *g == gen { + tracing::warn!("Nym tunnel failed; discarding it and clearing the DNS cache"); + let tunnel = tunnel.clone(); + slot.tunnel = None; + if let Ok(mut cache) = DNS_CACHE.lock() { + *cache = None; + } + tokio::spawn(async move { tunnel.shutdown().await }); + } + } +} + +/// Open a TCP stream to (host, port) through the Nym mixnet. +/// Transport-level failures invalidate the shared tunnel so the next +/// attempt (e.g. the mempool retry loop) recovers with a fresh one. +pub async fn nym_connect(host: &str, port: u16) -> Result { + let (gen, tunnel) = get_tunnel().await?; + + let ip = match resolve_over_nym(&tunnel, host).await { + Ok(Some(ip)) => ip, + // The DNS server answered but had no A record: the tunnel works, + // the hostname is just unresolvable. + Ok(None) => anyhow::bail!("no A record for {host} from mixnet DNS"), + Err(e) => { + invalidate_tunnel(gen).await; + return Err(e); + } + }; + + match tokio::time::timeout(TCP_CONNECT_TIMEOUT, tunnel.tcp_connect(SocketAddr::new(ip, port))) + .await + { + Ok(Ok(stream)) => Ok(stream), + Ok(Err(e)) => { + invalidate_tunnel(gen).await; + Err(e).with_context(|| format!("mixnet TCP connect to {host}:{port} failed")) + } + Err(_) => { + invalidate_tunnel(gen).await; + anyhow::bail!("mixnet TCP connect to {host}:{port} timed out") + } + } +} + +/// Resolve `host` through the mixnet unless it is an IP literal or freshly +/// cached. Returns `Ok(None)` when the DNS server responded without an A +/// record (tunnel healthy, name unresolvable); `Err` on transport failure. +async fn resolve_over_nym(tunnel: &Tunnel, host: &str) -> Result> { + if let Ok(ip) = host.parse::() { + return Ok(Some(ip)); + } + if let Some(ip) = dns_cache_get(host) { + return Ok(Some(ip)); + } + + let mut last_err = None; + for attempt in 0..DNS_ATTEMPTS { + // The timeout covers the whole query: socket creation and send can + // also stall when the tunnel's bridge is unhealthy, not just recv. + let query = tokio::time::timeout(DNS_TIMEOUT, dns_query(tunnel, host)) + .await + .map_err(|_| anyhow::anyhow!("mixnet DNS lookup for {host} timed out")) + .and_then(|r| r); + match query { + Ok(answer) => { + if let Some(ip) = answer { + dns_cache_put(host, ip); + } + return Ok(answer); + } + Err(e) => { + tracing::warn!("mixnet DNS lookup for {host} failed (attempt {attempt}): {e:#}"); + last_err = Some(e); + } + } + } + Err(last_err.expect("DNS_ATTEMPTS > 0")) +} + +/// One DNS A query over a fresh tunnel UDP socket. +/// `Ok(None)` means the server responded without a usable A record. +async fn dns_query(tunnel: &Tunnel, host: &str) -> Result> { + let udp = tunnel.udp_socket().await?; + let mut query = Message::new(); + query.set_recursion_desired(true); + query.add_query(Query::query(Name::from_ascii(host)?, RecordType::A)); + udp.send_to(&query.to_vec()?, "1.1.1.1:53".parse()?).await?; + let mut buf = [0u8; 1500]; + let (len, _src) = udp.recv_from(&mut buf).await?; + let response = Message::from_vec(&buf[..len])?; + Ok(first_a_record(&response)) +} + +fn dns_cache_get(host: &str) -> Option { + let cache = DNS_CACHE.lock().ok()?; + let (ip, at) = cache.as_ref()?.get(host)?; + (at.elapsed() < DNS_TTL).then_some(*ip) +} + +fn dns_cache_put(host: &str, ip: IpAddr) { + if let Ok(mut cache) = DNS_CACHE.lock() { + cache + .get_or_insert_with(HashMap::new) + .insert(host.to_string(), (ip, Instant::now())); + } +} + +/// First A record in a DNS response, if any. +fn first_a_record(msg: &Message) -> Option { + msg.answers().iter().find_map(|record| match record.data() { + Some(RData::A(a)) => Some(IpAddr::V4(a.0)), + _ => None, + }) +} + +#[cfg(test)] +mod tests { + use std::net::Ipv4Addr; + use std::str::FromStr; + + use hickory_proto::op::{Message, MessageType, Query}; + use hickory_proto::rr::{rdata, Name, RData, Record, RecordType}; + + use super::*; + + #[test] + fn first_a_record_skips_cname_and_picks_a() { + let name = Name::from_str("example.com.").unwrap(); + let mut msg = Message::new(); + msg.set_message_type(MessageType::Response); + msg.add_query(Query::query(name.clone(), RecordType::A)); + msg.add_answer(Record::from_rdata( + name.clone(), + 300, + RData::CNAME(rdata::CNAME(Name::from_str("alias.example.com.").unwrap())), + )); + msg.add_answer(Record::from_rdata( + name, + 300, + RData::A(rdata::A(Ipv4Addr::new(93, 184, 216, 34))), + )); + assert_eq!( + first_a_record(&msg), + Some(IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34))) + ); + } + + #[test] + fn first_a_record_none_when_no_a_answer() { + let msg = Message::new(); + assert_eq!(first_a_record(&msg), None); + } + + #[test] + fn dns_cache_round_trip_and_expiry_check() { + let ip = IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)); + dns_cache_put("cache-test.example", ip); + assert_eq!(dns_cache_get("cache-test.example"), Some(ip)); + assert_eq!(dns_cache_get("cache-miss.example"), None); + } +} diff --git a/rust/src/net/nym_service.rs b/rust/src/net/nym_service.rs new file mode 100644 index 000000000..606ffb048 --- /dev/null +++ b/rust/src/net/nym_service.rs @@ -0,0 +1,272 @@ +//! Mixnet-native RPC endpoints (`nym://` URLs). +//! +//! Speaks the [nym-rpc](https://github.com/rachyandco/nym-rpc) raw-tunnel +//! protocol: gRPC bytes are framed into bincode-serialized `ProxiedMessage`s +//! (nym-sdk `tcp_proxy` wire types) and exchanged with a nym-rpc server +//! addressed by its Nym recipient key — no IPR exit, no DNS, no clearnet hop +//! on the client side. The first data message of each session carries an +//! `UPSTREAM:host:port\n` hint; public nym-rpc servers pin their upstream +//! and ignore it. +//! +//! Integration mirrors nym-rpc's `TcpProxyClient`: a localhost forwarder +//! accepts plain TCP (tonic connects to it with h2c — Sphinx already +//! provides end-to-end encryption) and each accepted connection becomes an +//! ordered mixnet session. + +use std::collections::HashMap; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use anyhow::{anyhow, Result}; +use nym_sdk::client_pool::ClientPool; +use nym_sdk::mixnet::{ + IncludedSurbs, MixnetClient, MixnetClientBuilder, MixnetMessageSender, NymNetworkDetails, + Recipient, +}; +use nym_sdk::tcp_proxy::utils::{MessageBuffer, Payload, ProxiedMessage}; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::{oneshot, Mutex, OnceCell}; +use tokio_stream::StreamExt; +use tokio_util::codec::{BytesCodec, FramedRead}; +use tonic::transport::{Channel, Endpoint}; + +pub const NYM_URL_SCHEME: &str = "nym://"; +/// Upstream hint sent in the first message of a session (nym-rpc `--zcash` +/// preset value). Public nym-rpc servers pin their upstream and ignore it. +const DEFAULT_UPSTREAM: &str = "127.0.0.1:8137"; +/// Idle time after local EOF before the session's mixnet client is released. +const CLOSE_TIMEOUT: Duration = Duration::from_secs(60); +/// Give up building a mixnet client after this long. +const CLIENT_TIMEOUT: Duration = Duration::from_secs(90); +/// Pre-warmed mixnet clients (same as nym-rpc's default). +const POOL_SIZE: usize = 2; +/// Kill a session when a request has gone unanswered this long: bytes went +/// out after the last incoming message and nothing has come back since. +/// Long-lived quiet streams (e.g. the mempool long-poll, which receives +/// last) are not affected. This turns a lost RPC response — e.g. a +/// broadcast whose reply the mixnet dropped — into an error the app can +/// surface instead of hanging forever. +const STALL_TIMEOUT: Duration = Duration::from_secs(120); + +/// Parse a `nym://.@` URL into a Recipient. +pub fn parse_nym_url(url: &str) -> Option { + let rest = url.trim().strip_prefix(NYM_URL_SCHEME)?; + Recipient::try_from_base58_string(rest.trim_end_matches('/')).ok() +} + +/// One localhost forwarder per recipient, started on first use. +static FORWARDERS: Mutex>> = Mutex::const_new(None); +/// One shared gRPC channel per recipient: every RPC (sync, mempool, +/// block-height poll, broadcast) multiplexes over one warm mixnet session +/// instead of paying a client bootstrap per connection. +static CHANNELS: Mutex>> = Mutex::const_new(None); +static POOL: OnceCell> = OnceCell::const_new(); + +/// Shared gRPC channel to `recipient`. Lazy: tonic (re)connects through the +/// local forwarder on demand, so a dead session heals on the next RPC. +pub async fn grpc_channel(recipient: Recipient) -> Result { + let mut channels = CHANNELS.lock().await; + let channels = channels.get_or_insert_with(HashMap::new); + let key = recipient.to_string(); + if let Some(channel) = channels.get(&key) { + return Ok(channel.clone()); + } + let port = local_forwarder_port(recipient).await?; + let endpoint = Endpoint::from_shared(format!("http://127.0.0.1:{port}"))? + .connect_timeout(Duration::from_secs(30)); + let channel = endpoint.connect_lazy(); + channels.insert(key, channel.clone()); + Ok(channel) +} + +/// Local TCP port forwarding to `recipient` through the mixnet, binding a +/// listener for it on first use. +pub async fn local_forwarder_port(recipient: Recipient) -> Result { + let mut forwarders = FORWARDERS.lock().await; + let forwarders = forwarders.get_or_insert_with(HashMap::new); + let key = recipient.to_string(); + if let Some(port) = forwarders.get(&key) { + return Ok(*port); + } + let listener = TcpListener::bind(("127.0.0.1", 0)).await?; + let port = listener.local_addr()?.port(); + tracing::info!("nym-rpc forwarder for {key} listening on 127.0.0.1:{port}"); + tokio::spawn(accept_loop(listener, recipient)); + forwarders.insert(key, port); + Ok(port) +} + +async fn accept_loop(listener: TcpListener, recipient: Recipient) { + loop { + match listener.accept().await { + Ok((stream, _)) => { + tokio::spawn(async move { + if let Err(e) = run_session(stream, recipient).await { + tracing::warn!("nym-rpc session failed: {e:#}"); + } + }); + } + Err(e) => { + tracing::warn!("nym-rpc forwarder accept failed: {e}"); + tokio::time::sleep(Duration::from_millis(200)).await; + } + } + } +} + +/// A mixnet client from the shared pool, or an ephemeral one if the pool +/// has none ready yet. +async fn get_client() -> Result { + let pool = POOL + .get_or_init(|| async { + // Populate the nym network env (mainnet defaults) before any + // client is built — both the pool's internal builder and the + // ephemeral fallback read it (mirrors nym-rpc's setup_env call). + nym_network_defaults::setup_env(None::<&str>); + let pool = Arc::new(ClientPool::new(POOL_SIZE)); + let filler = Arc::clone(&pool); + tokio::spawn(async move { + if let Err(e) = filler.start().await { + tracing::warn!("nym-rpc client pool stopped: {e:#}"); + } + }); + pool + }) + .await; + if let Some(client) = pool.get_mixnet_client().await { + return Ok(client); + } + tracing::info!("nym-rpc client pool empty; building an ephemeral mixnet client"); + let net = NymNetworkDetails::new_from_env(); + let client = tokio::time::timeout(CLIENT_TIMEOUT, async { + MixnetClientBuilder::new_ephemeral() + .network_details(net) + .build()? + .connect_to_mixnet() + .await + .map_err(anyhow::Error::from) + }) + .await + .map_err(|_| anyhow!("mixnet client bootstrap timed out"))??; + Ok(client) +} + +/// One ordered mixnet session per local TCP connection, mirroring nym-rpc's +/// `TcpProxyClient::handle_incoming`. +async fn run_session(stream: TcpStream, recipient: Recipient) -> Result<()> { + let session_id = uuid::Uuid::new_v4(); + let mut client = get_client().await?; + tracing::debug!("nym-rpc session {session_id} started"); + + let (tx, mut rx) = oneshot::channel(); + let (read, mut write) = stream.into_split(); + let mut framed_read = FramedRead::new(read, BytesCodec::new()); + let sender = client.split_sender(); + + // Seconds-since-session-start of the last outgoing send / incoming + // message, for stall detection. + let started = Instant::now(); + let last_out = Arc::new(AtomicU64::new(0)); + let last_out_writer = Arc::clone(&last_out); + let mut last_in: u64 = 0; + + // Outgoing: local bytes -> ordered ProxiedMessages through the mixnet, + // UPSTREAM hint on the first message, Close on local EOF. + let out_started = started; + tokio::spawn(async move { + let mut message_id: u16 = 0; + while let Some(Ok(bytes)) = framed_read.next().await { + message_id += 1; + let data = if message_id == 1 { + let mut framed = format!("UPSTREAM:{DEFAULT_UPSTREAM}\n").into_bytes(); + framed.extend_from_slice(&bytes); + framed + } else { + bytes.to_vec() + }; + let message = ProxiedMessage::new(Payload::Data(data), session_id, message_id); + sender + .send_message(recipient, &bincode1::serialize(&message)?, IncludedSurbs::Amount(100)) + .await?; + last_out_writer.store(out_started.elapsed().as_secs().max(1), Ordering::Relaxed); + } + message_id += 1; + let message = ProxiedMessage::new(Payload::Close, session_id, message_id); + sender + .send_message(recipient, &bincode1::serialize(&message)?, IncludedSurbs::Amount(100)) + .await?; + tracing::debug!("nym-rpc session {session_id}: local EOF, Close sent"); + let _ = tx.send(true); + Ok::<_, anyhow::Error>(()) + }); + + // Incoming: reorder mixnet messages and write them to the local socket; + // after local EOF keep draining for CLOSE_TIMEOUT. + let mut msg_buffer = MessageBuffer::new(); + loop { + tokio::select! { + _ = &mut rx => break, + Some(message) = client.next() => { + let message = bincode1::deserialize::(&message.message)?; + msg_buffer.push(message); + msg_buffer.tick(&mut write).await?; + last_in = started.elapsed().as_secs().max(1); + }, + _ = tokio::time::sleep(Duration::from_millis(100)) => { + msg_buffer.tick(&mut write).await?; + // Stall: we sent a request after the last reply and the + // mixnet has returned nothing since. Drop the session so + // the caller gets an error instead of waiting forever. + let out = last_out.load(Ordering::Relaxed); + if out > last_in + && started.elapsed().as_secs().saturating_sub(last_in.max(out)) + > STALL_TIMEOUT.as_secs() + { + tracing::warn!( + "nym-rpc session {session_id} stalled (no reply for {}s); closing", + STALL_TIMEOUT.as_secs() + ); + client.disconnect().await; + return Ok(()); + } + } + } + } + loop { + tokio::select! { + Some(message) = client.next() => { + let message = bincode1::deserialize::(&message.message)?; + msg_buffer.push(message); + msg_buffer.tick(&mut write).await?; + }, + _ = tokio::time::sleep(CLOSE_TIMEOUT) => { + tracing::debug!("nym-rpc session {session_id} closed"); + client.disconnect().await; + return Ok(()); + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const ADDR: &str = "BbTPrU1gNTsPiieXdC58xkp5QFSHhUUM98BP1Rm2adf9.GKiGLNQB116YszFwbuweeL2GsrfpHpuUzq6JuqFQ8EEE@ZXSDhRTKU5HgMpH8ma78FftvLiKyZ6jWL1e2U7GD7gQ"; + + #[test] + fn parses_nym_scheme_url() { + assert!(parse_nym_url(&format!("nym://{ADDR}")).is_some()); + assert!(parse_nym_url(&format!("nym://{ADDR}/")).is_some()); + assert!(parse_nym_url(&format!(" nym://{ADDR} ")).is_some()); + } + + #[test] + fn rejects_non_nym_urls() { + assert!(parse_nym_url(ADDR).is_none()); // scheme required + assert!(parse_nym_url("https://zec.rocks").is_none()); + assert!(parse_nym_url("nym://not-a-recipient").is_none()); + assert!(parse_nym_url("").is_none()); + } +} diff --git a/rust/src/net/zebra.rs b/rust/src/net/zebra.rs index 3cbed4f59..8ff5be2f2 100644 --- a/rust/src/net/zebra.rs +++ b/rust/src/net/zebra.rs @@ -12,7 +12,6 @@ use std::{ }; use anyhow::{Context, Result}; -use arti_client::TorClient; use httparse::Status; use reqwest::Url; use rustls::{pki_types::ServerName, ClientConfig, RootCertStore}; @@ -20,7 +19,6 @@ use serde::Deserialize; use serde_json::{json, Value}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio_rustls::TlsConnector; -use tor_rtcompat::PreferredRuntime; use webpki_roots::TLS_SERVER_ROOTS; use zcash_primitives::transaction::OrchardBundle; use zcash_primitives::{block::BlockHeader, transaction::Transaction}; @@ -32,17 +30,13 @@ use zcash_protocol::consensus::{BlockHeight, BranchId}; const COMPACT_NOTE_SIZE: usize = 52; -use crate::{ - api::coin::{Network, TOR}, - lwd::*, - net::LwdServer, - IntoAnyhow, -}; +use crate::{api::coin::Network, lwd::*, net::LwdServer, IntoAnyhow}; #[derive(Clone)] pub struct ZebraClient { url: String, client: reqwest::Client, + transport: u8, ssl: bool, host: String, @@ -52,16 +46,17 @@ pub struct ZebraClient { } impl ZebraClient { - pub fn new(network: &Network, url: &str, proxy: &str) -> Result { - // Route Zebra (full node) JSON-RPC through the configured proxy when set. + pub fn new(network: &Network, url: &str, transport: u8, proxy: &str) -> Result { + // Direct/proxy Zebra JSON-RPC uses reqwest; the proxy applies only + // when the Proxy transport (3) is selected. // reqwest natively supports socks5/socks5h/http/https proxy URLs. - let client = if proxy.is_empty() { - reqwest::Client::new() - } else { + let client = if transport == 3 && !proxy.is_empty() { reqwest::Client::builder() .proxy(reqwest::Proxy::all(proxy).anyhow()?) .build() .anyhow()? + } else { + reqwest::Client::new() }; let url = Url::parse(url).anyhow()?; @@ -86,6 +81,7 @@ impl ZebraClient { Ok(Self { url: url.to_string(), client, + transport, ssl, host: host.to_string(), port, @@ -118,29 +114,40 @@ impl ZebraClient { where R: for<'de> Deserialize<'de>, { - let rep = if let Some(tor_client) = TOR.get() { - let tor = &*tor_client.lock().await; - self.post_tor(tor, req).await? - } else { - let body: Value = self - .client - .post(&self.url) - .json(&req) - .send() - .await? - .error_for_status()? - .json::() - .await?; - if let Some(error) = body.pointer("/error") { - if !error.is_null() { - let msg = error - .pointer("/message") - .and_then(|m| m.as_str()) - .unwrap_or("unknown error"); - anyhow::bail!("JSON RPC error: {}", msg); + let rep = match self.transport { + // Tor and Nym hand a raw stream to post_stream; Direct and + // Proxy keep the reqwest path. + 1 => { + let tor_client = crate::api::coin::get_tor_client().await.lock().await; + let stream = tor_client.connect((self.host.clone(), self.port)).await?; + drop(tor_client); + self.post_stream(Box::pin(stream), req).await? + } + 2 => { + let stream = crate::net::nym::nym_connect(&self.host, self.port).await?; + self.post_stream(Box::pin(stream), req).await? + } + _ => { + let body: Value = self + .client + .post(&self.url) + .json(&req) + .send() + .await? + .error_for_status()? + .json::() + .await?; + if let Some(error) = body.pointer("/error") { + if !error.is_null() { + let msg = error + .pointer("/message") + .and_then(|m| m.as_str()) + .unwrap_or("unknown error"); + anyhow::bail!("JSON RPC error: {}", msg); + } } + body } - body }; let result = rep .pointer("/result") @@ -149,26 +156,21 @@ impl ZebraClient { Ok(res) } - pub async fn post_tor( + async fn post_stream( &self, - tor_client: &TorClient, + stream: Pin>, req: Value, ) -> Result { - let connector = TlsConnector::from(self.tls_config.clone()); - - let host = self.host.clone(); - let server_name: ServerName = host.clone().try_into().anyhow()?; - - let stream = tor_client.connect((host, self.port)).await?; - let mut stream: Pin> = if self.ssl { + let connector = TlsConnector::from(self.tls_config.clone()); + let server_name: ServerName = self.host.clone().try_into().anyhow()?; let tls_stream = connector .connect(server_name, stream) .await - .context("TLS handshake failed over Tor stream")?; + .context("TLS handshake failed over transport stream")?; Box::pin(tls_stream) } else { - Box::pin(stream) + stream }; let request_json = req.to_string(); From a83f65552648136db1296daa2652448125195e8d Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 08:17:53 +0800 Subject: [PATCH 061/189] fix: fix ios build --- build_number.txt | 2 +- rust_builder/ios/rlz.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_number.txt b/build_number.txt index 1ce6b02d7..51272bac5 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -339 +340 diff --git a/rust_builder/ios/rlz.podspec b/rust_builder/ios/rlz.podspec index f139bf201..2fc9400eb 100644 --- a/rust_builder/ios/rlz.podspec +++ b/rust_builder/ios/rlz.podspec @@ -40,6 +40,6 @@ A new Flutter FFI plugin project. 'DEFINES_MODULE' => 'YES', # Flutter.framework does not contain a i386 slice. 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librlz.a', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librlz.a -framework SystemConfiguration', } end \ No newline at end of file From 267b070ebc7a7d67f4ffb4c6dc2f609409dcb53d Mon Sep 17 00:00:00 2001 From: hhanh00 Date: Sat, 15 Aug 2026 09:36:17 +0800 Subject: [PATCH 062/189] chore(main): release zkool 6.27.0 (#1200) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1d9a80f42..20a91f896 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.26.1" + ".": "6.27.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d275f71b..daf3240d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [6.27.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.26.1...zkool-v6.27.0) (2026-08-15) + + +### Features + +* add nym mixnet as transport ([#1195](https://github.com/hhanh00/zkool2/issues/1195)) ([59a5ed8](https://github.com/hhanh00/zkool2/commit/59a5ed8bd187e1ff2645e15448424f07d5a1ca55)) +* Zcash voting (ZIP 262) delegation and vote casting ([#1198](https://github.com/hhanh00/zkool2/issues/1198)) ([b59f958](https://github.com/hhanh00/zkool2/commit/b59f958915696bf3d50af590ac6ca0e765ab23cd)) + + +### Bug Fixes + +* fix ios build ([a83f655](https://github.com/hhanh00/zkool2/commit/a83f65552648136db1296daa2652448125195e8d)) +* honour RUST_LOG in zkool_graphql ([#1190](https://github.com/hhanh00/zkool2/issues/1190)) ([ca49412](https://github.com/hhanh00/zkool2/commit/ca4941250d2dfac13832d40066062cf6915ba579)) +* send to TEX (ZIP 320) addresses ([aba4f30](https://github.com/hhanh00/zkool2/commit/aba4f3012e6d5c761388fcbd4d452c080d7dc14a)) + ## [6.26.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.26.0...zkool-v6.26.1) (2026-08-02) diff --git a/build_number.txt b/build_number.txt index 51272bac5..947e93bc2 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -340 +341 diff --git a/pubspec.yaml b/pubspec.yaml index d05106902..4bc532416 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.26.1 # x-release-please-version +version: 6.27.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 0e10c8e2c..9cd1a39f6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.26.1 +6.27.0 From 1e5564ca8808768b2b2959484e7372f76a2083d2 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 14:06:11 +0800 Subject: [PATCH 063/189] feat: shielded voting UI (ZIP 262) Port the voting feature over the zcash_voting fork api: - recovery/plan read surface (voting_rounds/plan/recovery/ballot_intents) - vote-chain HTTP client (rust/src/net/votechain.rs, status-preserving) - delegation vertical: progress streams, prepare-resume, mark-submitted, wire-JSON reconstruction, restart-safe resume via persisted round config - vote path: ballot intents, drafts, commit stream, vote submit/confirm, share record/plan/tracking with resubmission - dynamic config resolution (static+dynamic authenticated, cached) - screens: polls, ballot, review, status, confirmation, results - submission guard blocks account deletion and vault sign-out mid-job cargo check and flutter analyze clean. --- lib/pages/account.dart | 6 + lib/pages/accounts.dart | 8 + lib/pages/voting_confirmation.dart | 55 + lib/pages/voting_polls.dart | 235 + lib/pages/voting_proposal.dart | 302 + lib/pages/voting_results.dart | 248 + lib/pages/voting_review.dart | 118 + lib/pages/voting_status.dart | 186 + lib/router.dart | 69 + lib/settings.dart | 74 + lib/src/rust/api/voting.dart | 671 +- lib/src/rust/api/voting.freezed.dart | 13282 +++++++++++++++++++++---- lib/src/rust/frb_generated.dart | 3632 ++++++- lib/src/rust/frb_generated.io.dart | 463 + lib/src/rust/frb_generated.web.dart | 463 + lib/store.dart | 691 ++ lib/store.freezed.dart | 806 +- lib/store.g.dart | 395 +- rust/src/api/voting.rs | 1658 ++- rust/src/db.rs | 8 + rust/src/frb_generated.rs | 5592 +++++++++-- rust/src/net/mod.rs | 1 + rust/src/net/votechain.rs | 142 + rust/src/voting.rs | 218 +- 24 files changed, 25773 insertions(+), 3550 deletions(-) create mode 100644 lib/pages/voting_confirmation.dart create mode 100644 lib/pages/voting_polls.dart create mode 100644 lib/pages/voting_proposal.dart create mode 100644 lib/pages/voting_results.dart create mode 100644 lib/pages/voting_review.dart create mode 100644 lib/pages/voting_status.dart create mode 100644 rust/src/net/votechain.rs diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 53b02c2aa..9ce8e1375 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -238,6 +238,8 @@ class AccountViewPageState extends ConsumerState with SingleTic GoRouter.of(context).push("/chart"); case "migration": GoRouter.of(context).push("/migrate"); + case "voting": + GoRouter.of(context).push("/voting"); case "settings": GoRouter.of(context).push("/settings"); default: @@ -288,6 +290,10 @@ class AccountViewPageState extends ConsumerState with SingleTic value: "migration", child: Text("Note Migration"), ), + const PopupMenuItem( + value: "voting", + child: Text("Voting"), + ), ], ), ], diff --git a/lib/pages/accounts.dart b/lib/pages/accounts.dart index 0138afb6a..459c4ebfd 100644 --- a/lib/pages/accounts.dart +++ b/lib/pages/accounts.dart @@ -137,6 +137,14 @@ class AccountListPageState extends ConsumerState with RouteAwar createBuilder: (context) => GoRouter.of(context).push("/account/new"), editBuilder: (context, a) => GoRouter.of(context).push("/account/edit", extra: a), deleteBuilder: (context, accounts) async { + if (ref.read(votingSubmissionGuardProvider)) { + await showMessage( + context, + "A voting submission is in progress. Wait for it to finish " + "before deleting accounts.", + ); + return; + } final confirmed = await confirmDialog(context, title: "Delete Account(s)", message: "Are you sure you want to delete these accounts?"); if (confirmed) { for (var a in accounts) { diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart new file mode 100644 index 000000000..588d2af87 --- /dev/null +++ b/lib/pages/voting_confirmation.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/store.dart'; + +/// Receipt screen shown after the submission job completes. +class VotingConfirmationPage extends ConsumerStatefulWidget { + final String roundId; + + const VotingConfirmationPage({super.key, required this.roundId}); + + @override + ConsumerState createState() => + VotingConfirmationPageState(); +} + +class VotingConfirmationPageState extends ConsumerState { + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + return Scaffold( + appBar: AppBar(title: const Text("Vote submitted")), + body: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Icon( + Icons.check_circle_outline, + size: 72, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 16), + Text( + "Your vote for ${widget.roundId} has been submitted.", + style: Theme.of(context).textTheme.titleMedium, + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + FilledButton( + onPressed: () => GoRouter.of(context).go("/voting"), + child: const Text("Done"), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart new file mode 100644 index 000000000..0ad5e6e03 --- /dev/null +++ b/lib/pages/voting_polls.dart @@ -0,0 +1,235 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; +import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/db.dart'; +import 'package:zkool/src/rust/api/voting.dart'; +import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; +import 'package:zkool/widgets/error_display.dart'; + +/// Round list for shielded voting (ZIP 262). Each row derives its action +/// label from the fork's resume plan (`primary_action`), so a restart shows +/// the correct "Resume"/"Start"/"View results" affordance without any Dart +/// session state. +class VotingPollsPage extends ConsumerStatefulWidget { + const VotingPollsPage({super.key}); + + @override + ConsumerState createState() => VotingPollsPageState(); +} + +class VotingPollsPageState extends ConsumerState { + late final c = coinContext.coin; + + @override + void initState() { + super.initState(); + Future(_guardHardwareAccount); + Future(() async { + final settings = await ref.read(appSettingsProvider.future); + if (settings.votingConfigUrl.isNotEmpty) { + await ref.read(votingConfigProvider.notifier).resolve(); + } + }); + } + + /// Voting v1 supports software accounts only; the fork signs with the + /// wallet seed, which hardware accounts cannot expose. + Future _guardHardwareAccount() async { + try { + final accounts = await ref.read(getAccountsProvider.future); + final selected = ref.read(selectedAccountIdProvider); + final account = accounts.where((a) => a.id == selected).firstOrNull; + if (account != null && account.hw != 0) { + if (mounted) { + await showMessage( + context, + "Voting is not supported for hardware accounts yet. " + "Switch to a software account to vote.", + ); + } + } + } on AnyhowException catch (e) { + if (mounted) await showException(context, e.message); + } + } + + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + final config = ref.watch(votingConfigProvider); + final rounds = ref.watch(votingRoundListProvider); + return Scaffold( + appBar: AppBar( + title: Text("Voting"), + actions: [ + IconButton( + icon: Icon(Icons.refresh), + onPressed: () { + ref.invalidate(votingRoundListProvider); + ref.read(votingConfigProvider.notifier).resolve(); + }, + ), + ], + ), + body: rounds.when( + loading: () => blank(context), + error: (e, _) => showError(e), + data: (list) { + final configRounds = config.value?.rounds ?? const []; + final localIds = list.map((r) => r.roundId).toSet(); + final joinable = configRounds + .where((r) => !localIds.contains(r.roundId)) + .toList(); + if (list.isEmpty && joinable.isEmpty) { + return const Center(child: Text("No voting rounds")); + } + final chainUrl = (config.value != null && + config.value!.voteServers.isNotEmpty) + ? config.value!.voteServers.first.url + : ""; + return RefreshIndicator( + onRefresh: () async => + ref.invalidate(votingRoundListProvider), + child: ListView( + children: [ + if (joinable.isNotEmpty) ...[ + const Padding( + padding: EdgeInsets.all(12), + child: Text("Open rounds", + style: TextStyle(fontWeight: FontWeight.bold)), + ), + ...joinable.map( + (r) => ListTile( + title: Text(r.roundId), + trailing: FilledButton.tonal( + onPressed: chainUrl.isEmpty + ? null + : () => GoRouter.of(context) + .push("/voting/proposal", extra: { + "roundId": r.roundId, + "chainUrl": chainUrl, + }), + child: const Text("Join"), + ), + ), + ), + const Divider(), + ], + ...list.map((r) => _RoundTile(round: r)), + ], + ), + ); + }, + ), + ); + } +} + +class _RoundTile extends ConsumerWidget { + final VotingRoundInfo round; + + const _RoundTile({required this.round}); + + String _actionLabel(String primaryAction) { + switch (primaryAction) { + case "delegate" || "vote" || "submit_shares": + return "Resume"; + case "done": + return "View results"; + default: + return "Start voting"; + } + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final cs = Theme.of(context).colorScheme; + final session = ref.watch(votingSessionProvider(round.roundId)); + return session.when( + loading: () => ListTile( + title: Text(round.roundId), + subtitle: Text("Snapshot height ${round.snapshotHeight}"), + trailing: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(strokeWidth: 2), + ), + ), + error: (e, _) => ListTile( + title: Text(round.roundId), + subtitle: Text("Snapshot height ${round.snapshotHeight}"), + trailing: IconButton( + icon: Icon(Icons.refresh), + onPressed: () => + ref.invalidate(votingSessionProvider(round.roundId)), + ), + ), + data: (state) { + final action = state.plan?.primaryAction ?? "idle"; + final label = _actionLabel(action); + return ListTile( + title: Text(round.roundId), + subtitle: Text( + "Snapshot height ${round.snapshotHeight} • " + "${round.bundleCount} bundle${round.bundleCount == 1 ? "" : "s"}", + ), + trailing: FilledButton.tonal( + onPressed: () => _openStatus(context, ref, action), + child: Text(label), + ), + selected: action != "idle" && action != "done", + selectedTileColor: cs.primaryContainer.withValues(alpha: 0.3), + ); + }, + ); + } + + Future _openStatus( + BuildContext context, + WidgetRef ref, + String action, + ) async { + final c = coinContext.coin; + final configValue = ref.read(votingConfigProvider).value; + final chainUrl = (configValue != null && configValue.voteServers.isNotEmpty) + ? configValue.voteServers.first.url + : await getProp(key: "voting_chain_url", c: c) ?? ""; + if (chainUrl.isEmpty) { + await showMessage( + context, + "No vote chain URL configured. Add voting_chain_url in settings or " + "resolve a voting config source.", + ); + return; + } + if (!context.mounted) return; + if (action == "done") { + await GoRouter.of(context).push("/voting/results", extra: { + "roundId": round.roundId, + "chainUrl": chainUrl, + }); + return; + } + if (action == "idle") { + // Fresh round: open the ballot first. + await GoRouter.of(context).push("/voting/proposal", extra: { + "roundId": round.roundId, + "chainUrl": chainUrl, + }); + return; + } + final settings = await ref.read(appSettingsProvider.future); + await GoRouter.of(context).push("/voting/status", extra: { + "roundId": round.roundId, + "chainUrl": chainUrl, + "pirServerUrl": "", + "voteNodeUrl": settings.voteNodeUrl, + }); + } +} diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart new file mode 100644 index 000000000..cfe99c0b0 --- /dev/null +++ b/lib/pages/voting_proposal.dart @@ -0,0 +1,302 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; +import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/voting.dart'; +import 'package:zkool/store.dart'; + +/// One parsed proposal option. +class _Option { + final int id; + final String label; + + const _Option({required this.id, required this.label}); +} + +/// One parsed proposal from the round status body (lenient). +class _Proposal { + final int id; + final String title; + final List<_Option> options; + + const _Proposal({ + required this.id, + required this.title, + required this.options, + }); +} + +/// Ballot screen: shows the round's proposals, lets the voter choose or skip +/// each one, persists the draft (props) and the durable ballot intent (voting +/// DB) on every change, then hands off to the review screen. +class VotingProposalPage extends ConsumerStatefulWidget { + final String roundId; + final String chainUrl; + + const VotingProposalPage({ + super.key, + required this.roundId, + required this.chainUrl, + }); + + @override + ConsumerState createState() => VotingProposalPageState(); +} + +class VotingProposalPageState extends ConsumerState { + List<_Proposal> _proposals = []; + Map _choices = {}; // proposal id -> option id + final Set _skipped = {}; + String? _error; + String? _roundParamsJson; + String? _roundName; + int? _snapshotHeight; + + @override + void initState() { + super.initState(); + Future(_load); + } + + /// Lenient nested field lookup (mirrors vizor's round-status parsing). + Object? _find(Map json, String key) { + if (json.containsKey(key)) return json[key]; + for (final entry in json.entries) { + if (entry.value is Map) { + final match = _find((entry.value as Map).cast(), key); + if (match != null) return match; + } + } + return null; + } + + Future _load() async { + try { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: widget.chainUrl, + roundId: widget.roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Round status failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final body = jsonDecode(res.body) as Map; + final round = body['round'] as Map? ?? {}; + final proposalsJson = round['proposals'] as List? ?? []; + _proposals = proposalsJson + .map(_parseProposal) + .whereType<_Proposal>() + .toList(); + + // Derive the authenticated round params for delegation_prepare from the + // cached config + the chain-reported snapshot fields. + final snapshotHeight = _find(round, "snapshot_height"); + final ncRoot = _find(round, "nc_root"); + final nullifierImtRoot = _find(round, "nullifier_imt_root"); + if (snapshotHeight is int && ncRoot is String && nullifierImtRoot is String) { + _snapshotHeight = snapshotHeight; + _roundName = (_find(round, "round_name") ?? _find(round, "name")) + ?.toString() ?? + widget.roundId; + final settings = await ref.read(appSettingsProvider.future); + if (settings.votingConfigUrl.isNotEmpty) { + _roundParamsJson = await votingRoundParamsJson( + source: settings.votingConfigUrl, + roundId: widget.roundId, + snapshotHeight: BigInt.from(snapshotHeight), + ncRoot: base64Decode(ncRoot), + nullifierImtRoot: base64Decode(nullifierImtRoot), + c: c, + ); + } + } + + // Best-effort vote-tree pre-sync so the commit step doesn't wait on it. + final settings = await ref.read(appSettingsProvider.future); + if (settings.voteNodeUrl.isNotEmpty) { + try { + await votingSyncTree( + roundId: widget.roundId, + voteNodeUrl: settings.voteNodeUrl, + c: c, + ); + } on AnyhowException catch (_) { + // The round may not exist locally yet; the commit step syncs anyway. + } + } + + final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); + if (drafts != null && drafts.isNotEmpty) { + final list = jsonDecode(drafts) as List; + for (final d in list) { + final map = d as Map; + final pid = map['proposal_id'] as int? ?? 0; + final choice = map['choice'] as int? ?? 0; + final numOptions = map['num_options'] as int? ?? 2; + if (choice == numOptions) { + _skipped.add(pid); + } else { + _choices[pid] = choice; + } + } + } + if (mounted) setState(() {}); + } on AnyhowException catch (e) { + if (mounted) setState(() => _error = e.message); + } + } + + _Proposal? _parseProposal(dynamic value) { + if (value is! Map) return null; + final id = value['id']; + if (id is! int || id < 1 || id > 15) return null; + final title = (value['title'] ?? "Proposal $id").toString(); + var options = (value['options'] as List? ?? []) + .map((o) { + if (o is! Map) return null; + return _Option( + id: (o['id'] is int) ? o['id'] as int : 0, + label: (o['label'] ?? o['title'] ?? "Option").toString(), + ); + }) + .whereType<_Option>() + .toList(); + if (options.isEmpty) { + // Vote-sdk default: Yes/No when options are missing. + options = const [ + _Option(id: 0, label: "Yes"), + _Option(id: 1, label: "No"), + ]; + } + return _Proposal(id: id, title: title, options: options); + } + + Future _persist() async { + final c = coinContext.coin; + for (final p in _proposals) { + if (_skipped.contains(p.id)) { + await votingSetBallotIntent( + roundId: widget.roundId, + proposalId: p.id, + skipped: true, + choice: 0, + numOptions: p.options.length, + c: c, + ); + } else if (_choices.containsKey(p.id)) { + await votingSetBallotIntent( + roundId: widget.roundId, + proposalId: p.id, + skipped: false, + choice: _choices[p.id]!, + numOptions: p.options.length, + c: c, + ); + } + } + // Draft votes mirror the fork's DraftVote JSON: skipped = choice == num_options. + final drafts = _proposals + .where((p) => _skipped.contains(p.id) || _choices.containsKey(p.id)) + .map((p) { + final skipped = _skipped.contains(p.id); + return { + "proposal_id": p.id, + "choice": skipped ? p.options.length : _choices[p.id], + "num_options": p.options.length, + "vc_tree_position": 0, + "single_share": false, + }; + }).toList(); + await votingDraftsSave( + roundId: widget.roundId, + draftsJson: jsonEncode(drafts), + c: c, + ); + } + + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + final allAnswered = _proposals.every( + (p) => _skipped.contains(p.id) || _choices.containsKey(p.id), + ); + + return Scaffold( + appBar: AppBar(title: Text(widget.roundId)), + body: _error != null + ? Center(child: Text(_error!)) + : _proposals.isEmpty + ? const Center(child: Text("No proposals found for this round")) + : ListView.builder( + itemCount: _proposals.length, + itemBuilder: (context, i) { + final p = _proposals[i]; + final selected = _choices[p.id]; + final skipped = _skipped.contains(p.id); + return Card( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(p.title, + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + ...p.options.map((o) => RadioListTile( + title: Text(o.label), + value: o.id, + groupValue: selected, + onChanged: (v) async { + setState(() { + _skipped.remove(p.id); + _choices[p.id] = v!; + }); + await _persist(); + }, + )), + RadioListTile( + title: const Text("Skip"), + value: -1, + groupValue: skipped ? -1 : null, + onChanged: (v) async { + setState(() { + _choices.remove(p.id); + _skipped.add(p.id); + }); + await _persist(); + }, + ), + ], + ), + ), + ); + }, + ), + bottomNavigationBar: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: FilledButton( + onPressed: allAnswered + ? () => GoRouter.of(context).push("/voting/review", extra: { + "roundId": widget.roundId, + "chainUrl": widget.chainUrl, + "roundParamsJson": _roundParamsJson, + "roundName": _roundName, + "snapshotHeight": _snapshotHeight, + }) + : null, + child: const Text("Review answers"), + ), + ), + ), + ); + } +} diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart new file mode 100644 index 000000000..2fa625b18 --- /dev/null +++ b/lib/pages/voting_results.dart @@ -0,0 +1,248 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/voting.dart'; +import 'package:zkool/store.dart'; + +/// Results screen: fetches the round tally from the vote chain and renders +/// per-proposal option bars with the winning option highlighted. While the +/// chain reports the round as tallying, it polls every 10 seconds. +class VotingResultsPage extends ConsumerStatefulWidget { + final String roundId; + final String chainUrl; + + const VotingResultsPage({ + super.key, + required this.roundId, + required this.chainUrl, + }); + + @override + ConsumerState createState() => VotingResultsPageState(); +} + +class VotingResultsPageState extends ConsumerState { + Timer? _pollTimer; + String? _error; + bool _tallying = false; + Map> _tallies = {}; // proposal id -> option id -> amount + + @override + void initState() { + super.initState(); + Future(_load); + } + + @override + void dispose() { + _pollTimer?.cancel(); + super.dispose(); + } + + Future _load() async { + try { + final c = coinContext.coin; + final session = await ref.read(votingSessionProvider(widget.roundId).future); + final intents = session.intents + .map((i) => i.proposalId) + .toSet() + .toList() + ..sort(); + final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); + if (drafts != null && drafts.isNotEmpty) { + for (final d in jsonDecode(drafts) as List) { + final pid = (d as Map)['proposal_id'] as int?; + if (pid != null && !intents.contains(pid)) intents.add(pid); + } + } + final res = await votechainRoundTally( + baseUrl: widget.chainUrl, + roundId: widget.roundId, + c: c, + ); + if (res.statusCode == 404) { + // Round still tallying or tally not published yet. + if (mounted) setState(() => _tallying = true); + _schedulePoll(); + return; + } + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Tally fetch failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final body = jsonDecode(res.body) as Map; + final status = ((body['status'] ?? body['phase'] ?? "") as String) + .toLowerCase(); + _tallying = status == "2" || status == "tallying" || status == "pending"; + _tallies = _parseTally(body, intents); + if (mounted) setState(() {}); + if (_tallying) _schedulePoll(); + } on AnyhowException catch (e) { + if (mounted) setState(() => _error = e.message); + } + } + + /// Lenient tally parse mirroring vizor's precedence: direct entry, + /// `tallies`/`results`/`proposals` map or list, then nested + /// `entries`/`options`/`tally`. Decision keys and amount keys are tried in + /// the same order as vizor's client. + Map> _parseTally(Map json, List proposalIds) { + final result = >{}; + + Object? value(List keys) { + for (final k in keys) { + if (json.containsKey(k)) return json[k]; + } + return null; + } + + int? toInt(Object? v) => v is int + ? v + : v is num + ? v.toInt() + : int.tryParse(v?.toString() ?? ""); + + num? toNum(Object? v) => v is num + ? v + : num.tryParse(v?.toString() ?? ""); + + int decisionOf(Object? v) => toInt(value(["vote_decision", "voteDecision", "decision", "choice", "index", "option", "option_id", "optionId"])) ?? 0; + + num? amountOf(Object? v) => toNum(value(["total_value", "totalValue", "amount", "votes", "value"])); + + void addDirect(Object? object, int proposalId) { + if (object is! Map) return; + final d = decisionOf(object); + final a = amountOf(object); + if (a != null) { + result.putIfAbsent(proposalId, () => {})[d] = a; + } + } + + void addEntries(Object? object, int proposalId) { + if (object is Map) { + for (final e in object.entries) { + final d = toInt(e.key) ?? 0; + final a = toNum(e.value); + if (a != null) result.putIfAbsent(proposalId, () => {})[d] = a; + } + } else if (object is List) { + for (final entry in object) { + if (entry is Map) addDirect(entry, proposalId); + } + } + } + + for (final pid in proposalIds) { + final tallies = value(["tallies", "results", "proposals"]); + if (tallies is Map) { + addEntries(tallies[pid.toString()], pid); + } + if (tallies is List) { + for (final item in tallies) { + if (item is! Map) continue; + final id = toInt(item["proposal_id"] ?? item["proposalId"] ?? item["id"]); + if (id == pid) { + addDirect(item, pid); + addEntries(item["entries"] ?? item["options"] ?? item["tally"], pid); + } + } + } + addEntries(value(["entries", "tally"]), pid); + } + return result; + } + + void _schedulePoll() { + _pollTimer?.cancel(); + _pollTimer = Timer(const Duration(seconds: 10), () { + if (mounted) Future(_load); + }); + } + + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + return Scaffold( + appBar: AppBar(title: Text("${widget.roundId} results")), + body: _error != null + ? Center(child: Text(_error!)) + : _tallies.isEmpty + ? Center( + child: Text( + _tallying + ? "Results pending..." + : "No tally data for this round", + ), + ) + : ListView.builder( + itemCount: _tallies.length, + itemBuilder: (context, i) { + final pid = _tallies.keys.elementAt(i); + final tally = _tallies[pid]!; + final total = tally.values.fold(0, (a, b) => a + b); + final winner = tally.entries.reduce( + (a, b) => a.value >= b.value ? a : b, + ); + return Card( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text("Proposal $pid", + style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + ...tally.entries.map((e) { + final fraction = total == 0 + ? 0.0 + : e.value / total; + final winning = e.key == winner.key; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + children: [ + SizedBox( + width: 80, + child: Text( + "Option ${e.key + 1}", + style: TextStyle( + fontWeight: winning + ? FontWeight.bold + : FontWeight.normal, + ), + ), + ), + Expanded( + child: LinearProgressIndicator( + value: fraction.clamp(0.0, 1.0), + minHeight: 8, + ), + ), + SizedBox( + width: 90, + child: Text( + "${(fraction * 100).toStringAsFixed(1)}%", + textAlign: TextAlign.end, + ), + ), + ], + ), + ); + }), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/pages/voting_review.dart b/lib/pages/voting_review.dart new file mode 100644 index 000000000..8737df880 --- /dev/null +++ b/lib/pages/voting_review.dart @@ -0,0 +1,118 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; +import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/voting.dart'; +import 'package:zkool/store.dart'; + +/// Read-only summary of the persisted draft ballot. "Confirm & submit" hands +/// off to the execution screen, which runs the submission job. +class VotingReviewPage extends ConsumerStatefulWidget { + final String roundId; + final String chainUrl; + final String? roundParamsJson; + final String? roundName; + final int? snapshotHeight; + + const VotingReviewPage({ + super.key, + required this.roundId, + required this.chainUrl, + this.roundParamsJson, + this.roundName, + this.snapshotHeight, + }); + + @override + ConsumerState createState() => VotingReviewPageState(); +} + +class VotingReviewPageState extends ConsumerState { + List> _drafts = []; + String? _error; + + @override + void initState() { + super.initState(); + Future(_load); + } + + Future _load() async { + try { + final c = coinContext.coin; + final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); + if (drafts != null && drafts.isNotEmpty) { + _drafts = (jsonDecode(drafts) as List) + .map((d) => d as Map) + .toList(); + } + if (mounted) setState(() {}); + } on AnyhowException catch (e) { + if (mounted) setState(() => _error = e.message); + } + } + + String _answerLabel(Map draft) { + final choice = draft['choice'] as int? ?? 0; + final numOptions = draft['num_options'] as int? ?? 2; + if (choice == numOptions) return "Skipped"; + return "Option ${choice + 1}"; + } + + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + return Scaffold( + appBar: AppBar(title: const Text("Review your answers")), + body: _error != null + ? Center(child: Text(_error!)) + : _drafts.isEmpty + ? const Center(child: Text("No ballot saved for this round")) + : ListView.builder( + itemCount: _drafts.length, + itemBuilder: (context, i) { + final draft = _drafts[i]; + return ListTile( + title: Text("Proposal ${draft['proposal_id']}"), + trailing: Text( + _answerLabel(draft), + style: TextStyle( + color: draft['choice'] == draft['num_options'] + ? Theme.of(context).colorScheme.outline + : Theme.of(context).colorScheme.primary, + ), + ), + ); + }, + ), + bottomNavigationBar: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: FilledButton( + onPressed: _drafts.isEmpty + ? null + : () async { + final settings = await ref.read(appSettingsProvider.future); + if (!context.mounted) return; + await GoRouter.of(context).push("/voting/status", extra: { + "roundId": widget.roundId, + "chainUrl": widget.chainUrl, + "pirServerUrl": "", + "voteNodeUrl": settings.voteNodeUrl, + "roundParamsJson": widget.roundParamsJson, + "roundName": widget.roundName, + "snapshotHeight": widget.snapshotHeight, + }); + }, + child: const Text("Confirm & submit"), + ), + ), + ), + ); + } +} diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart new file mode 100644 index 000000000..fb5c738ca --- /dev/null +++ b/lib/pages/voting_status.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/voting.dart'; +import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; + +/// Delegation execution screen: watches the submission job for a round, +/// renders per-stage progress, blocks leaving mid-run, and offers Retry on +/// error / Done on completion. +class VotingStatusPage extends ConsumerStatefulWidget { + final String roundId; + final String chainUrl; + final String pirServerUrl; + final VotingPirLayout? pirLayout; + final String? roundParamsJson; + final String? roundName; + final int? maxRealNotesPerBundle; + final String? lightwalletdUrl; + final String voteNodeUrl; + final int ceremonyStart; + final int? voteEnd; + final List shareServerUrls; + final bool singleShare; + + const VotingStatusPage({ + super.key, + required this.roundId, + required this.chainUrl, + required this.pirServerUrl, + this.pirLayout, + this.roundParamsJson, + this.roundName, + this.maxRealNotesPerBundle, + this.lightwalletdUrl, + this.voteNodeUrl = "", + this.ceremonyStart = 0, + this.voteEnd, + this.shareServerUrls = const [], + this.singleShare = false, + }); + + @override + ConsumerState createState() => VotingStatusPageState(); +} + +class VotingStatusPageState extends ConsumerState { + bool _handlingLeave = false; + + @override + void initState() { + super.initState(); + Future(_start); + } + + Future _start() async { + await ref + .read(votingSubmissionJobProvider(widget.roundId).notifier) + .start( + chainUrl: widget.chainUrl, + pirServerUrl: widget.pirServerUrl, + pirLayout: widget.pirLayout, + roundParamsJson: widget.roundParamsJson, + roundName: widget.roundName, + maxRealNotesPerBundle: widget.maxRealNotesPerBundle, + lightwalletdUrl: widget.lightwalletdUrl, + voteNodeUrl: widget.voteNodeUrl, + ceremonyStart: widget.ceremonyStart, + voteEnd: widget.voteEnd, + shareServerUrls: widget.shareServerUrls, + singleShare: widget.singleShare, + ); + } + + String _stageLabel(String stage) { + switch (stage) { + case "preparing": + return "Preparing delegation bundle"; + case "proving": + return "Generating zero-knowledge proof"; + case "submitting": + return "Submitting delegation to the vote chain"; + case "confirming": + return "Waiting for confirmation"; + case "done": + return "Delegation confirmed"; + case "error": + return "Submission failed"; + default: + return "Starting"; + } + } + + @override + Widget build(BuildContext context) { + final pinlock = ref.watch(lifecycleProvider); + if (pinlock.value ?? false) return PinLock(); + + final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); + final running = job.stage != "done" && job.stage != "error"; + + return PopScope( + canPop: !running, + onPopInvokedWithResult: (didPop, _) async { + if (didPop) return; + if (_handlingLeave) return; + _handlingLeave = true; + try { + final leave = await confirmDialog( + context, + title: "Submission in progress", + message: "Generating zero-knowledge proofs can take a while. " + "Are you sure you want to leave?", + ); + if (leave && mounted) GoRouter.of(context).pop(); + } finally { + _handlingLeave = false; + } + }, + child: Scaffold( + appBar: AppBar(title: const Text("Voting submission")), + body: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + _stageLabel(job.stage), + style: Theme.of(context).textTheme.titleLarge, + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + LinearProgressIndicator( + value: job.stage == "done" + ? 1 + : job.stage == "proving" || job.stage == "confirming" + ? null + : job.progress, + minHeight: 6, + ), + if (job.stage == "proving") + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + "Proof progress ${(job.progress * 100).toStringAsFixed(0)}%", + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 24), + if (job.stage == "error") ...[ + Text( + job.error ?? "Unknown error", + style: TextStyle( + color: Theme.of(context).colorScheme.error, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + FilledButton( + onPressed: () { + ref + .read(votingSubmissionJobProvider(widget.roundId).notifier) + .reset(); + Future(_start); + }, + child: const Text("Retry"), + ), + ] else if (job.stage == "done") + FilledButton( + onPressed: () => GoRouter.of(context).pushReplacement( + "/voting/confirmation", + extra: {"roundId": widget.roundId}, + ), + child: const Text("Done"), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/router.dart b/lib/router.dart index 30e5702f8..b685bfa30 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -24,6 +24,12 @@ import 'package:zkool/pages/splash.dart'; import 'package:zkool/pages/tx.dart'; import 'package:zkool/pages/tx_view.dart'; import 'package:zkool/pages/migrate.dart'; +import 'package:zkool/pages/voting_polls.dart'; +import 'package:zkool/pages/voting_proposal.dart'; +import 'package:zkool/pages/voting_review.dart'; +import 'package:zkool/pages/voting_confirmation.dart'; +import 'package:zkool/pages/voting_results.dart'; +import 'package:zkool/pages/voting_status.dart'; import 'package:zkool/pages/zsa.dart'; import 'package:zkool/pages/lwd_select.dart'; import 'package:zkool/pages/plugin_manager.dart'; @@ -32,6 +38,7 @@ import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/coin.dart'; import 'package:zkool/src/rust/api/contacts.dart'; import 'package:zkool/src/rust/api/pay.dart'; +import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/src/rust/pay.dart'; import 'package:zkool/store.dart'; import 'package:zkool/widgets/scanner.dart'; @@ -143,6 +150,68 @@ GoRouter router(bool disclaimerAccepted, bool recoveryMode) => GoRouter( GoRoute(path: '/lwd_select', builder: (context, state) => const LWDSelectPage()), GoRoute(path: '/show_animated_qr', builder: (context, state) => ShowAnimatedQRPage(state.extra as List)), GoRoute(path: '/migrate', builder: (context, state) => const MigratePage()), + GoRoute(path: '/voting', builder: (context, state) => const VotingPollsPage()), + GoRoute( + path: '/voting/proposal', + builder: (context, state) { + final args = state.extra as Map; + return VotingProposalPage( + roundId: args['roundId'] as String, + chainUrl: args['chainUrl'] as String, + ); + }, + ), + GoRoute( + path: '/voting/review', + builder: (context, state) { + final args = state.extra as Map; + return VotingReviewPage( + roundId: args['roundId'] as String, + chainUrl: args['chainUrl'] as String, + roundParamsJson: args['roundParamsJson'] as String?, + roundName: args['roundName'] as String?, + snapshotHeight: args['snapshotHeight'] as int?, + ); + }, + ), + GoRoute( + path: '/voting/confirmation', + builder: (context, state) { + final args = state.extra as Map; + return VotingConfirmationPage(roundId: args['roundId'] as String); + }, + ), + GoRoute( + path: '/voting/results', + builder: (context, state) { + final args = state.extra as Map; + return VotingResultsPage( + roundId: args['roundId'] as String, + chainUrl: args['chainUrl'] as String, + ); + }, + ), + GoRoute( + path: '/voting/status', + builder: (context, state) { + final args = state.extra as Map; + return VotingStatusPage( + roundId: args['roundId'] as String, + chainUrl: args['chainUrl'] as String, + pirServerUrl: args['pirServerUrl'] as String, + pirLayout: args['pirLayout'] as VotingPirLayout?, + roundParamsJson: args['roundParamsJson'] as String?, + roundName: args['roundName'] as String?, + maxRealNotesPerBundle: args['maxRealNotesPerBundle'] as int?, + lightwalletdUrl: args['lightwalletdUrl'] as String?, + voteNodeUrl: args['voteNodeUrl'] as String? ?? "", + ceremonyStart: args['ceremonyStart'] as int? ?? 0, + voteEnd: args['voteEnd'] as int?, + shareServerUrls: (args['shareServerUrls'] as List?) ?? const [], + singleShare: args['singleShare'] as bool? ?? false, + ); + }, + ), GoRoute(path: '/zsa', builder: (context, state) => const ZsaHoldingsPage()), GoRoute(path: '/zsa/issue', builder: (context, state) => IssueAssetPage(args: state.extra as IssuanceArgs?)), GoRoute(path: '/scan_animated_qr', builder: (context, state) => ScanAnimatedQRPage()), diff --git a/lib/settings.dart b/lib/settings.dart index 1f9f14905..807eb9a3a 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -240,6 +240,43 @@ class SettingsFormState extends ConsumerState { onChanged: onChangedProxy, ), ), + Tooltip( + message: "URL of the voting config source. The wallet fetches " + "and authenticates the static config, then the dynamic " + "config it points to, and caches the resolved result.", + child: Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: "voting_config_url", + decoration: const InputDecoration( + labelText: "Voting Config URL", + hintText: "https://…/voting-config.json", + ), + initialValue: settings.votingConfigUrl, + onChanged: onChangedVotingConfigUrl, + ), + ), + IconButton( + icon: const Icon(Icons.refresh), + onPressed: () => _fetchVotingConfig(context), + ), + ], + ), + ), + Tooltip( + message: "URL of the vote commitment tree node used for " + "VAN witness sync before casting votes.", + child: FormBuilderTextField( + name: "vote_node_url", + decoration: const InputDecoration( + labelText: "Vote Node URL", + hintText: "https://…/vote-node", + ), + initialValue: settings.voteNodeUrl, + onChanged: onChangedVoteNodeUrl, + ), + ), Tooltip( message: "Number actions per synchronization chunk", child: FormBuilderTextField( @@ -508,6 +545,43 @@ class SettingsFormState extends ConsumerState { }); } + void onChangedVotingConfigUrl(String? value) async { + if (value == null) return; + setState(() { + settings = settings.copyWith(votingConfigUrl: value); + widget.onChanged(settings); + }); + } + + void onChangedVoteNodeUrl(String? value) async { + if (value == null) return; + setState(() { + settings = settings.copyWith(voteNodeUrl: value); + widget.onChanged(settings); + }); + } + + Future _fetchVotingConfig(BuildContext context) async { + try { + final config = + await ref.read(votingConfigProvider.notifier).resolve(); + if (!context.mounted) return; + if (config == null) { + await showMessage( + context, + "No voting config source configured. Enter a URL first.", + ); + return; + } + showSnackbar( + "Voting config resolved: ${config.rounds.length} round(s), " + "switch ${config.switchKind}", + ); + } on AnyhowException catch (e) { + if (context.mounted) await showException(context, e.message); + } + } + void onChangedTransport(Set selection) { setState(() { settings = settings.copyWith(transport: selection.first); diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index 562308a1f..108e8b8a4 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -9,9 +9,9 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'voting.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `to_fork` +// These functions are ignored because they are not marked as `pub`: `config_switch_kind_string`, `fork_network_string`, `from_resolved`, `prepare_bundle`, `to_fork`, `votechain_proxy` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `VotingShareDelivery` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` /// Creates and persists a fresh app-owned voting hotkey (hex stored secret). Future votingHotkeyCreate({required Coin c}) => @@ -25,7 +25,9 @@ Future votingHotkeyGet({required Coin c}) => /// /// `round_params_json` is the JSON-serialized `VotingRoundParams` from the /// vote chain. The wallet must be synced through the round snapshot height; -/// witnesses are rooted at the snapshot's Ironwood `nc_root`. +/// witnesses are rooted at the snapshot's Ironwood `nc_root`. On success the +/// round inputs are persisted (props table) so a restart can re-prepare via +/// [`delegation_prepare_resume`]. Future delegationPrepare( {required String roundParamsJson, required String roundName, @@ -43,6 +45,23 @@ Future delegationPrepare( lightwalletdUrl: lightwalletdUrl, c: c); +/// Re-runs [`delegation_prepare`] for a round whose prepared bundle was lost +/// with the process (the prepared-bundle cache is process-local). Inputs come +/// from the config saved by the first prepare; the optional params override +/// the saved values when present. +Future delegationPrepareResume( + {required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationPrepareResume( + roundId: roundId, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c); + /// Builds and persists the governance PCZT setup for a prepared bundle. Future delegationSetup( {required String roundId, required int bundleIndex, required Coin c}) => @@ -81,6 +100,268 @@ Future delegationConfirm( eventsJson: eventsJson, c: c); +/// Builds and signs the delegation payload with live progress events +/// (`delegation_sign_and_submit` without the progress stream). +/// +/// `pir_layout` is persisted on first use; pass `None` after a restart to +/// resume with the saved layout. Returns the submission together with its +/// vote-chain wire JSON body (ready for `votechain_submit_delegation`). +Stream delegationBuildSubmission( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationBuildSubmission( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: pcztBytes, + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c); + +/// Returns the vote-chain wire JSON built by the last +/// [`delegation_build_submission`] run for a bundle, if any. +Future delegationWireJson( + {required String roundId, required int bundleIndex, required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationWireJson( + roundId: roundId, bundleIndex: bundleIndex, c: c); + +/// Atomically records a delegation transaction hash with idempotency checks, +/// so a restart between broadcast and confirmation resumes via `PollDelegation` +/// instead of re-broadcasting. +Future delegationMarkSubmitted( + {required String roundId, + required int bundleIndex, + required String txHash, + required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationMarkSubmitted( + roundId: roundId, bundleIndex: bundleIndex, txHash: txHash, c: c); + +/// Returns the recorded delegation transaction hash for a bundle, if any. +Future delegationTxHash( + {required String roundId, required int bundleIndex, required Coin c}) => + RustLib.instance.api.crateApiVotingDelegationTxHash( + roundId: roundId, bundleIndex: bundleIndex, c: c); + +/// Persists the voter's terminal decision for one proposal before any +/// zero-knowledge work, so a crash cannot lose the ballot and later votes are +/// conflict-checked against it. +Future votingSetBallotIntent( + {required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingSetBallotIntent( + roundId: roundId, + proposalId: proposalId, + skipped: skipped, + choice: choice, + numOptions: numOptions, + c: c); + +/// Persists the draft ballot for a round (props table, wallet-scoped). +Future votingDraftsSave( + {required String roundId, + required String draftsJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingDraftsSave( + roundId: roundId, draftsJson: draftsJson, c: c); + +/// Returns the persisted draft ballot for a round, if any. +Future votingDraftsLoad({required String roundId, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingDraftsLoad(roundId: roundId, c: c); + +/// Commits one bundle's votes with live stage events. Draft votes are +/// JSON-serialized fork `DraftVote`s; the VAN witness is derived internally +/// after syncing the vote tree. +Stream votingCommitWithProgress( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingCommitWithProgress( + roundId: roundId, + bundleIndex: bundleIndex, + draftsJson: draftsJson, + voteNodeUrl: voteNodeUrl, + c: c); + +/// Reconstructs the chain-ready wire JSON for a committed vote. +Future votingVoteWireJson( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c); + +/// Atomically records a cast-vote transaction hash with idempotency checks, so +/// a restart between broadcast and confirmation resumes via `PollVote`. +Future votingMarkVoteSubmitted( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingMarkVoteSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + c: c); + +/// Records a helper-share submission (derives the nullifier from recovery +/// state). +Future votingShareRecord( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List sentToUrls, + required BigInt submitAt, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingShareRecord( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + sentToUrls: sentToUrls, + submitAt: submitAt, + c: c); + +/// Lists unconfirmed helper-share records for a round. +Future> votingShareUnconfirmed( + {required String roundId, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingShareUnconfirmed(roundId: roundId, c: c); + +/// Marks one helper-share record confirmed. +Future votingShareConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingShareConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + c: c); + +/// Adds helper URLs to an existing share record after resubmission. +Future votingShareAddServers( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List newUrls, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingShareAddServers( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + newUrls: newUrls, + c: c); + +/// Reconstructs one helper-share payload as helper wire JSON from the +/// persisted commitment bundle. +Future votingShareWireJson( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingShareWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + vcTreePosition: vcTreePosition, + submitAt: submitAt, + c: c); + +/// Best-effort pre-sync of the vote commitment tree for a round, returning +/// the latest synced tree height. Requires the round to exist locally (it is +/// created by the first prepare); callers may ignore failures. +Future votingSyncTree( + {required String roundId, + required String voteNodeUrl, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingSyncTree( + roundId: roundId, voteNodeUrl: voteNodeUrl, c: c); + +/// Computes the share tracking plan for a round: summary counts, next poll +/// delay, last-moment flag, and freshly planned submissions (with local +/// entropy) for the unconfirmed shares. +Future votingSharePlan( + {required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List serverUrls, + required bool singleShare, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingSharePlan( + roundId: roundId, + now: now, + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + serverUrls: serverUrls, + singleShare: singleShare, + c: c); + +/// Resolves and authenticates the voting config for a source URL. +/// +/// The wallet owns transport: it fetches the static bytes, learns the dynamic +/// URL, fetches the dynamic bytes, then Rust authenticates both and classifies +/// the config switch against the previously resolved summary. The result is +/// cached in the props table so [`voting_config_cached`] can serve as a +/// last-good fallback. +Future votingConfigResolve( + {required String source, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingConfigResolve(source: source, c: c); + +/// Returns the last cached resolved config for a source URL, if any. +Future votingConfigCached( + {required String source, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingConfigCached(source: source, c: c); + +/// Builds the round params JSON for `delegation_prepare` from the cached +/// authenticated config plus chain-reported snapshot fields (`ea_pk` is +/// pinned to the authenticated config, so a stale endpoint cannot steer +/// voting to the wrong authority or roots). +Future votingRoundParamsJson( + {required String source, + required String roundId, + required BigInt snapshotHeight, + required List ncRoot, + required List nullifierImtRoot, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRoundParamsJson( + source: source, + roundId: roundId, + snapshotHeight: snapshotHeight, + ncRoot: ncRoot, + nullifierImtRoot: nullifierImtRoot, + c: c); + +/// Clears the cached resolved configs (all sources). +Future votingConfigClearCache({required Coin c}) => + RustLib.instance.api.crateApiVotingVotingConfigClearCache(c: c); + /// Syncs the vote-authority-note tree and derives this bundle's VAN witness. Future votingVanWitness( {required String roundId, @@ -157,6 +438,176 @@ Future votingConfirm( eventsJson: eventsJson, c: c); +/// Lists rounds persisted in the voting DB for the current wallet. +Future> votingRounds({required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRounds(c: c); + +/// Returns the derived resume plan for a round (the ordered work that remains +/// after any restart; empty `next_steps` with `primary_action == "done"` means +/// the round is complete for this wallet). +Future votingPlan( + {required String roundId, + required List proposalIds, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingPlan( + roundId: roundId, proposalIds: proposalIds, c: c); + +/// Returns the full read-only recovery snapshot for a round. +Future votingRecovery( + {required String roundId, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRecovery(roundId: roundId, c: c); + +/// Clears unconfirmed recovery artifacts for a round. Ballot intents, recorded +/// confirmations, and imported delegation capabilities are preserved. +Future votingRecoveryClear({required String roundId, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingRecoveryClear(roundId: roundId, c: c); + +/// Returns the persisted ballot intents for a round, sorted by proposal id. +Future> votingBallotIntents( + {required String roundId, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingBallotIntents(roundId: roundId, c: c); + +/// Lists rounds from the vote server (`{ "rounds": [...] }`). +Future votechainListRounds( + {required String baseUrl, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotechainListRounds(baseUrl: baseUrl, c: c); + +/// Fetches one round's status (`{ "round": ... }` envelope). +Future votechainRoundStatus( + {required String baseUrl, required String roundId, required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainRoundStatus( + baseUrl: baseUrl, roundId: roundId, c: c); + +/// Fetches the round tally envelope. +Future votechainRoundTally( + {required String baseUrl, required String roundId, required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainRoundTally( + baseUrl: baseUrl, roundId: roundId, c: c); + +/// Broadcasts a delegation transaction to the vote chain. +Future votechainSubmitDelegation( + {required String baseUrl, + required String submissionJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainSubmitDelegation( + baseUrl: baseUrl, submissionJson: submissionJson, c: c); + +/// Broadcasts a vote commitment transaction to the vote chain. +Future votechainSubmitVote( + {required String baseUrl, + required String submissionJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainSubmitVote( + baseUrl: baseUrl, submissionJson: submissionJson, c: c); + +/// Fetches the on-chain confirmation for a transaction; 404 = not confirmed. +Future votechainTxConfirmation( + {required String baseUrl, required String txHash, required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainTxConfirmation( + baseUrl: baseUrl, txHash: txHash, c: c); + +/// Posts one encrypted share to a helper server. +Future votechainSubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainSubmitShare( + serverUrl: serverUrl, payloadJson: payloadJson, c: c); + +/// Resends a previously generated share to a helper server (same endpoint as +/// the initial submission). +Future votechainResubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainResubmitShare( + serverUrl: serverUrl, payloadJson: payloadJson, c: c); + +/// Checks whether a helper has confirmed a share identified by its nullifier. +Future votechainShareStatus( + {required String serverUrl, + required String roundId, + required String shareId, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotechainShareStatus( + serverUrl: serverUrl, roundId: roundId, shareId: shareId, c: c); + +/// The voter's terminal decision for one proposal. +@freezed +sealed class VotingBallotIntent with _$VotingBallotIntent { + const factory VotingBallotIntent({ + required int proposalId, + required bool skipped, + int? choice, + }) = _VotingBallotIntent; +} + +/// Generic vote-chain HTTP response: status code + raw JSON body. +/// +/// 404 means "not found" (e.g. a transaction that is not confirmed yet) and +/// 422 means a deterministic chain rejection whose body is a `VotingTxResult`. +/// Only network failures surface as `Err`. +@freezed +sealed class VotingChainResponse with _$VotingChainResponse { + const factory VotingChainResponse({ + required int statusCode, + required String body, + }) = _VotingChainResponse; +} + +/// Display choice for one proposal in a completed round. +@freezed +sealed class VotingCompletedVoteChoice with _$VotingCompletedVoteChoice { + const factory VotingCompletedVoteChoice({ + required int proposalId, + int? choice, + }) = _VotingCompletedVoteChoice; +} + +/// Read-only display summary for a locally completed vote. +@freezed +sealed class VotingCompletedVoteDisplay with _$VotingCompletedVoteDisplay { + const factory VotingCompletedVoteDisplay({ + required List choices, + BigInt? votedAt, + }) = _VotingCompletedVoteDisplay; +} + +/// Authenticated dynamic voting config, ready for wallet use. +@freezed +sealed class VotingConfig with _$VotingConfig { + const factory VotingConfig({ + required String source, + required String sourceFingerprint, + required String trustedKeyFingerprint, + required String switchKind, + required List voteServers, + required List pirServers, + VotingPirLayout? pirLayout, + required List rounds, + }) = _VotingConfig; +} + +/// Round authenticated by the dynamic voting config. +@freezed +sealed class VotingConfigRound with _$VotingConfigRound { + const factory VotingConfigRound({ + required String roundId, + required Uint8List eaPk, + }) = _VotingConfigRound; +} + +@freezed +sealed class VotingDelegationBuild with _$VotingDelegationBuild { + const factory VotingDelegationBuild({ + required VotingDelegationSubmission submission, + required String wireJson, + }) = _VotingDelegationBuild; +} + @freezed sealed class VotingDelegationConfirmation with _$VotingDelegationConfirmation { const factory VotingDelegationConfirmation({ @@ -165,6 +616,41 @@ sealed class VotingDelegationConfirmation with _$VotingDelegationConfirmation { }) = _VotingDelegationConfirmation; } +@freezed +sealed class VotingDelegationProgress with _$VotingDelegationProgress { + const VotingDelegationProgress._(); + + const factory VotingDelegationProgress.selectingNotes() = + VotingDelegationProgress_SelectingNotes; + const factory VotingDelegationProgress.pcztBuilding() = + VotingDelegationProgress_PcztBuilding; + const factory VotingDelegationProgress.pcztBuilt() = + VotingDelegationProgress_PcztBuilt; + const factory VotingDelegationProgress.proofStarting() = + VotingDelegationProgress_ProofStarting; + const factory VotingDelegationProgress.proofProgress({ + required double progress, + }) = VotingDelegationProgress_ProofProgress; + const factory VotingDelegationProgress.proofComplete() = + VotingDelegationProgress_ProofComplete; + const factory VotingDelegationProgress.signingPayload() = + VotingDelegationProgress_SigningPayload; + const factory VotingDelegationProgress.payloadReady() = + VotingDelegationProgress_PayloadReady; +} + +/// Delegation recovery state for one bundle. +@freezed +sealed class VotingDelegationRecovery with _$VotingDelegationRecovery { + const factory VotingDelegationRecovery({ + required int bundleIndex, + required String phase, + required String workflowPhase, + String? txHash, + int? vanLeafPosition, + }) = _VotingDelegationRecovery; +} + @freezed sealed class VotingDelegationSetup with _$VotingDelegationSetup { const factory VotingDelegationSetup({ @@ -177,6 +663,16 @@ sealed class VotingDelegationSetup with _$VotingDelegationSetup { }) = _VotingDelegationSetup; } +/// Durable delegation state for one eligible bundle. +@freezed +sealed class VotingDelegationStatus with _$VotingDelegationStatus { + const factory VotingDelegationStatus({ + required int bundleIndex, + required String phase, + String? txHash, + }) = _VotingDelegationStatus; +} + @freezed sealed class VotingDelegationSubmission with _$VotingDelegationSubmission { const factory VotingDelegationSubmission({ @@ -203,6 +699,18 @@ sealed class VotingEncryptedShare with _$VotingEncryptedShare { }) = _VotingEncryptedShare; } +/// One remaining unit of recovery work for a round. +@freezed +sealed class VotingNextStep with _$VotingNextStep { + const factory VotingNextStep({ + required String kind, + required int bundleIndex, + required int proposalId, + required int choice, + required int shareIndex, + }) = _VotingNextStep; +} + @freezed sealed class VotingPirLayout with _$VotingPirLayout { const factory VotingPirLayout({ @@ -224,6 +732,80 @@ sealed class VotingPreparedInfo with _$VotingPreparedInfo { }) = _VotingPreparedInfo; } +/// Round row from the voting DB (rounds list). +@freezed +sealed class VotingRoundInfo with _$VotingRoundInfo { + const factory VotingRoundInfo({ + required String roundId, + required String network, + required BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + required int bundleCount, + required BigInt createdAt, + }) = _VotingRoundInfo; +} + +/// Derived resume state for one round. +@freezed +sealed class VotingRoundPlan with _$VotingRoundPlan { + const factory VotingRoundPlan({ + required String roundId, + required bool pendingRecovery, + required List nextSteps, + required Uint32List openProposals, + required bool allDecided, + required List delegationStatuses, + required bool blockingRecovery, + required bool blockingShareWork, + required bool hotkeyBound, + required bool completedVoteArtifact, + required bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + required bool needsDraftSetup, + required String primaryAction, + }) = _VotingRoundPlan; +} + +/// Full read-only recovery snapshot for one round. +@freezed +sealed class VotingRoundRecovery with _$VotingRoundRecovery { + const factory VotingRoundRecovery({ + required String roundId, + required int bundleCount, + required List delegation, + required List votes, + required List shares, + required List shareDelegations, + required List unconfirmedShareDelegations, + }) = _VotingRoundRecovery; +} + +/// Endpoint advertised by a voting service config. +@freezed +sealed class VotingServiceEndpoint with _$VotingServiceEndpoint { + const factory VotingServiceEndpoint({ + required String url, + required String label, + }) = _VotingServiceEndpoint; +} + +/// A share delegation record from the local DB. +@freezed +sealed class VotingShareDelegationRecord with _$VotingShareDelegationRecord { + const factory VotingShareDelegationRecord({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List sentToUrls, + required Uint8List nullifier, + required bool confirmed, + required BigInt submitAt, + required BigInt createdAt, + }) = _VotingShareDelegationRecord; +} + @freezed sealed class VotingSharePayload with _$VotingSharePayload { const factory VotingSharePayload({ @@ -238,6 +820,51 @@ sealed class VotingSharePayload with _$VotingSharePayload { }) = _VotingSharePayload; } +/// The share tracking plan for a round: summary, next poll delay, last-moment +/// flag, and freshly planned submissions for the unconfirmed shares. +@freezed +sealed class VotingSharePlan with _$VotingSharePlan { + const factory VotingSharePlan({ + required VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + required bool lastMoment, + required List submissions, + }) = _VotingSharePlan; +} + +/// One planned helper-share submission. +@freezed +sealed class VotingSharePlanItem with _$VotingSharePlanItem { + const factory VotingSharePlanItem({ + required BigInt submitAt, + required int targetCount, + required List targetServers, + }) = _VotingSharePlanItem; +} + +/// Share tracking summary, one-to-one with the fork's `ShareTrackingSummary`. +@freezed +sealed class VotingShareTrackingSummary with _$VotingShareTrackingSummary { + const factory VotingShareTrackingSummary({ + required BigInt total, + required BigInt confirmed, + required BigInt waiting, + required BigInt ready, + required BigInt overdue, + }) = _VotingShareTrackingSummary; +} + +/// Share recovery state for one delegated share. +@freezed +sealed class VotingShareWorkflow with _$VotingShareWorkflow { + const factory VotingShareWorkflow({ + required int bundleIndex, + required int proposalId, + required int shareIndex, + required String phase, + }) = _VotingShareWorkflow; +} + @freezed sealed class VotingSignedVoteCommitment with _$VotingSignedVoteCommitment { const factory VotingSignedVoteCommitment({ @@ -264,6 +891,29 @@ sealed class VotingVanWitness with _$VotingVanWitness { }) = _VotingVanWitness; } +@freezed +sealed class VotingVoteCommitStage with _$VotingVoteCommitStage { + const VotingVoteCommitStage._(); + + const factory VotingVoteCommitStage.proofStarting({ + required int proposalId, + required int bundleIndex, + }) = VotingVoteCommitStage_ProofStarting; + const factory VotingVoteCommitStage.proofProgress({ + required int proposalId, + required int bundleIndex, + required double progress, + }) = VotingVoteCommitStage_ProofProgress; + const factory VotingVoteCommitStage.sharePayloadsBuilding({ + required int proposalId, + required int bundleIndex, + }) = VotingVoteCommitStage_SharePayloadsBuilding; + const factory VotingVoteCommitStage.signing({ + required int proposalId, + required int bundleIndex, + }) = VotingVoteCommitStage_Signing; +} + @freezed sealed class VotingVoteCommitments with _$VotingVoteCommitments { const factory VotingVoteCommitments({ @@ -289,6 +939,21 @@ sealed class VotingVotePayloads with _$VotingVotePayloads { }) = _VotingVotePayloads; } +/// Vote recovery state for one vote key. +@freezed +sealed class VotingVoteRecovery with _$VotingVoteRecovery { + const factory VotingVoteRecovery({ + required int bundleIndex, + required int proposalId, + required int choice, + required String phase, + required String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + required bool hasCommitmentBundle, + }) = _VotingVoteRecovery; +} + @freezed sealed class VotingVoteSubmission with _$VotingVoteSubmission { const factory VotingVoteSubmission({ diff --git a/lib/src/rust/api/voting.freezed.dart b/lib/src/rust/api/voting.freezed.dart index b0df52853..626558658 100644 --- a/lib/src/rust/api/voting.freezed.dart +++ b/lib/src/rust/api/voting.freezed.dart @@ -13,79 +13,84 @@ part of 'voting.dart'; T _$identity(T value) => value; /// @nodoc -mixin _$VotingDelegationConfirmation { - String get txHash; - int get vanLeafPosition; +mixin _$VotingBallotIntent { + int get proposalId; + bool get skipped; + int? get choice; - /// Create a copy of VotingDelegationConfirmation + /// Create a copy of VotingBallotIntent /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingDelegationConfirmationCopyWith - get copyWith => _$VotingDelegationConfirmationCopyWithImpl< - VotingDelegationConfirmation>( - this as VotingDelegationConfirmation, _$identity); + $VotingBallotIntentCopyWith get copyWith => + _$VotingBallotIntentCopyWithImpl( + this as VotingBallotIntent, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingDelegationConfirmation && - (identical(other.txHash, txHash) || other.txHash == txHash) && - (identical(other.vanLeafPosition, vanLeafPosition) || - other.vanLeafPosition == vanLeafPosition)); + other is VotingBallotIntent && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.skipped, skipped) || other.skipped == skipped) && + (identical(other.choice, choice) || other.choice == choice)); } @override - int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); + int get hashCode => Object.hash(runtimeType, proposalId, skipped, choice); @override String toString() { - return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + return 'VotingBallotIntent(proposalId: $proposalId, skipped: $skipped, choice: $choice)'; } } /// @nodoc -abstract mixin class $VotingDelegationConfirmationCopyWith<$Res> { - factory $VotingDelegationConfirmationCopyWith( - VotingDelegationConfirmation value, - $Res Function(VotingDelegationConfirmation) _then) = - _$VotingDelegationConfirmationCopyWithImpl; +abstract mixin class $VotingBallotIntentCopyWith<$Res> { + factory $VotingBallotIntentCopyWith( + VotingBallotIntent value, $Res Function(VotingBallotIntent) _then) = + _$VotingBallotIntentCopyWithImpl; @useResult - $Res call({String txHash, int vanLeafPosition}); + $Res call({int proposalId, bool skipped, int? choice}); } /// @nodoc -class _$VotingDelegationConfirmationCopyWithImpl<$Res> - implements $VotingDelegationConfirmationCopyWith<$Res> { - _$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); +class _$VotingBallotIntentCopyWithImpl<$Res> + implements $VotingBallotIntentCopyWith<$Res> { + _$VotingBallotIntentCopyWithImpl(this._self, this._then); - final VotingDelegationConfirmation _self; - final $Res Function(VotingDelegationConfirmation) _then; + final VotingBallotIntent _self; + final $Res Function(VotingBallotIntent) _then; - /// Create a copy of VotingDelegationConfirmation + /// Create a copy of VotingBallotIntent /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? txHash = null, - Object? vanLeafPosition = null, + Object? proposalId = null, + Object? skipped = null, + Object? choice = freezed, }) { return _then(_self.copyWith( - txHash: null == txHash - ? _self.txHash - : txHash // ignore: cast_nullable_to_non_nullable - as String, - vanLeafPosition: null == vanLeafPosition - ? _self.vanLeafPosition - : vanLeafPosition // ignore: cast_nullable_to_non_nullable + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable as int, + skipped: null == skipped + ? _self.skipped + : skipped // ignore: cast_nullable_to_non_nullable + as bool, + choice: freezed == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int?, )); } } -/// Adds pattern-matching-related methods to [VotingDelegationConfirmation]. -extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { +/// Adds pattern-matching-related methods to [VotingBallotIntent]. +extension VotingBallotIntentPatterns on VotingBallotIntent { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -100,12 +105,12 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingDelegationConfirmation value)? $default, { + TResult Function(_VotingBallotIntent value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation() when $default != null: + case _VotingBallotIntent() when $default != null: return $default(_that); case _: return orElse(); @@ -127,11 +132,11 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult map( - TResult Function(_VotingDelegationConfirmation value) $default, + TResult Function(_VotingBallotIntent value) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation(): + case _VotingBallotIntent(): return $default(_that); } } @@ -150,11 +155,11 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingDelegationConfirmation value)? $default, + TResult? Function(_VotingBallotIntent value)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation() when $default != null: + case _VotingBallotIntent() when $default != null: return $default(_that); case _: return null; @@ -175,13 +180,13 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult maybeWhen( - TResult Function(String txHash, int vanLeafPosition)? $default, { + TResult Function(int proposalId, bool skipped, int? choice)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation() when $default != null: - return $default(_that.txHash, _that.vanLeafPosition); + case _VotingBallotIntent() when $default != null: + return $default(_that.proposalId, _that.skipped, _that.choice); case _: return orElse(); } @@ -202,12 +207,12 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult when( - TResult Function(String txHash, int vanLeafPosition) $default, + TResult Function(int proposalId, bool skipped, int? choice) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation(): - return $default(_that.txHash, _that.vanLeafPosition); + case _VotingBallotIntent(): + return $default(_that.proposalId, _that.skipped, _that.choice); } } @@ -225,12 +230,12 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String txHash, int vanLeafPosition)? $default, + TResult? Function(int proposalId, bool skipped, int? choice)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationConfirmation() when $default != null: - return $default(_that.txHash, _that.vanLeafPosition); + case _VotingBallotIntent() when $default != null: + return $default(_that.proposalId, _that.skipped, _that.choice); case _: return null; } @@ -239,200 +244,162 @@ extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { /// @nodoc -class _VotingDelegationConfirmation implements VotingDelegationConfirmation { - const _VotingDelegationConfirmation( - {required this.txHash, required this.vanLeafPosition}); +class _VotingBallotIntent implements VotingBallotIntent { + const _VotingBallotIntent( + {required this.proposalId, required this.skipped, this.choice}); @override - final String txHash; + final int proposalId; @override - final int vanLeafPosition; + final bool skipped; + @override + final int? choice; - /// Create a copy of VotingDelegationConfirmation + /// Create a copy of VotingBallotIntent /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingDelegationConfirmationCopyWith<_VotingDelegationConfirmation> - get copyWith => __$VotingDelegationConfirmationCopyWithImpl< - _VotingDelegationConfirmation>(this, _$identity); + _$VotingBallotIntentCopyWith<_VotingBallotIntent> get copyWith => + __$VotingBallotIntentCopyWithImpl<_VotingBallotIntent>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingDelegationConfirmation && - (identical(other.txHash, txHash) || other.txHash == txHash) && - (identical(other.vanLeafPosition, vanLeafPosition) || - other.vanLeafPosition == vanLeafPosition)); + other is _VotingBallotIntent && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.skipped, skipped) || other.skipped == skipped) && + (identical(other.choice, choice) || other.choice == choice)); } @override - int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); + int get hashCode => Object.hash(runtimeType, proposalId, skipped, choice); @override String toString() { - return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + return 'VotingBallotIntent(proposalId: $proposalId, skipped: $skipped, choice: $choice)'; } } /// @nodoc -abstract mixin class _$VotingDelegationConfirmationCopyWith<$Res> - implements $VotingDelegationConfirmationCopyWith<$Res> { - factory _$VotingDelegationConfirmationCopyWith( - _VotingDelegationConfirmation value, - $Res Function(_VotingDelegationConfirmation) _then) = - __$VotingDelegationConfirmationCopyWithImpl; +abstract mixin class _$VotingBallotIntentCopyWith<$Res> + implements $VotingBallotIntentCopyWith<$Res> { + factory _$VotingBallotIntentCopyWith( + _VotingBallotIntent value, $Res Function(_VotingBallotIntent) _then) = + __$VotingBallotIntentCopyWithImpl; @override @useResult - $Res call({String txHash, int vanLeafPosition}); + $Res call({int proposalId, bool skipped, int? choice}); } /// @nodoc -class __$VotingDelegationConfirmationCopyWithImpl<$Res> - implements _$VotingDelegationConfirmationCopyWith<$Res> { - __$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); +class __$VotingBallotIntentCopyWithImpl<$Res> + implements _$VotingBallotIntentCopyWith<$Res> { + __$VotingBallotIntentCopyWithImpl(this._self, this._then); - final _VotingDelegationConfirmation _self; - final $Res Function(_VotingDelegationConfirmation) _then; + final _VotingBallotIntent _self; + final $Res Function(_VotingBallotIntent) _then; - /// Create a copy of VotingDelegationConfirmation + /// Create a copy of VotingBallotIntent /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? txHash = null, - Object? vanLeafPosition = null, + Object? proposalId = null, + Object? skipped = null, + Object? choice = freezed, }) { - return _then(_VotingDelegationConfirmation( - txHash: null == txHash - ? _self.txHash - : txHash // ignore: cast_nullable_to_non_nullable - as String, - vanLeafPosition: null == vanLeafPosition - ? _self.vanLeafPosition - : vanLeafPosition // ignore: cast_nullable_to_non_nullable + return _then(_VotingBallotIntent( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable as int, + skipped: null == skipped + ? _self.skipped + : skipped // ignore: cast_nullable_to_non_nullable + as bool, + choice: freezed == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int?, )); } } /// @nodoc -mixin _$VotingDelegationSetup { - Uint8List get pcztBytes; - Uint8List get pcztSighash; - Uint8List get rk; - int get actionIndex; - Uint8List get actionBytes; - Uint8List get tx1Effects; +mixin _$VotingChainResponse { + int get statusCode; + String get body; - /// Create a copy of VotingDelegationSetup + /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingDelegationSetupCopyWith get copyWith => - _$VotingDelegationSetupCopyWithImpl( - this as VotingDelegationSetup, _$identity); + $VotingChainResponseCopyWith get copyWith => + _$VotingChainResponseCopyWithImpl( + this as VotingChainResponse, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingDelegationSetup && - const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && - const DeepCollectionEquality() - .equals(other.pcztSighash, pcztSighash) && - const DeepCollectionEquality().equals(other.rk, rk) && - (identical(other.actionIndex, actionIndex) || - other.actionIndex == actionIndex) && - const DeepCollectionEquality() - .equals(other.actionBytes, actionBytes) && - const DeepCollectionEquality() - .equals(other.tx1Effects, tx1Effects)); + other is VotingChainResponse && + (identical(other.statusCode, statusCode) || + other.statusCode == statusCode) && + (identical(other.body, body) || other.body == body)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(pcztBytes), - const DeepCollectionEquality().hash(pcztSighash), - const DeepCollectionEquality().hash(rk), - actionIndex, - const DeepCollectionEquality().hash(actionBytes), - const DeepCollectionEquality().hash(tx1Effects)); + int get hashCode => Object.hash(runtimeType, statusCode, body); @override String toString() { - return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + return 'VotingChainResponse(statusCode: $statusCode, body: $body)'; } } /// @nodoc -abstract mixin class $VotingDelegationSetupCopyWith<$Res> { - factory $VotingDelegationSetupCopyWith(VotingDelegationSetup value, - $Res Function(VotingDelegationSetup) _then) = - _$VotingDelegationSetupCopyWithImpl; +abstract mixin class $VotingChainResponseCopyWith<$Res> { + factory $VotingChainResponseCopyWith( + VotingChainResponse value, $Res Function(VotingChainResponse) _then) = + _$VotingChainResponseCopyWithImpl; @useResult - $Res call( - {Uint8List pcztBytes, - Uint8List pcztSighash, - Uint8List rk, - int actionIndex, - Uint8List actionBytes, - Uint8List tx1Effects}); + $Res call({int statusCode, String body}); } /// @nodoc -class _$VotingDelegationSetupCopyWithImpl<$Res> - implements $VotingDelegationSetupCopyWith<$Res> { - _$VotingDelegationSetupCopyWithImpl(this._self, this._then); +class _$VotingChainResponseCopyWithImpl<$Res> + implements $VotingChainResponseCopyWith<$Res> { + _$VotingChainResponseCopyWithImpl(this._self, this._then); - final VotingDelegationSetup _self; - final $Res Function(VotingDelegationSetup) _then; + final VotingChainResponse _self; + final $Res Function(VotingChainResponse) _then; - /// Create a copy of VotingDelegationSetup + /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? pcztBytes = null, - Object? pcztSighash = null, - Object? rk = null, - Object? actionIndex = null, - Object? actionBytes = null, - Object? tx1Effects = null, + Object? statusCode = null, + Object? body = null, }) { return _then(_self.copyWith( - pcztBytes: null == pcztBytes - ? _self.pcztBytes - : pcztBytes // ignore: cast_nullable_to_non_nullable - as Uint8List, - pcztSighash: null == pcztSighash - ? _self.pcztSighash - : pcztSighash // ignore: cast_nullable_to_non_nullable - as Uint8List, - rk: null == rk - ? _self.rk - : rk // ignore: cast_nullable_to_non_nullable - as Uint8List, - actionIndex: null == actionIndex - ? _self.actionIndex - : actionIndex // ignore: cast_nullable_to_non_nullable + statusCode: null == statusCode + ? _self.statusCode + : statusCode // ignore: cast_nullable_to_non_nullable as int, - actionBytes: null == actionBytes - ? _self.actionBytes - : actionBytes // ignore: cast_nullable_to_non_nullable - as Uint8List, - tx1Effects: null == tx1Effects - ? _self.tx1Effects - : tx1Effects // ignore: cast_nullable_to_non_nullable - as Uint8List, + body: null == body + ? _self.body + : body // ignore: cast_nullable_to_non_nullable + as String, )); } } -/// Adds pattern-matching-related methods to [VotingDelegationSetup]. -extension VotingDelegationSetupPatterns on VotingDelegationSetup { +/// Adds pattern-matching-related methods to [VotingChainResponse]. +extension VotingChainResponsePatterns on VotingChainResponse { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -447,12 +414,12 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingDelegationSetup value)? $default, { + TResult Function(_VotingChainResponse value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationSetup() when $default != null: + case _VotingChainResponse() when $default != null: return $default(_that); case _: return orElse(); @@ -474,11 +441,11 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult map( - TResult Function(_VotingDelegationSetup value) $default, + TResult Function(_VotingChainResponse value) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSetup(): + case _VotingChainResponse(): return $default(_that); } } @@ -497,11 +464,11 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingDelegationSetup value)? $default, + TResult? Function(_VotingChainResponse value)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSetup() when $default != null: + case _VotingChainResponse() when $default != null: return $default(_that); case _: return null; @@ -522,16 +489,13 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult maybeWhen( - TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, - int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? - $default, { + TResult Function(int statusCode, String body)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationSetup() when $default != null: - return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, - _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _VotingChainResponse() when $default != null: + return $default(_that.statusCode, _that.body); case _: return orElse(); } @@ -552,15 +516,12 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult when( - TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, - int actionIndex, Uint8List actionBytes, Uint8List tx1Effects) - $default, + TResult Function(int statusCode, String body) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSetup(): - return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, - _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _VotingChainResponse(): + return $default(_that.statusCode, _that.body); } } @@ -578,15 +539,12 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, - int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? - $default, + TResult? Function(int statusCode, String body)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSetup() when $default != null: - return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, - _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _VotingChainResponse() when $default != null: + return $default(_that.statusCode, _that.body); case _: return null; } @@ -595,298 +553,154 @@ extension VotingDelegationSetupPatterns on VotingDelegationSetup { /// @nodoc -class _VotingDelegationSetup implements VotingDelegationSetup { - const _VotingDelegationSetup( - {required this.pcztBytes, - required this.pcztSighash, - required this.rk, - required this.actionIndex, - required this.actionBytes, - required this.tx1Effects}); +class _VotingChainResponse implements VotingChainResponse { + const _VotingChainResponse({required this.statusCode, required this.body}); @override - final Uint8List pcztBytes; - @override - final Uint8List pcztSighash; - @override - final Uint8List rk; - @override - final int actionIndex; - @override - final Uint8List actionBytes; + final int statusCode; @override - final Uint8List tx1Effects; + final String body; - /// Create a copy of VotingDelegationSetup + /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingDelegationSetupCopyWith<_VotingDelegationSetup> get copyWith => - __$VotingDelegationSetupCopyWithImpl<_VotingDelegationSetup>( + _$VotingChainResponseCopyWith<_VotingChainResponse> get copyWith => + __$VotingChainResponseCopyWithImpl<_VotingChainResponse>( this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingDelegationSetup && - const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && - const DeepCollectionEquality() - .equals(other.pcztSighash, pcztSighash) && - const DeepCollectionEquality().equals(other.rk, rk) && - (identical(other.actionIndex, actionIndex) || - other.actionIndex == actionIndex) && - const DeepCollectionEquality() - .equals(other.actionBytes, actionBytes) && - const DeepCollectionEquality() - .equals(other.tx1Effects, tx1Effects)); + other is _VotingChainResponse && + (identical(other.statusCode, statusCode) || + other.statusCode == statusCode) && + (identical(other.body, body) || other.body == body)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(pcztBytes), - const DeepCollectionEquality().hash(pcztSighash), - const DeepCollectionEquality().hash(rk), - actionIndex, - const DeepCollectionEquality().hash(actionBytes), - const DeepCollectionEquality().hash(tx1Effects)); + int get hashCode => Object.hash(runtimeType, statusCode, body); @override String toString() { - return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + return 'VotingChainResponse(statusCode: $statusCode, body: $body)'; } } /// @nodoc -abstract mixin class _$VotingDelegationSetupCopyWith<$Res> - implements $VotingDelegationSetupCopyWith<$Res> { - factory _$VotingDelegationSetupCopyWith(_VotingDelegationSetup value, - $Res Function(_VotingDelegationSetup) _then) = - __$VotingDelegationSetupCopyWithImpl; +abstract mixin class _$VotingChainResponseCopyWith<$Res> + implements $VotingChainResponseCopyWith<$Res> { + factory _$VotingChainResponseCopyWith(_VotingChainResponse value, + $Res Function(_VotingChainResponse) _then) = + __$VotingChainResponseCopyWithImpl; @override @useResult - $Res call( - {Uint8List pcztBytes, - Uint8List pcztSighash, - Uint8List rk, - int actionIndex, - Uint8List actionBytes, - Uint8List tx1Effects}); + $Res call({int statusCode, String body}); } /// @nodoc -class __$VotingDelegationSetupCopyWithImpl<$Res> - implements _$VotingDelegationSetupCopyWith<$Res> { - __$VotingDelegationSetupCopyWithImpl(this._self, this._then); +class __$VotingChainResponseCopyWithImpl<$Res> + implements _$VotingChainResponseCopyWith<$Res> { + __$VotingChainResponseCopyWithImpl(this._self, this._then); - final _VotingDelegationSetup _self; - final $Res Function(_VotingDelegationSetup) _then; + final _VotingChainResponse _self; + final $Res Function(_VotingChainResponse) _then; - /// Create a copy of VotingDelegationSetup + /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? pcztBytes = null, - Object? pcztSighash = null, - Object? rk = null, - Object? actionIndex = null, - Object? actionBytes = null, - Object? tx1Effects = null, + Object? statusCode = null, + Object? body = null, }) { - return _then(_VotingDelegationSetup( - pcztBytes: null == pcztBytes - ? _self.pcztBytes - : pcztBytes // ignore: cast_nullable_to_non_nullable - as Uint8List, - pcztSighash: null == pcztSighash - ? _self.pcztSighash - : pcztSighash // ignore: cast_nullable_to_non_nullable - as Uint8List, - rk: null == rk - ? _self.rk - : rk // ignore: cast_nullable_to_non_nullable - as Uint8List, - actionIndex: null == actionIndex - ? _self.actionIndex - : actionIndex // ignore: cast_nullable_to_non_nullable + return _then(_VotingChainResponse( + statusCode: null == statusCode + ? _self.statusCode + : statusCode // ignore: cast_nullable_to_non_nullable as int, - actionBytes: null == actionBytes - ? _self.actionBytes - : actionBytes // ignore: cast_nullable_to_non_nullable - as Uint8List, - tx1Effects: null == tx1Effects - ? _self.tx1Effects - : tx1Effects // ignore: cast_nullable_to_non_nullable - as Uint8List, + body: null == body + ? _self.body + : body // ignore: cast_nullable_to_non_nullable + as String, )); } } /// @nodoc -mixin _$VotingDelegationSubmission { - Uint8List get proof; - Uint8List get rk; - Uint8List get nfSigned; - Uint8List get cmxNew; - Uint8List get govComm; - List get govNullifiers; - Uint8List get alpha; - String get voteRoundId; - Uint8List get spendAuthSig; - Uint8List get sighash; - Uint8List get tx1Effects; +mixin _$VotingCompletedVoteChoice { + int get proposalId; + int? get choice; - /// Create a copy of VotingDelegationSubmission + /// Create a copy of VotingCompletedVoteChoice /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingDelegationSubmissionCopyWith - get copyWith => - _$VotingDelegationSubmissionCopyWithImpl( - this as VotingDelegationSubmission, _$identity); + $VotingCompletedVoteChoiceCopyWith get copyWith => + _$VotingCompletedVoteChoiceCopyWithImpl( + this as VotingCompletedVoteChoice, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingDelegationSubmission && - const DeepCollectionEquality().equals(other.proof, proof) && - const DeepCollectionEquality().equals(other.rk, rk) && - const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && - const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && - const DeepCollectionEquality().equals(other.govComm, govComm) && - const DeepCollectionEquality() - .equals(other.govNullifiers, govNullifiers) && - const DeepCollectionEquality().equals(other.alpha, alpha) && - (identical(other.voteRoundId, voteRoundId) || - other.voteRoundId == voteRoundId) && - const DeepCollectionEquality() - .equals(other.spendAuthSig, spendAuthSig) && - const DeepCollectionEquality().equals(other.sighash, sighash) && - const DeepCollectionEquality() - .equals(other.tx1Effects, tx1Effects)); + other is VotingCompletedVoteChoice && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(proof), - const DeepCollectionEquality().hash(rk), - const DeepCollectionEquality().hash(nfSigned), - const DeepCollectionEquality().hash(cmxNew), - const DeepCollectionEquality().hash(govComm), - const DeepCollectionEquality().hash(govNullifiers), - const DeepCollectionEquality().hash(alpha), - voteRoundId, - const DeepCollectionEquality().hash(spendAuthSig), - const DeepCollectionEquality().hash(sighash), - const DeepCollectionEquality().hash(tx1Effects)); + int get hashCode => Object.hash(runtimeType, proposalId, choice); @override String toString() { - return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + return 'VotingCompletedVoteChoice(proposalId: $proposalId, choice: $choice)'; } } /// @nodoc -abstract mixin class $VotingDelegationSubmissionCopyWith<$Res> { - factory $VotingDelegationSubmissionCopyWith(VotingDelegationSubmission value, - $Res Function(VotingDelegationSubmission) _then) = - _$VotingDelegationSubmissionCopyWithImpl; +abstract mixin class $VotingCompletedVoteChoiceCopyWith<$Res> { + factory $VotingCompletedVoteChoiceCopyWith(VotingCompletedVoteChoice value, + $Res Function(VotingCompletedVoteChoice) _then) = + _$VotingCompletedVoteChoiceCopyWithImpl; @useResult - $Res call( - {Uint8List proof, - Uint8List rk, - Uint8List nfSigned, - Uint8List cmxNew, - Uint8List govComm, - List govNullifiers, - Uint8List alpha, - String voteRoundId, - Uint8List spendAuthSig, - Uint8List sighash, - Uint8List tx1Effects}); + $Res call({int proposalId, int? choice}); } /// @nodoc -class _$VotingDelegationSubmissionCopyWithImpl<$Res> - implements $VotingDelegationSubmissionCopyWith<$Res> { - _$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); +class _$VotingCompletedVoteChoiceCopyWithImpl<$Res> + implements $VotingCompletedVoteChoiceCopyWith<$Res> { + _$VotingCompletedVoteChoiceCopyWithImpl(this._self, this._then); - final VotingDelegationSubmission _self; - final $Res Function(VotingDelegationSubmission) _then; + final VotingCompletedVoteChoice _self; + final $Res Function(VotingCompletedVoteChoice) _then; - /// Create a copy of VotingDelegationSubmission + /// Create a copy of VotingCompletedVoteChoice /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? proof = null, - Object? rk = null, - Object? nfSigned = null, - Object? cmxNew = null, - Object? govComm = null, - Object? govNullifiers = null, - Object? alpha = null, - Object? voteRoundId = null, - Object? spendAuthSig = null, - Object? sighash = null, - Object? tx1Effects = null, + Object? proposalId = null, + Object? choice = freezed, }) { return _then(_self.copyWith( - proof: null == proof - ? _self.proof - : proof // ignore: cast_nullable_to_non_nullable - as Uint8List, - rk: null == rk - ? _self.rk - : rk // ignore: cast_nullable_to_non_nullable - as Uint8List, - nfSigned: null == nfSigned - ? _self.nfSigned - : nfSigned // ignore: cast_nullable_to_non_nullable - as Uint8List, - cmxNew: null == cmxNew - ? _self.cmxNew - : cmxNew // ignore: cast_nullable_to_non_nullable - as Uint8List, - govComm: null == govComm - ? _self.govComm - : govComm // ignore: cast_nullable_to_non_nullable - as Uint8List, - govNullifiers: null == govNullifiers - ? _self.govNullifiers - : govNullifiers // ignore: cast_nullable_to_non_nullable - as List, - alpha: null == alpha - ? _self.alpha - : alpha // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteRoundId: null == voteRoundId - ? _self.voteRoundId - : voteRoundId // ignore: cast_nullable_to_non_nullable - as String, - spendAuthSig: null == spendAuthSig - ? _self.spendAuthSig - : spendAuthSig // ignore: cast_nullable_to_non_nullable - as Uint8List, - sighash: null == sighash - ? _self.sighash - : sighash // ignore: cast_nullable_to_non_nullable - as Uint8List, - tx1Effects: null == tx1Effects - ? _self.tx1Effects - : tx1Effects // ignore: cast_nullable_to_non_nullable - as Uint8List, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: freezed == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int?, )); } } -/// Adds pattern-matching-related methods to [VotingDelegationSubmission]. -extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { +/// Adds pattern-matching-related methods to [VotingCompletedVoteChoice]. +extension VotingCompletedVoteChoicePatterns on VotingCompletedVoteChoice { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -901,12 +715,12 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingDelegationSubmission value)? $default, { + TResult Function(_VotingCompletedVoteChoice value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationSubmission() when $default != null: + case _VotingCompletedVoteChoice() when $default != null: return $default(_that); case _: return orElse(); @@ -928,11 +742,11 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult map( - TResult Function(_VotingDelegationSubmission value) $default, + TResult Function(_VotingCompletedVoteChoice value) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSubmission(): + case _VotingCompletedVoteChoice(): return $default(_that); } } @@ -951,11 +765,11 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingDelegationSubmission value)? $default, + TResult? Function(_VotingCompletedVoteChoice value)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSubmission() when $default != null: + case _VotingCompletedVoteChoice() when $default != null: return $default(_that); case _: return null; @@ -976,36 +790,13 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult maybeWhen( - TResult Function( - Uint8List proof, - Uint8List rk, - Uint8List nfSigned, - Uint8List cmxNew, - Uint8List govComm, - List govNullifiers, - Uint8List alpha, - String voteRoundId, - Uint8List spendAuthSig, - Uint8List sighash, - Uint8List tx1Effects)? - $default, { + TResult Function(int proposalId, int? choice)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingDelegationSubmission() when $default != null: - return $default( - _that.proof, - _that.rk, - _that.nfSigned, - _that.cmxNew, - _that.govComm, - _that.govNullifiers, - _that.alpha, - _that.voteRoundId, - _that.spendAuthSig, - _that.sighash, - _that.tx1Effects); + case _VotingCompletedVoteChoice() when $default != null: + return $default(_that.proposalId, _that.choice); case _: return orElse(); } @@ -1026,35 +817,12 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult when( - TResult Function( - Uint8List proof, - Uint8List rk, - Uint8List nfSigned, - Uint8List cmxNew, - Uint8List govComm, - List govNullifiers, - Uint8List alpha, - String voteRoundId, - Uint8List spendAuthSig, - Uint8List sighash, - Uint8List tx1Effects) - $default, + TResult Function(int proposalId, int? choice) $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSubmission(): - return $default( - _that.proof, - _that.rk, - _that.nfSigned, - _that.cmxNew, - _that.govComm, - _that.govNullifiers, - _that.alpha, - _that.voteRoundId, - _that.spendAuthSig, - _that.sighash, - _that.tx1Effects); + case _VotingCompletedVoteChoice(): + return $default(_that.proposalId, _that.choice); } } @@ -1072,35 +840,12 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Uint8List proof, - Uint8List rk, - Uint8List nfSigned, - Uint8List cmxNew, - Uint8List govComm, - List govNullifiers, - Uint8List alpha, - String voteRoundId, - Uint8List spendAuthSig, - Uint8List sighash, - Uint8List tx1Effects)? - $default, + TResult? Function(int proposalId, int? choice)? $default, ) { final _that = this; switch (_that) { - case _VotingDelegationSubmission() when $default != null: - return $default( - _that.proof, - _that.rk, - _that.nfSigned, - _that.cmxNew, - _that.govComm, - _that.govNullifiers, - _that.alpha, - _that.voteRoundId, - _that.spendAuthSig, - _that.sighash, - _that.tx1Effects); + case _VotingCompletedVoteChoice() when $default != null: + return $default(_that.proposalId, _that.choice); case _: return null; } @@ -1109,282 +854,156 @@ extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { /// @nodoc -class _VotingDelegationSubmission implements VotingDelegationSubmission { - const _VotingDelegationSubmission( - {required this.proof, - required this.rk, - required this.nfSigned, - required this.cmxNew, - required this.govComm, - required final List govNullifiers, - required this.alpha, - required this.voteRoundId, - required this.spendAuthSig, - required this.sighash, - required this.tx1Effects}) - : _govNullifiers = govNullifiers; - - @override - final Uint8List proof; - @override - final Uint8List rk; - @override - final Uint8List nfSigned; - @override - final Uint8List cmxNew; - @override - final Uint8List govComm; - final List _govNullifiers; - @override - List get govNullifiers { - if (_govNullifiers is EqualUnmodifiableListView) return _govNullifiers; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_govNullifiers); - } +class _VotingCompletedVoteChoice implements VotingCompletedVoteChoice { + const _VotingCompletedVoteChoice({required this.proposalId, this.choice}); @override - final Uint8List alpha; - @override - final String voteRoundId; - @override - final Uint8List spendAuthSig; - @override - final Uint8List sighash; + final int proposalId; @override - final Uint8List tx1Effects; + final int? choice; - /// Create a copy of VotingDelegationSubmission + /// Create a copy of VotingCompletedVoteChoice /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingDelegationSubmissionCopyWith<_VotingDelegationSubmission> - get copyWith => __$VotingDelegationSubmissionCopyWithImpl< - _VotingDelegationSubmission>(this, _$identity); + _$VotingCompletedVoteChoiceCopyWith<_VotingCompletedVoteChoice> + get copyWith => + __$VotingCompletedVoteChoiceCopyWithImpl<_VotingCompletedVoteChoice>( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingDelegationSubmission && - const DeepCollectionEquality().equals(other.proof, proof) && - const DeepCollectionEquality().equals(other.rk, rk) && - const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && - const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && - const DeepCollectionEquality().equals(other.govComm, govComm) && - const DeepCollectionEquality() - .equals(other._govNullifiers, _govNullifiers) && - const DeepCollectionEquality().equals(other.alpha, alpha) && - (identical(other.voteRoundId, voteRoundId) || - other.voteRoundId == voteRoundId) && - const DeepCollectionEquality() - .equals(other.spendAuthSig, spendAuthSig) && - const DeepCollectionEquality().equals(other.sighash, sighash) && - const DeepCollectionEquality() - .equals(other.tx1Effects, tx1Effects)); + other is _VotingCompletedVoteChoice && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(proof), - const DeepCollectionEquality().hash(rk), - const DeepCollectionEquality().hash(nfSigned), - const DeepCollectionEquality().hash(cmxNew), - const DeepCollectionEquality().hash(govComm), - const DeepCollectionEquality().hash(_govNullifiers), - const DeepCollectionEquality().hash(alpha), - voteRoundId, - const DeepCollectionEquality().hash(spendAuthSig), - const DeepCollectionEquality().hash(sighash), - const DeepCollectionEquality().hash(tx1Effects)); + int get hashCode => Object.hash(runtimeType, proposalId, choice); @override String toString() { - return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + return 'VotingCompletedVoteChoice(proposalId: $proposalId, choice: $choice)'; } } /// @nodoc -abstract mixin class _$VotingDelegationSubmissionCopyWith<$Res> - implements $VotingDelegationSubmissionCopyWith<$Res> { - factory _$VotingDelegationSubmissionCopyWith( - _VotingDelegationSubmission value, - $Res Function(_VotingDelegationSubmission) _then) = - __$VotingDelegationSubmissionCopyWithImpl; +abstract mixin class _$VotingCompletedVoteChoiceCopyWith<$Res> + implements $VotingCompletedVoteChoiceCopyWith<$Res> { + factory _$VotingCompletedVoteChoiceCopyWith(_VotingCompletedVoteChoice value, + $Res Function(_VotingCompletedVoteChoice) _then) = + __$VotingCompletedVoteChoiceCopyWithImpl; @override @useResult - $Res call( - {Uint8List proof, - Uint8List rk, - Uint8List nfSigned, - Uint8List cmxNew, - Uint8List govComm, - List govNullifiers, - Uint8List alpha, - String voteRoundId, - Uint8List spendAuthSig, - Uint8List sighash, - Uint8List tx1Effects}); + $Res call({int proposalId, int? choice}); } /// @nodoc -class __$VotingDelegationSubmissionCopyWithImpl<$Res> - implements _$VotingDelegationSubmissionCopyWith<$Res> { - __$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); +class __$VotingCompletedVoteChoiceCopyWithImpl<$Res> + implements _$VotingCompletedVoteChoiceCopyWith<$Res> { + __$VotingCompletedVoteChoiceCopyWithImpl(this._self, this._then); - final _VotingDelegationSubmission _self; - final $Res Function(_VotingDelegationSubmission) _then; + final _VotingCompletedVoteChoice _self; + final $Res Function(_VotingCompletedVoteChoice) _then; - /// Create a copy of VotingDelegationSubmission + /// Create a copy of VotingCompletedVoteChoice /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? proof = null, - Object? rk = null, - Object? nfSigned = null, - Object? cmxNew = null, - Object? govComm = null, - Object? govNullifiers = null, - Object? alpha = null, - Object? voteRoundId = null, - Object? spendAuthSig = null, - Object? sighash = null, - Object? tx1Effects = null, + Object? proposalId = null, + Object? choice = freezed, }) { - return _then(_VotingDelegationSubmission( - proof: null == proof - ? _self.proof - : proof // ignore: cast_nullable_to_non_nullable - as Uint8List, - rk: null == rk - ? _self.rk - : rk // ignore: cast_nullable_to_non_nullable - as Uint8List, - nfSigned: null == nfSigned - ? _self.nfSigned - : nfSigned // ignore: cast_nullable_to_non_nullable - as Uint8List, - cmxNew: null == cmxNew - ? _self.cmxNew - : cmxNew // ignore: cast_nullable_to_non_nullable - as Uint8List, - govComm: null == govComm - ? _self.govComm - : govComm // ignore: cast_nullable_to_non_nullable - as Uint8List, - govNullifiers: null == govNullifiers - ? _self._govNullifiers - : govNullifiers // ignore: cast_nullable_to_non_nullable - as List, - alpha: null == alpha - ? _self.alpha - : alpha // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteRoundId: null == voteRoundId - ? _self.voteRoundId - : voteRoundId // ignore: cast_nullable_to_non_nullable - as String, - spendAuthSig: null == spendAuthSig - ? _self.spendAuthSig - : spendAuthSig // ignore: cast_nullable_to_non_nullable - as Uint8List, - sighash: null == sighash - ? _self.sighash - : sighash // ignore: cast_nullable_to_non_nullable - as Uint8List, - tx1Effects: null == tx1Effects - ? _self.tx1Effects - : tx1Effects // ignore: cast_nullable_to_non_nullable - as Uint8List, + return _then(_VotingCompletedVoteChoice( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: freezed == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int?, )); } } /// @nodoc -mixin _$VotingEncryptedShare { - Uint8List get c1; - Uint8List get c2; - int get shareIndex; +mixin _$VotingCompletedVoteDisplay { + List get choices; + BigInt? get votedAt; - /// Create a copy of VotingEncryptedShare + /// Create a copy of VotingCompletedVoteDisplay /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingEncryptedShareCopyWith get copyWith => - _$VotingEncryptedShareCopyWithImpl( - this as VotingEncryptedShare, _$identity); + $VotingCompletedVoteDisplayCopyWith + get copyWith => + _$VotingCompletedVoteDisplayCopyWithImpl( + this as VotingCompletedVoteDisplay, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingEncryptedShare && - const DeepCollectionEquality().equals(other.c1, c1) && - const DeepCollectionEquality().equals(other.c2, c2) && - (identical(other.shareIndex, shareIndex) || - other.shareIndex == shareIndex)); + other is VotingCompletedVoteDisplay && + const DeepCollectionEquality().equals(other.choices, choices) && + (identical(other.votedAt, votedAt) || other.votedAt == votedAt)); } @override int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(c1), - const DeepCollectionEquality().hash(c2), - shareIndex); + runtimeType, const DeepCollectionEquality().hash(choices), votedAt); @override String toString() { - return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + return 'VotingCompletedVoteDisplay(choices: $choices, votedAt: $votedAt)'; } } /// @nodoc -abstract mixin class $VotingEncryptedShareCopyWith<$Res> { - factory $VotingEncryptedShareCopyWith(VotingEncryptedShare value, - $Res Function(VotingEncryptedShare) _then) = - _$VotingEncryptedShareCopyWithImpl; +abstract mixin class $VotingCompletedVoteDisplayCopyWith<$Res> { + factory $VotingCompletedVoteDisplayCopyWith(VotingCompletedVoteDisplay value, + $Res Function(VotingCompletedVoteDisplay) _then) = + _$VotingCompletedVoteDisplayCopyWithImpl; @useResult - $Res call({Uint8List c1, Uint8List c2, int shareIndex}); + $Res call({List choices, BigInt? votedAt}); } /// @nodoc -class _$VotingEncryptedShareCopyWithImpl<$Res> - implements $VotingEncryptedShareCopyWith<$Res> { - _$VotingEncryptedShareCopyWithImpl(this._self, this._then); +class _$VotingCompletedVoteDisplayCopyWithImpl<$Res> + implements $VotingCompletedVoteDisplayCopyWith<$Res> { + _$VotingCompletedVoteDisplayCopyWithImpl(this._self, this._then); - final VotingEncryptedShare _self; - final $Res Function(VotingEncryptedShare) _then; + final VotingCompletedVoteDisplay _self; + final $Res Function(VotingCompletedVoteDisplay) _then; - /// Create a copy of VotingEncryptedShare + /// Create a copy of VotingCompletedVoteDisplay /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? c1 = null, - Object? c2 = null, - Object? shareIndex = null, + Object? choices = null, + Object? votedAt = freezed, }) { return _then(_self.copyWith( - c1: null == c1 - ? _self.c1 - : c1 // ignore: cast_nullable_to_non_nullable - as Uint8List, - c2: null == c2 - ? _self.c2 - : c2 // ignore: cast_nullable_to_non_nullable - as Uint8List, - shareIndex: null == shareIndex - ? _self.shareIndex - : shareIndex // ignore: cast_nullable_to_non_nullable - as int, + choices: null == choices + ? _self.choices + : choices // ignore: cast_nullable_to_non_nullable + as List, + votedAt: freezed == votedAt + ? _self.votedAt + : votedAt // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } -/// Adds pattern-matching-related methods to [VotingEncryptedShare]. -extension VotingEncryptedSharePatterns on VotingEncryptedShare { +/// Adds pattern-matching-related methods to [VotingCompletedVoteDisplay]. +extension VotingCompletedVoteDisplayPatterns on VotingCompletedVoteDisplay { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -1399,12 +1018,12 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingEncryptedShare value)? $default, { + TResult Function(_VotingCompletedVoteDisplay value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingEncryptedShare() when $default != null: + case _VotingCompletedVoteDisplay() when $default != null: return $default(_that); case _: return orElse(); @@ -1426,11 +1045,11 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult map( - TResult Function(_VotingEncryptedShare value) $default, + TResult Function(_VotingCompletedVoteDisplay value) $default, ) { final _that = this; switch (_that) { - case _VotingEncryptedShare(): + case _VotingCompletedVoteDisplay(): return $default(_that); } } @@ -1449,11 +1068,11 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingEncryptedShare value)? $default, + TResult? Function(_VotingCompletedVoteDisplay value)? $default, ) { final _that = this; switch (_that) { - case _VotingEncryptedShare() when $default != null: + case _VotingCompletedVoteDisplay() when $default != null: return $default(_that); case _: return null; @@ -1474,13 +1093,14 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult maybeWhen( - TResult Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, { + TResult Function(List choices, BigInt? votedAt)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingEncryptedShare() when $default != null: - return $default(_that.c1, _that.c2, _that.shareIndex); + case _VotingCompletedVoteDisplay() when $default != null: + return $default(_that.choices, _that.votedAt); case _: return orElse(); } @@ -1501,12 +1121,13 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult when( - TResult Function(Uint8List c1, Uint8List c2, int shareIndex) $default, + TResult Function(List choices, BigInt? votedAt) + $default, ) { final _that = this; switch (_that) { - case _VotingEncryptedShare(): - return $default(_that.c1, _that.c2, _that.shareIndex); + case _VotingCompletedVoteDisplay(): + return $default(_that.choices, _that.votedAt); } } @@ -1524,12 +1145,13 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, + TResult? Function(List choices, BigInt? votedAt)? + $default, ) { final _that = this; switch (_that) { - case _VotingEncryptedShare() when $default != null: - return $default(_that.c1, _that.c2, _that.shareIndex); + case _VotingCompletedVoteDisplay() when $default != null: + return $default(_that.choices, _that.votedAt); case _: return null; } @@ -1538,184 +1160,242 @@ extension VotingEncryptedSharePatterns on VotingEncryptedShare { /// @nodoc -class _VotingEncryptedShare implements VotingEncryptedShare { - const _VotingEncryptedShare( - {required this.c1, required this.c2, required this.shareIndex}); +class _VotingCompletedVoteDisplay implements VotingCompletedVoteDisplay { + const _VotingCompletedVoteDisplay( + {required final List choices, this.votedAt}) + : _choices = choices; + final List _choices; @override - final Uint8List c1; - @override - final Uint8List c2; + List get choices { + if (_choices is EqualUnmodifiableListView) return _choices; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_choices); + } + @override - final int shareIndex; + final BigInt? votedAt; - /// Create a copy of VotingEncryptedShare + /// Create a copy of VotingCompletedVoteDisplay /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingEncryptedShareCopyWith<_VotingEncryptedShare> get copyWith => - __$VotingEncryptedShareCopyWithImpl<_VotingEncryptedShare>( - this, _$identity); + _$VotingCompletedVoteDisplayCopyWith<_VotingCompletedVoteDisplay> + get copyWith => __$VotingCompletedVoteDisplayCopyWithImpl< + _VotingCompletedVoteDisplay>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingEncryptedShare && - const DeepCollectionEquality().equals(other.c1, c1) && - const DeepCollectionEquality().equals(other.c2, c2) && - (identical(other.shareIndex, shareIndex) || - other.shareIndex == shareIndex)); + other is _VotingCompletedVoteDisplay && + const DeepCollectionEquality().equals(other._choices, _choices) && + (identical(other.votedAt, votedAt) || other.votedAt == votedAt)); } @override int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(c1), - const DeepCollectionEquality().hash(c2), - shareIndex); + runtimeType, const DeepCollectionEquality().hash(_choices), votedAt); @override String toString() { - return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + return 'VotingCompletedVoteDisplay(choices: $choices, votedAt: $votedAt)'; } } /// @nodoc -abstract mixin class _$VotingEncryptedShareCopyWith<$Res> - implements $VotingEncryptedShareCopyWith<$Res> { - factory _$VotingEncryptedShareCopyWith(_VotingEncryptedShare value, - $Res Function(_VotingEncryptedShare) _then) = - __$VotingEncryptedShareCopyWithImpl; +abstract mixin class _$VotingCompletedVoteDisplayCopyWith<$Res> + implements $VotingCompletedVoteDisplayCopyWith<$Res> { + factory _$VotingCompletedVoteDisplayCopyWith( + _VotingCompletedVoteDisplay value, + $Res Function(_VotingCompletedVoteDisplay) _then) = + __$VotingCompletedVoteDisplayCopyWithImpl; @override @useResult - $Res call({Uint8List c1, Uint8List c2, int shareIndex}); + $Res call({List choices, BigInt? votedAt}); } /// @nodoc -class __$VotingEncryptedShareCopyWithImpl<$Res> - implements _$VotingEncryptedShareCopyWith<$Res> { - __$VotingEncryptedShareCopyWithImpl(this._self, this._then); +class __$VotingCompletedVoteDisplayCopyWithImpl<$Res> + implements _$VotingCompletedVoteDisplayCopyWith<$Res> { + __$VotingCompletedVoteDisplayCopyWithImpl(this._self, this._then); - final _VotingEncryptedShare _self; - final $Res Function(_VotingEncryptedShare) _then; + final _VotingCompletedVoteDisplay _self; + final $Res Function(_VotingCompletedVoteDisplay) _then; - /// Create a copy of VotingEncryptedShare + /// Create a copy of VotingCompletedVoteDisplay /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? c1 = null, - Object? c2 = null, - Object? shareIndex = null, + Object? choices = null, + Object? votedAt = freezed, }) { - return _then(_VotingEncryptedShare( - c1: null == c1 - ? _self.c1 - : c1 // ignore: cast_nullable_to_non_nullable - as Uint8List, - c2: null == c2 - ? _self.c2 - : c2 // ignore: cast_nullable_to_non_nullable - as Uint8List, - shareIndex: null == shareIndex - ? _self.shareIndex - : shareIndex // ignore: cast_nullable_to_non_nullable - as int, + return _then(_VotingCompletedVoteDisplay( + choices: null == choices + ? _self._choices + : choices // ignore: cast_nullable_to_non_nullable + as List, + votedAt: freezed == votedAt + ? _self.votedAt + : votedAt // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } /// @nodoc -mixin _$VotingPirLayout { - int get pirDepth; - int get tier0Layers; - int get tier1Layers; - int get polyLen; - - /// Create a copy of VotingPirLayout +mixin _$VotingConfig { + String get source; + String get sourceFingerprint; + String get trustedKeyFingerprint; + String get switchKind; + List get voteServers; + List get pirServers; + VotingPirLayout? get pirLayout; + List get rounds; + + /// Create a copy of VotingConfig /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingPirLayoutCopyWith get copyWith => - _$VotingPirLayoutCopyWithImpl( - this as VotingPirLayout, _$identity); + $VotingConfigCopyWith get copyWith => + _$VotingConfigCopyWithImpl( + this as VotingConfig, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingPirLayout && - (identical(other.pirDepth, pirDepth) || - other.pirDepth == pirDepth) && - (identical(other.tier0Layers, tier0Layers) || - other.tier0Layers == tier0Layers) && - (identical(other.tier1Layers, tier1Layers) || - other.tier1Layers == tier1Layers) && - (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + other is VotingConfig && + (identical(other.source, source) || other.source == source) && + (identical(other.sourceFingerprint, sourceFingerprint) || + other.sourceFingerprint == sourceFingerprint) && + (identical(other.trustedKeyFingerprint, trustedKeyFingerprint) || + other.trustedKeyFingerprint == trustedKeyFingerprint) && + (identical(other.switchKind, switchKind) || + other.switchKind == switchKind) && + const DeepCollectionEquality() + .equals(other.voteServers, voteServers) && + const DeepCollectionEquality() + .equals(other.pirServers, pirServers) && + (identical(other.pirLayout, pirLayout) || + other.pirLayout == pirLayout) && + const DeepCollectionEquality().equals(other.rounds, rounds)); } @override - int get hashCode => - Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + int get hashCode => Object.hash( + runtimeType, + source, + sourceFingerprint, + trustedKeyFingerprint, + switchKind, + const DeepCollectionEquality().hash(voteServers), + const DeepCollectionEquality().hash(pirServers), + pirLayout, + const DeepCollectionEquality().hash(rounds)); @override String toString() { - return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + return 'VotingConfig(source: $source, sourceFingerprint: $sourceFingerprint, trustedKeyFingerprint: $trustedKeyFingerprint, switchKind: $switchKind, voteServers: $voteServers, pirServers: $pirServers, pirLayout: $pirLayout, rounds: $rounds)'; } } /// @nodoc -abstract mixin class $VotingPirLayoutCopyWith<$Res> { - factory $VotingPirLayoutCopyWith( - VotingPirLayout value, $Res Function(VotingPirLayout) _then) = - _$VotingPirLayoutCopyWithImpl; +abstract mixin class $VotingConfigCopyWith<$Res> { + factory $VotingConfigCopyWith( + VotingConfig value, $Res Function(VotingConfig) _then) = + _$VotingConfigCopyWithImpl; @useResult - $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); + $Res call( + {String source, + String sourceFingerprint, + String trustedKeyFingerprint, + String switchKind, + List voteServers, + List pirServers, + VotingPirLayout? pirLayout, + List rounds}); + + $VotingPirLayoutCopyWith<$Res>? get pirLayout; } /// @nodoc -class _$VotingPirLayoutCopyWithImpl<$Res> - implements $VotingPirLayoutCopyWith<$Res> { - _$VotingPirLayoutCopyWithImpl(this._self, this._then); +class _$VotingConfigCopyWithImpl<$Res> implements $VotingConfigCopyWith<$Res> { + _$VotingConfigCopyWithImpl(this._self, this._then); - final VotingPirLayout _self; - final $Res Function(VotingPirLayout) _then; + final VotingConfig _self; + final $Res Function(VotingConfig) _then; - /// Create a copy of VotingPirLayout + /// Create a copy of VotingConfig /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? pirDepth = null, - Object? tier0Layers = null, - Object? tier1Layers = null, - Object? polyLen = null, + Object? source = null, + Object? sourceFingerprint = null, + Object? trustedKeyFingerprint = null, + Object? switchKind = null, + Object? voteServers = null, + Object? pirServers = null, + Object? pirLayout = freezed, + Object? rounds = null, }) { return _then(_self.copyWith( - pirDepth: null == pirDepth - ? _self.pirDepth - : pirDepth // ignore: cast_nullable_to_non_nullable - as int, - tier0Layers: null == tier0Layers - ? _self.tier0Layers - : tier0Layers // ignore: cast_nullable_to_non_nullable - as int, - tier1Layers: null == tier1Layers - ? _self.tier1Layers - : tier1Layers // ignore: cast_nullable_to_non_nullable - as int, - polyLen: null == polyLen - ? _self.polyLen - : polyLen // ignore: cast_nullable_to_non_nullable - as int, + source: null == source + ? _self.source + : source // ignore: cast_nullable_to_non_nullable + as String, + sourceFingerprint: null == sourceFingerprint + ? _self.sourceFingerprint + : sourceFingerprint // ignore: cast_nullable_to_non_nullable + as String, + trustedKeyFingerprint: null == trustedKeyFingerprint + ? _self.trustedKeyFingerprint + : trustedKeyFingerprint // ignore: cast_nullable_to_non_nullable + as String, + switchKind: null == switchKind + ? _self.switchKind + : switchKind // ignore: cast_nullable_to_non_nullable + as String, + voteServers: null == voteServers + ? _self.voteServers + : voteServers // ignore: cast_nullable_to_non_nullable + as List, + pirServers: null == pirServers + ? _self.pirServers + : pirServers // ignore: cast_nullable_to_non_nullable + as List, + pirLayout: freezed == pirLayout + ? _self.pirLayout + : pirLayout // ignore: cast_nullable_to_non_nullable + as VotingPirLayout?, + rounds: null == rounds + ? _self.rounds + : rounds // ignore: cast_nullable_to_non_nullable + as List, )); } + + /// Create a copy of VotingConfig + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingPirLayoutCopyWith<$Res>? get pirLayout { + if (_self.pirLayout == null) { + return null; + } + + return $VotingPirLayoutCopyWith<$Res>(_self.pirLayout!, (value) { + return _then(_self.copyWith(pirLayout: value)); + }); + } } -/// Adds pattern-matching-related methods to [VotingPirLayout]. -extension VotingPirLayoutPatterns on VotingPirLayout { +/// Adds pattern-matching-related methods to [VotingConfig]. +extension VotingConfigPatterns on VotingConfig { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -1730,12 +1410,12 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingPirLayout value)? $default, { + TResult Function(_VotingConfig value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingPirLayout() when $default != null: + case _VotingConfig() when $default != null: return $default(_that); case _: return orElse(); @@ -1757,11 +1437,11 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult map( - TResult Function(_VotingPirLayout value) $default, + TResult Function(_VotingConfig value) $default, ) { final _that = this; switch (_that) { - case _VotingPirLayout(): + case _VotingConfig(): return $default(_that); } } @@ -1780,11 +1460,11 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingPirLayout value)? $default, + TResult? Function(_VotingConfig value)? $default, ) { final _that = this; switch (_that) { - case _VotingPirLayout() when $default != null: + case _VotingConfig() when $default != null: return $default(_that); case _: return null; @@ -1806,15 +1486,29 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult maybeWhen( TResult Function( - int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + String source, + String sourceFingerprint, + String trustedKeyFingerprint, + String switchKind, + List voteServers, + List pirServers, + VotingPirLayout? pirLayout, + List rounds)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingPirLayout() when $default != null: - return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, - _that.polyLen); + case _VotingConfig() when $default != null: + return $default( + _that.source, + _that.sourceFingerprint, + _that.trustedKeyFingerprint, + _that.switchKind, + _that.voteServers, + _that.pirServers, + _that.pirLayout, + _that.rounds); case _: return orElse(); } @@ -1836,14 +1530,28 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult when( TResult Function( - int pirDepth, int tier0Layers, int tier1Layers, int polyLen) + String source, + String sourceFingerprint, + String trustedKeyFingerprint, + String switchKind, + List voteServers, + List pirServers, + VotingPirLayout? pirLayout, + List rounds) $default, ) { final _that = this; switch (_that) { - case _VotingPirLayout(): - return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, - _that.polyLen); + case _VotingConfig(): + return $default( + _that.source, + _that.sourceFingerprint, + _that.trustedKeyFingerprint, + _that.switchKind, + _that.voteServers, + _that.pirServers, + _that.pirLayout, + _that.rounds); } } @@ -1862,14 +1570,28 @@ extension VotingPirLayoutPatterns on VotingPirLayout { @optionalTypeArgs TResult? whenOrNull( TResult? Function( - int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + String source, + String sourceFingerprint, + String trustedKeyFingerprint, + String switchKind, + List voteServers, + List pirServers, + VotingPirLayout? pirLayout, + List rounds)? $default, ) { final _that = this; switch (_that) { - case _VotingPirLayout() when $default != null: - return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, - _that.polyLen); + case _VotingConfig() when $default != null: + return $default( + _that.source, + _that.sourceFingerprint, + _that.trustedKeyFingerprint, + _that.switchKind, + _that.voteServers, + _that.pirServers, + _that.pirLayout, + _that.rounds); case _: return null; } @@ -1878,206 +1600,268 @@ extension VotingPirLayoutPatterns on VotingPirLayout { /// @nodoc -class _VotingPirLayout implements VotingPirLayout { - const _VotingPirLayout( - {required this.pirDepth, - required this.tier0Layers, - required this.tier1Layers, - required this.polyLen}); +class _VotingConfig implements VotingConfig { + const _VotingConfig( + {required this.source, + required this.sourceFingerprint, + required this.trustedKeyFingerprint, + required this.switchKind, + required final List voteServers, + required final List pirServers, + this.pirLayout, + required final List rounds}) + : _voteServers = voteServers, + _pirServers = pirServers, + _rounds = rounds; @override - final int pirDepth; + final String source; @override - final int tier0Layers; + final String sourceFingerprint; @override - final int tier1Layers; + final String trustedKeyFingerprint; @override - final int polyLen; + final String switchKind; + final List _voteServers; + @override + List get voteServers { + if (_voteServers is EqualUnmodifiableListView) return _voteServers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_voteServers); + } - /// Create a copy of VotingPirLayout + final List _pirServers; + @override + List get pirServers { + if (_pirServers is EqualUnmodifiableListView) return _pirServers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_pirServers); + } + + @override + final VotingPirLayout? pirLayout; + final List _rounds; + @override + List get rounds { + if (_rounds is EqualUnmodifiableListView) return _rounds; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_rounds); + } + + /// Create a copy of VotingConfig /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingPirLayoutCopyWith<_VotingPirLayout> get copyWith => - __$VotingPirLayoutCopyWithImpl<_VotingPirLayout>(this, _$identity); + _$VotingConfigCopyWith<_VotingConfig> get copyWith => + __$VotingConfigCopyWithImpl<_VotingConfig>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingPirLayout && - (identical(other.pirDepth, pirDepth) || - other.pirDepth == pirDepth) && - (identical(other.tier0Layers, tier0Layers) || - other.tier0Layers == tier0Layers) && - (identical(other.tier1Layers, tier1Layers) || - other.tier1Layers == tier1Layers) && - (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + other is _VotingConfig && + (identical(other.source, source) || other.source == source) && + (identical(other.sourceFingerprint, sourceFingerprint) || + other.sourceFingerprint == sourceFingerprint) && + (identical(other.trustedKeyFingerprint, trustedKeyFingerprint) || + other.trustedKeyFingerprint == trustedKeyFingerprint) && + (identical(other.switchKind, switchKind) || + other.switchKind == switchKind) && + const DeepCollectionEquality() + .equals(other._voteServers, _voteServers) && + const DeepCollectionEquality() + .equals(other._pirServers, _pirServers) && + (identical(other.pirLayout, pirLayout) || + other.pirLayout == pirLayout) && + const DeepCollectionEquality().equals(other._rounds, _rounds)); } @override - int get hashCode => - Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + int get hashCode => Object.hash( + runtimeType, + source, + sourceFingerprint, + trustedKeyFingerprint, + switchKind, + const DeepCollectionEquality().hash(_voteServers), + const DeepCollectionEquality().hash(_pirServers), + pirLayout, + const DeepCollectionEquality().hash(_rounds)); @override String toString() { - return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + return 'VotingConfig(source: $source, sourceFingerprint: $sourceFingerprint, trustedKeyFingerprint: $trustedKeyFingerprint, switchKind: $switchKind, voteServers: $voteServers, pirServers: $pirServers, pirLayout: $pirLayout, rounds: $rounds)'; } } /// @nodoc -abstract mixin class _$VotingPirLayoutCopyWith<$Res> - implements $VotingPirLayoutCopyWith<$Res> { - factory _$VotingPirLayoutCopyWith( - _VotingPirLayout value, $Res Function(_VotingPirLayout) _then) = - __$VotingPirLayoutCopyWithImpl; +abstract mixin class _$VotingConfigCopyWith<$Res> + implements $VotingConfigCopyWith<$Res> { + factory _$VotingConfigCopyWith( + _VotingConfig value, $Res Function(_VotingConfig) _then) = + __$VotingConfigCopyWithImpl; @override @useResult - $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); + $Res call( + {String source, + String sourceFingerprint, + String trustedKeyFingerprint, + String switchKind, + List voteServers, + List pirServers, + VotingPirLayout? pirLayout, + List rounds}); + + @override + $VotingPirLayoutCopyWith<$Res>? get pirLayout; } /// @nodoc -class __$VotingPirLayoutCopyWithImpl<$Res> - implements _$VotingPirLayoutCopyWith<$Res> { - __$VotingPirLayoutCopyWithImpl(this._self, this._then); +class __$VotingConfigCopyWithImpl<$Res> + implements _$VotingConfigCopyWith<$Res> { + __$VotingConfigCopyWithImpl(this._self, this._then); - final _VotingPirLayout _self; - final $Res Function(_VotingPirLayout) _then; + final _VotingConfig _self; + final $Res Function(_VotingConfig) _then; - /// Create a copy of VotingPirLayout + /// Create a copy of VotingConfig /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? pirDepth = null, - Object? tier0Layers = null, - Object? tier1Layers = null, - Object? polyLen = null, + Object? source = null, + Object? sourceFingerprint = null, + Object? trustedKeyFingerprint = null, + Object? switchKind = null, + Object? voteServers = null, + Object? pirServers = null, + Object? pirLayout = freezed, + Object? rounds = null, }) { - return _then(_VotingPirLayout( - pirDepth: null == pirDepth - ? _self.pirDepth - : pirDepth // ignore: cast_nullable_to_non_nullable - as int, - tier0Layers: null == tier0Layers - ? _self.tier0Layers - : tier0Layers // ignore: cast_nullable_to_non_nullable - as int, - tier1Layers: null == tier1Layers - ? _self.tier1Layers - : tier1Layers // ignore: cast_nullable_to_non_nullable - as int, - polyLen: null == polyLen - ? _self.polyLen - : polyLen // ignore: cast_nullable_to_non_nullable - as int, + return _then(_VotingConfig( + source: null == source + ? _self.source + : source // ignore: cast_nullable_to_non_nullable + as String, + sourceFingerprint: null == sourceFingerprint + ? _self.sourceFingerprint + : sourceFingerprint // ignore: cast_nullable_to_non_nullable + as String, + trustedKeyFingerprint: null == trustedKeyFingerprint + ? _self.trustedKeyFingerprint + : trustedKeyFingerprint // ignore: cast_nullable_to_non_nullable + as String, + switchKind: null == switchKind + ? _self.switchKind + : switchKind // ignore: cast_nullable_to_non_nullable + as String, + voteServers: null == voteServers + ? _self._voteServers + : voteServers // ignore: cast_nullable_to_non_nullable + as List, + pirServers: null == pirServers + ? _self._pirServers + : pirServers // ignore: cast_nullable_to_non_nullable + as List, + pirLayout: freezed == pirLayout + ? _self.pirLayout + : pirLayout // ignore: cast_nullable_to_non_nullable + as VotingPirLayout?, + rounds: null == rounds + ? _self._rounds + : rounds // ignore: cast_nullable_to_non_nullable + as List, )); } + + /// Create a copy of VotingConfig + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingPirLayoutCopyWith<$Res>? get pirLayout { + if (_self.pirLayout == null) { + return null; + } + + return $VotingPirLayoutCopyWith<$Res>(_self.pirLayout!, (value) { + return _then(_self.copyWith(pirLayout: value)); + }); + } } /// @nodoc -mixin _$VotingPreparedInfo { +mixin _$VotingConfigRound { String get roundId; - int get bundleIndex; - BigInt get eligibleWeightZatoshi; - BigInt get delegatedWeightZatoshi; - String get roundName; + Uint8List get eaPk; - /// Create a copy of VotingPreparedInfo + /// Create a copy of VotingConfigRound /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingPreparedInfoCopyWith get copyWith => - _$VotingPreparedInfoCopyWithImpl( - this as VotingPreparedInfo, _$identity); + $VotingConfigRoundCopyWith get copyWith => + _$VotingConfigRoundCopyWithImpl( + this as VotingConfigRound, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingPreparedInfo && + other is VotingConfigRound && (identical(other.roundId, roundId) || other.roundId == roundId) && - (identical(other.bundleIndex, bundleIndex) || - other.bundleIndex == bundleIndex) && - (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || - other.eligibleWeightZatoshi == eligibleWeightZatoshi) && - (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || - other.delegatedWeightZatoshi == delegatedWeightZatoshi) && - (identical(other.roundName, roundName) || - other.roundName == roundName)); + const DeepCollectionEquality().equals(other.eaPk, eaPk)); } @override - int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, - eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + int get hashCode => Object.hash( + runtimeType, roundId, const DeepCollectionEquality().hash(eaPk)); @override String toString() { - return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + return 'VotingConfigRound(roundId: $roundId, eaPk: $eaPk)'; } } /// @nodoc -abstract mixin class $VotingPreparedInfoCopyWith<$Res> { - factory $VotingPreparedInfoCopyWith( - VotingPreparedInfo value, $Res Function(VotingPreparedInfo) _then) = - _$VotingPreparedInfoCopyWithImpl; +abstract mixin class $VotingConfigRoundCopyWith<$Res> { + factory $VotingConfigRoundCopyWith( + VotingConfigRound value, $Res Function(VotingConfigRound) _then) = + _$VotingConfigRoundCopyWithImpl; @useResult - $Res call( - {String roundId, - int bundleIndex, - BigInt eligibleWeightZatoshi, - BigInt delegatedWeightZatoshi, - String roundName}); + $Res call({String roundId, Uint8List eaPk}); } /// @nodoc -class _$VotingPreparedInfoCopyWithImpl<$Res> - implements $VotingPreparedInfoCopyWith<$Res> { - _$VotingPreparedInfoCopyWithImpl(this._self, this._then); +class _$VotingConfigRoundCopyWithImpl<$Res> + implements $VotingConfigRoundCopyWith<$Res> { + _$VotingConfigRoundCopyWithImpl(this._self, this._then); - final VotingPreparedInfo _self; - final $Res Function(VotingPreparedInfo) _then; + final VotingConfigRound _self; + final $Res Function(VotingConfigRound) _then; - /// Create a copy of VotingPreparedInfo + /// Create a copy of VotingConfigRound /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? roundId = null, - Object? bundleIndex = null, - Object? eligibleWeightZatoshi = null, - Object? delegatedWeightZatoshi = null, - Object? roundName = null, + Object? eaPk = null, }) { return _then(_self.copyWith( roundId: null == roundId ? _self.roundId : roundId // ignore: cast_nullable_to_non_nullable as String, - bundleIndex: null == bundleIndex - ? _self.bundleIndex - : bundleIndex // ignore: cast_nullable_to_non_nullable - as int, - eligibleWeightZatoshi: null == eligibleWeightZatoshi - ? _self.eligibleWeightZatoshi - : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable - as BigInt, - delegatedWeightZatoshi: null == delegatedWeightZatoshi - ? _self.delegatedWeightZatoshi - : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable - as BigInt, - roundName: null == roundName - ? _self.roundName - : roundName // ignore: cast_nullable_to_non_nullable - as String, + eaPk: null == eaPk + ? _self.eaPk + : eaPk // ignore: cast_nullable_to_non_nullable + as Uint8List, )); } } -/// Adds pattern-matching-related methods to [VotingPreparedInfo]. -extension VotingPreparedInfoPatterns on VotingPreparedInfo { +/// Adds pattern-matching-related methods to [VotingConfigRound]. +extension VotingConfigRoundPatterns on VotingConfigRound { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -2092,12 +1876,12 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingPreparedInfo value)? $default, { + TResult Function(_VotingConfigRound value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingPreparedInfo() when $default != null: + case _VotingConfigRound() when $default != null: return $default(_that); case _: return orElse(); @@ -2119,11 +1903,11 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult map( - TResult Function(_VotingPreparedInfo value) $default, + TResult Function(_VotingConfigRound value) $default, ) { final _that = this; switch (_that) { - case _VotingPreparedInfo(): + case _VotingConfigRound(): return $default(_that); } } @@ -2142,11 +1926,11 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingPreparedInfo value)? $default, + TResult? Function(_VotingConfigRound value)? $default, ) { final _that = this; switch (_that) { - case _VotingPreparedInfo() when $default != null: + case _VotingConfigRound() when $default != null: return $default(_that); case _: return null; @@ -2167,24 +1951,13 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult maybeWhen( - TResult Function( - String roundId, - int bundleIndex, - BigInt eligibleWeightZatoshi, - BigInt delegatedWeightZatoshi, - String roundName)? - $default, { + TResult Function(String roundId, Uint8List eaPk)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingPreparedInfo() when $default != null: - return $default( - _that.roundId, - _that.bundleIndex, - _that.eligibleWeightZatoshi, - _that.delegatedWeightZatoshi, - _that.roundName); + case _VotingConfigRound() when $default != null: + return $default(_that.roundId, _that.eaPk); case _: return orElse(); } @@ -2205,23 +1978,12 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult when( - TResult Function( - String roundId, - int bundleIndex, - BigInt eligibleWeightZatoshi, - BigInt delegatedWeightZatoshi, - String roundName) - $default, + TResult Function(String roundId, Uint8List eaPk) $default, ) { final _that = this; switch (_that) { - case _VotingPreparedInfo(): - return $default( - _that.roundId, - _that.bundleIndex, - _that.eligibleWeightZatoshi, - _that.delegatedWeightZatoshi, - _that.roundName); + case _VotingConfigRound(): + return $default(_that.roundId, _that.eaPk); } } @@ -2239,23 +2001,12 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - String roundId, - int bundleIndex, - BigInt eligibleWeightZatoshi, - BigInt delegatedWeightZatoshi, - String roundName)? - $default, + TResult? Function(String roundId, Uint8List eaPk)? $default, ) { final _that = this; switch (_that) { - case _VotingPreparedInfo() when $default != null: - return $default( - _that.roundId, - _that.bundleIndex, - _that.eligibleWeightZatoshi, - _that.delegatedWeightZatoshi, - _that.roundName); + case _VotingConfigRound() when $default != null: + return $default(_that.roundId, _that.eaPk); case _: return null; } @@ -2264,269 +2015,166 @@ extension VotingPreparedInfoPatterns on VotingPreparedInfo { /// @nodoc -class _VotingPreparedInfo implements VotingPreparedInfo { - const _VotingPreparedInfo( - {required this.roundId, - required this.bundleIndex, - required this.eligibleWeightZatoshi, - required this.delegatedWeightZatoshi, - required this.roundName}); +class _VotingConfigRound implements VotingConfigRound { + const _VotingConfigRound({required this.roundId, required this.eaPk}); @override final String roundId; @override - final int bundleIndex; - @override - final BigInt eligibleWeightZatoshi; - @override - final BigInt delegatedWeightZatoshi; - @override - final String roundName; + final Uint8List eaPk; - /// Create a copy of VotingPreparedInfo + /// Create a copy of VotingConfigRound /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingPreparedInfoCopyWith<_VotingPreparedInfo> get copyWith => - __$VotingPreparedInfoCopyWithImpl<_VotingPreparedInfo>(this, _$identity); + _$VotingConfigRoundCopyWith<_VotingConfigRound> get copyWith => + __$VotingConfigRoundCopyWithImpl<_VotingConfigRound>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingPreparedInfo && + other is _VotingConfigRound && (identical(other.roundId, roundId) || other.roundId == roundId) && - (identical(other.bundleIndex, bundleIndex) || - other.bundleIndex == bundleIndex) && - (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || - other.eligibleWeightZatoshi == eligibleWeightZatoshi) && - (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || - other.delegatedWeightZatoshi == delegatedWeightZatoshi) && - (identical(other.roundName, roundName) || - other.roundName == roundName)); + const DeepCollectionEquality().equals(other.eaPk, eaPk)); } @override - int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, - eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + int get hashCode => Object.hash( + runtimeType, roundId, const DeepCollectionEquality().hash(eaPk)); @override String toString() { - return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + return 'VotingConfigRound(roundId: $roundId, eaPk: $eaPk)'; } } /// @nodoc -abstract mixin class _$VotingPreparedInfoCopyWith<$Res> - implements $VotingPreparedInfoCopyWith<$Res> { - factory _$VotingPreparedInfoCopyWith( - _VotingPreparedInfo value, $Res Function(_VotingPreparedInfo) _then) = - __$VotingPreparedInfoCopyWithImpl; +abstract mixin class _$VotingConfigRoundCopyWith<$Res> + implements $VotingConfigRoundCopyWith<$Res> { + factory _$VotingConfigRoundCopyWith( + _VotingConfigRound value, $Res Function(_VotingConfigRound) _then) = + __$VotingConfigRoundCopyWithImpl; @override @useResult - $Res call( - {String roundId, - int bundleIndex, - BigInt eligibleWeightZatoshi, - BigInt delegatedWeightZatoshi, - String roundName}); + $Res call({String roundId, Uint8List eaPk}); } /// @nodoc -class __$VotingPreparedInfoCopyWithImpl<$Res> - implements _$VotingPreparedInfoCopyWith<$Res> { - __$VotingPreparedInfoCopyWithImpl(this._self, this._then); +class __$VotingConfigRoundCopyWithImpl<$Res> + implements _$VotingConfigRoundCopyWith<$Res> { + __$VotingConfigRoundCopyWithImpl(this._self, this._then); - final _VotingPreparedInfo _self; - final $Res Function(_VotingPreparedInfo) _then; + final _VotingConfigRound _self; + final $Res Function(_VotingConfigRound) _then; - /// Create a copy of VotingPreparedInfo + /// Create a copy of VotingConfigRound /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ Object? roundId = null, - Object? bundleIndex = null, - Object? eligibleWeightZatoshi = null, - Object? delegatedWeightZatoshi = null, - Object? roundName = null, + Object? eaPk = null, }) { - return _then(_VotingPreparedInfo( + return _then(_VotingConfigRound( roundId: null == roundId ? _self.roundId : roundId // ignore: cast_nullable_to_non_nullable as String, - bundleIndex: null == bundleIndex - ? _self.bundleIndex - : bundleIndex // ignore: cast_nullable_to_non_nullable - as int, - eligibleWeightZatoshi: null == eligibleWeightZatoshi - ? _self.eligibleWeightZatoshi - : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable - as BigInt, - delegatedWeightZatoshi: null == delegatedWeightZatoshi - ? _self.delegatedWeightZatoshi - : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable - as BigInt, - roundName: null == roundName - ? _self.roundName - : roundName // ignore: cast_nullable_to_non_nullable - as String, + eaPk: null == eaPk + ? _self.eaPk + : eaPk // ignore: cast_nullable_to_non_nullable + as Uint8List, )); } } /// @nodoc -mixin _$VotingSharePayload { - Uint8List get sharesHash; - int get proposalId; - int get voteDecision; - VotingEncryptedShare get encShare; - BigInt get treePosition; - List get allEncShares; - List get shareComms; - Uint8List get primaryBlind; +mixin _$VotingDelegationBuild { + VotingDelegationSubmission get submission; + String get wireJson; - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingSharePayloadCopyWith get copyWith => - _$VotingSharePayloadCopyWithImpl( - this as VotingSharePayload, _$identity); + $VotingDelegationBuildCopyWith get copyWith => + _$VotingDelegationBuildCopyWithImpl( + this as VotingDelegationBuild, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingSharePayload && - const DeepCollectionEquality() - .equals(other.sharesHash, sharesHash) && - (identical(other.proposalId, proposalId) || - other.proposalId == proposalId) && - (identical(other.voteDecision, voteDecision) || - other.voteDecision == voteDecision) && - (identical(other.encShare, encShare) || - other.encShare == encShare) && - (identical(other.treePosition, treePosition) || - other.treePosition == treePosition) && - const DeepCollectionEquality() - .equals(other.allEncShares, allEncShares) && - const DeepCollectionEquality() - .equals(other.shareComms, shareComms) && - const DeepCollectionEquality() - .equals(other.primaryBlind, primaryBlind)); + other is VotingDelegationBuild && + (identical(other.submission, submission) || + other.submission == submission) && + (identical(other.wireJson, wireJson) || + other.wireJson == wireJson)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(sharesHash), - proposalId, - voteDecision, - encShare, - treePosition, - const DeepCollectionEquality().hash(allEncShares), - const DeepCollectionEquality().hash(shareComms), - const DeepCollectionEquality().hash(primaryBlind)); + int get hashCode => Object.hash(runtimeType, submission, wireJson); @override String toString() { - return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + return 'VotingDelegationBuild(submission: $submission, wireJson: $wireJson)'; } } /// @nodoc -abstract mixin class $VotingSharePayloadCopyWith<$Res> { - factory $VotingSharePayloadCopyWith( - VotingSharePayload value, $Res Function(VotingSharePayload) _then) = - _$VotingSharePayloadCopyWithImpl; +abstract mixin class $VotingDelegationBuildCopyWith<$Res> { + factory $VotingDelegationBuildCopyWith(VotingDelegationBuild value, + $Res Function(VotingDelegationBuild) _then) = + _$VotingDelegationBuildCopyWithImpl; @useResult - $Res call( - {Uint8List sharesHash, - int proposalId, - int voteDecision, - VotingEncryptedShare encShare, - BigInt treePosition, - List allEncShares, - List shareComms, - Uint8List primaryBlind}); + $Res call({VotingDelegationSubmission submission, String wireJson}); - $VotingEncryptedShareCopyWith<$Res> get encShare; + $VotingDelegationSubmissionCopyWith<$Res> get submission; } /// @nodoc -class _$VotingSharePayloadCopyWithImpl<$Res> - implements $VotingSharePayloadCopyWith<$Res> { - _$VotingSharePayloadCopyWithImpl(this._self, this._then); +class _$VotingDelegationBuildCopyWithImpl<$Res> + implements $VotingDelegationBuildCopyWith<$Res> { + _$VotingDelegationBuildCopyWithImpl(this._self, this._then); - final VotingSharePayload _self; - final $Res Function(VotingSharePayload) _then; + final VotingDelegationBuild _self; + final $Res Function(VotingDelegationBuild) _then; - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? sharesHash = null, - Object? proposalId = null, - Object? voteDecision = null, - Object? encShare = null, - Object? treePosition = null, - Object? allEncShares = null, - Object? shareComms = null, - Object? primaryBlind = null, + Object? submission = null, + Object? wireJson = null, }) { return _then(_self.copyWith( - sharesHash: null == sharesHash - ? _self.sharesHash - : sharesHash // ignore: cast_nullable_to_non_nullable - as Uint8List, - proposalId: null == proposalId - ? _self.proposalId - : proposalId // ignore: cast_nullable_to_non_nullable - as int, - voteDecision: null == voteDecision - ? _self.voteDecision - : voteDecision // ignore: cast_nullable_to_non_nullable - as int, - encShare: null == encShare - ? _self.encShare - : encShare // ignore: cast_nullable_to_non_nullable - as VotingEncryptedShare, - treePosition: null == treePosition - ? _self.treePosition - : treePosition // ignore: cast_nullable_to_non_nullable - as BigInt, - allEncShares: null == allEncShares - ? _self.allEncShares - : allEncShares // ignore: cast_nullable_to_non_nullable - as List, - shareComms: null == shareComms - ? _self.shareComms - : shareComms // ignore: cast_nullable_to_non_nullable - as List, - primaryBlind: null == primaryBlind - ? _self.primaryBlind - : primaryBlind // ignore: cast_nullable_to_non_nullable - as Uint8List, + submission: null == submission + ? _self.submission + : submission // ignore: cast_nullable_to_non_nullable + as VotingDelegationSubmission, + wireJson: null == wireJson + ? _self.wireJson + : wireJson // ignore: cast_nullable_to_non_nullable + as String, )); } - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') - $VotingEncryptedShareCopyWith<$Res> get encShare { - return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { - return _then(_self.copyWith(encShare: value)); + $VotingDelegationSubmissionCopyWith<$Res> get submission { + return $VotingDelegationSubmissionCopyWith<$Res>(_self.submission, (value) { + return _then(_self.copyWith(submission: value)); }); } } -/// Adds pattern-matching-related methods to [VotingSharePayload]. -extension VotingSharePayloadPatterns on VotingSharePayload { +/// Adds pattern-matching-related methods to [VotingDelegationBuild]. +extension VotingDelegationBuildPatterns on VotingDelegationBuild { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -2541,12 +2189,12 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingSharePayload value)? $default, { + TResult Function(_VotingDelegationBuild value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingSharePayload() when $default != null: + case _VotingDelegationBuild() when $default != null: return $default(_that); case _: return orElse(); @@ -2568,11 +2216,11 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult map( - TResult Function(_VotingSharePayload value) $default, + TResult Function(_VotingDelegationBuild value) $default, ) { final _that = this; switch (_that) { - case _VotingSharePayload(): + case _VotingDelegationBuild(): return $default(_that); } } @@ -2591,11 +2239,11 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingSharePayload value)? $default, + TResult? Function(_VotingDelegationBuild value)? $default, ) { final _that = this; switch (_that) { - case _VotingSharePayload() when $default != null: + case _VotingDelegationBuild() when $default != null: return $default(_that); case _: return null; @@ -2616,30 +2264,14 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult maybeWhen( - TResult Function( - Uint8List sharesHash, - int proposalId, - int voteDecision, - VotingEncryptedShare encShare, - BigInt treePosition, - List allEncShares, - List shareComms, - Uint8List primaryBlind)? + TResult Function(VotingDelegationSubmission submission, String wireJson)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingSharePayload() when $default != null: - return $default( - _that.sharesHash, - _that.proposalId, - _that.voteDecision, - _that.encShare, - _that.treePosition, - _that.allEncShares, - _that.shareComms, - _that.primaryBlind); + case _VotingDelegationBuild() when $default != null: + return $default(_that.submission, _that.wireJson); case _: return orElse(); } @@ -2660,29 +2292,13 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult when( - TResult Function( - Uint8List sharesHash, - int proposalId, - int voteDecision, - VotingEncryptedShare encShare, - BigInt treePosition, - List allEncShares, - List shareComms, - Uint8List primaryBlind) + TResult Function(VotingDelegationSubmission submission, String wireJson) $default, ) { final _that = this; switch (_that) { - case _VotingSharePayload(): - return $default( - _that.sharesHash, - _that.proposalId, - _that.voteDecision, - _that.encShare, - _that.treePosition, - _that.allEncShares, - _that.shareComms, - _that.primaryBlind); + case _VotingDelegationBuild(): + return $default(_that.submission, _that.wireJson); } } @@ -2700,29 +2316,13 @@ extension VotingSharePayloadPatterns on VotingSharePayload { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - Uint8List sharesHash, - int proposalId, - int voteDecision, - VotingEncryptedShare encShare, - BigInt treePosition, - List allEncShares, - List shareComms, - Uint8List primaryBlind)? + TResult? Function(VotingDelegationSubmission submission, String wireJson)? $default, ) { final _that = this; switch (_that) { - case _VotingSharePayload() when $default != null: - return $default( - _that.sharesHash, - _that.proposalId, - _that.voteDecision, - _that.encShare, - _that.treePosition, - _that.allEncShares, - _that.shareComms, - _that.primaryBlind); + case _VotingDelegationBuild() when $default != null: + return $default(_that.submission, _that.wireJson); case _: return null; } @@ -2731,354 +2331,171 @@ extension VotingSharePayloadPatterns on VotingSharePayload { /// @nodoc -class _VotingSharePayload implements VotingSharePayload { - const _VotingSharePayload( - {required this.sharesHash, - required this.proposalId, - required this.voteDecision, - required this.encShare, - required this.treePosition, - required final List allEncShares, - required final List shareComms, - required this.primaryBlind}) - : _allEncShares = allEncShares, - _shareComms = shareComms; - - @override - final Uint8List sharesHash; - @override - final int proposalId; - @override - final int voteDecision; - @override - final VotingEncryptedShare encShare; - @override - final BigInt treePosition; - final List _allEncShares; - @override - List get allEncShares { - if (_allEncShares is EqualUnmodifiableListView) return _allEncShares; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_allEncShares); - } +class _VotingDelegationBuild implements VotingDelegationBuild { + const _VotingDelegationBuild( + {required this.submission, required this.wireJson}); - final List _shareComms; @override - List get shareComms { - if (_shareComms is EqualUnmodifiableListView) return _shareComms; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_shareComms); - } - + final VotingDelegationSubmission submission; @override - final Uint8List primaryBlind; + final String wireJson; - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingSharePayloadCopyWith<_VotingSharePayload> get copyWith => - __$VotingSharePayloadCopyWithImpl<_VotingSharePayload>(this, _$identity); + _$VotingDelegationBuildCopyWith<_VotingDelegationBuild> get copyWith => + __$VotingDelegationBuildCopyWithImpl<_VotingDelegationBuild>( + this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingSharePayload && - const DeepCollectionEquality() - .equals(other.sharesHash, sharesHash) && - (identical(other.proposalId, proposalId) || - other.proposalId == proposalId) && - (identical(other.voteDecision, voteDecision) || - other.voteDecision == voteDecision) && - (identical(other.encShare, encShare) || - other.encShare == encShare) && - (identical(other.treePosition, treePosition) || - other.treePosition == treePosition) && - const DeepCollectionEquality() - .equals(other._allEncShares, _allEncShares) && - const DeepCollectionEquality() - .equals(other._shareComms, _shareComms) && - const DeepCollectionEquality() - .equals(other.primaryBlind, primaryBlind)); + other is _VotingDelegationBuild && + (identical(other.submission, submission) || + other.submission == submission) && + (identical(other.wireJson, wireJson) || + other.wireJson == wireJson)); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(sharesHash), - proposalId, - voteDecision, - encShare, - treePosition, - const DeepCollectionEquality().hash(_allEncShares), - const DeepCollectionEquality().hash(_shareComms), - const DeepCollectionEquality().hash(primaryBlind)); + int get hashCode => Object.hash(runtimeType, submission, wireJson); @override String toString() { - return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + return 'VotingDelegationBuild(submission: $submission, wireJson: $wireJson)'; } } /// @nodoc -abstract mixin class _$VotingSharePayloadCopyWith<$Res> - implements $VotingSharePayloadCopyWith<$Res> { - factory _$VotingSharePayloadCopyWith( - _VotingSharePayload value, $Res Function(_VotingSharePayload) _then) = - __$VotingSharePayloadCopyWithImpl; +abstract mixin class _$VotingDelegationBuildCopyWith<$Res> + implements $VotingDelegationBuildCopyWith<$Res> { + factory _$VotingDelegationBuildCopyWith(_VotingDelegationBuild value, + $Res Function(_VotingDelegationBuild) _then) = + __$VotingDelegationBuildCopyWithImpl; @override @useResult - $Res call( - {Uint8List sharesHash, - int proposalId, - int voteDecision, - VotingEncryptedShare encShare, - BigInt treePosition, - List allEncShares, - List shareComms, - Uint8List primaryBlind}); + $Res call({VotingDelegationSubmission submission, String wireJson}); @override - $VotingEncryptedShareCopyWith<$Res> get encShare; + $VotingDelegationSubmissionCopyWith<$Res> get submission; } /// @nodoc -class __$VotingSharePayloadCopyWithImpl<$Res> - implements _$VotingSharePayloadCopyWith<$Res> { - __$VotingSharePayloadCopyWithImpl(this._self, this._then); +class __$VotingDelegationBuildCopyWithImpl<$Res> + implements _$VotingDelegationBuildCopyWith<$Res> { + __$VotingDelegationBuildCopyWithImpl(this._self, this._then); - final _VotingSharePayload _self; - final $Res Function(_VotingSharePayload) _then; + final _VotingDelegationBuild _self; + final $Res Function(_VotingDelegationBuild) _then; - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? sharesHash = null, - Object? proposalId = null, - Object? voteDecision = null, - Object? encShare = null, - Object? treePosition = null, - Object? allEncShares = null, - Object? shareComms = null, - Object? primaryBlind = null, + Object? submission = null, + Object? wireJson = null, }) { - return _then(_VotingSharePayload( - sharesHash: null == sharesHash - ? _self.sharesHash - : sharesHash // ignore: cast_nullable_to_non_nullable - as Uint8List, - proposalId: null == proposalId - ? _self.proposalId - : proposalId // ignore: cast_nullable_to_non_nullable - as int, - voteDecision: null == voteDecision - ? _self.voteDecision - : voteDecision // ignore: cast_nullable_to_non_nullable - as int, - encShare: null == encShare - ? _self.encShare - : encShare // ignore: cast_nullable_to_non_nullable - as VotingEncryptedShare, - treePosition: null == treePosition - ? _self.treePosition - : treePosition // ignore: cast_nullable_to_non_nullable - as BigInt, - allEncShares: null == allEncShares - ? _self._allEncShares - : allEncShares // ignore: cast_nullable_to_non_nullable - as List, - shareComms: null == shareComms - ? _self._shareComms - : shareComms // ignore: cast_nullable_to_non_nullable - as List, - primaryBlind: null == primaryBlind - ? _self.primaryBlind - : primaryBlind // ignore: cast_nullable_to_non_nullable - as Uint8List, + return _then(_VotingDelegationBuild( + submission: null == submission + ? _self.submission + : submission // ignore: cast_nullable_to_non_nullable + as VotingDelegationSubmission, + wireJson: null == wireJson + ? _self.wireJson + : wireJson // ignore: cast_nullable_to_non_nullable + as String, )); } - /// Create a copy of VotingSharePayload + /// Create a copy of VotingDelegationBuild /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') - $VotingEncryptedShareCopyWith<$Res> get encShare { - return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { - return _then(_self.copyWith(encShare: value)); + $VotingDelegationSubmissionCopyWith<$Res> get submission { + return $VotingDelegationSubmissionCopyWith<$Res>(_self.submission, (value) { + return _then(_self.copyWith(submission: value)); }); } } /// @nodoc -mixin _$VotingSignedVoteCommitment { - int get proposalId; - int get choice; - String get voteRoundId; - Uint8List get vanNullifier; - Uint8List get voteAuthorityNoteNew; - Uint8List get voteCommitment; - Uint8List get proof; - int get anchorHeight; - Uint8List get rVpk; - Uint8List get voteAuthSig; - String get commitmentBundleJson; +mixin _$VotingDelegationConfirmation { + String get txHash; + int get vanLeafPosition; - /// Create a copy of VotingSignedVoteCommitment + /// Create a copy of VotingDelegationConfirmation /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingSignedVoteCommitmentCopyWith - get copyWith => - _$VotingSignedVoteCommitmentCopyWithImpl( - this as VotingSignedVoteCommitment, _$identity); + $VotingDelegationConfirmationCopyWith + get copyWith => _$VotingDelegationConfirmationCopyWithImpl< + VotingDelegationConfirmation>( + this as VotingDelegationConfirmation, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingSignedVoteCommitment && - (identical(other.proposalId, proposalId) || - other.proposalId == proposalId) && - (identical(other.choice, choice) || other.choice == choice) && - (identical(other.voteRoundId, voteRoundId) || - other.voteRoundId == voteRoundId) && - const DeepCollectionEquality() - .equals(other.vanNullifier, vanNullifier) && - const DeepCollectionEquality() - .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && - const DeepCollectionEquality() - .equals(other.voteCommitment, voteCommitment) && - const DeepCollectionEquality().equals(other.proof, proof) && - (identical(other.anchorHeight, anchorHeight) || - other.anchorHeight == anchorHeight) && - const DeepCollectionEquality().equals(other.rVpk, rVpk) && - const DeepCollectionEquality() - .equals(other.voteAuthSig, voteAuthSig) && - (identical(other.commitmentBundleJson, commitmentBundleJson) || - other.commitmentBundleJson == commitmentBundleJson)); + other is VotingDelegationConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); } @override - int get hashCode => Object.hash( - runtimeType, - proposalId, - choice, - voteRoundId, - const DeepCollectionEquality().hash(vanNullifier), - const DeepCollectionEquality().hash(voteAuthorityNoteNew), - const DeepCollectionEquality().hash(voteCommitment), - const DeepCollectionEquality().hash(proof), - anchorHeight, - const DeepCollectionEquality().hash(rVpk), - const DeepCollectionEquality().hash(voteAuthSig), - commitmentBundleJson); + int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); @override String toString() { - return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; } } /// @nodoc -abstract mixin class $VotingSignedVoteCommitmentCopyWith<$Res> { - factory $VotingSignedVoteCommitmentCopyWith(VotingSignedVoteCommitment value, - $Res Function(VotingSignedVoteCommitment) _then) = - _$VotingSignedVoteCommitmentCopyWithImpl; +abstract mixin class $VotingDelegationConfirmationCopyWith<$Res> { + factory $VotingDelegationConfirmationCopyWith( + VotingDelegationConfirmation value, + $Res Function(VotingDelegationConfirmation) _then) = + _$VotingDelegationConfirmationCopyWithImpl; @useResult - $Res call( - {int proposalId, - int choice, - String voteRoundId, - Uint8List vanNullifier, - Uint8List voteAuthorityNoteNew, - Uint8List voteCommitment, - Uint8List proof, - int anchorHeight, - Uint8List rVpk, - Uint8List voteAuthSig, - String commitmentBundleJson}); + $Res call({String txHash, int vanLeafPosition}); } /// @nodoc -class _$VotingSignedVoteCommitmentCopyWithImpl<$Res> - implements $VotingSignedVoteCommitmentCopyWith<$Res> { - _$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); +class _$VotingDelegationConfirmationCopyWithImpl<$Res> + implements $VotingDelegationConfirmationCopyWith<$Res> { + _$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); - final VotingSignedVoteCommitment _self; - final $Res Function(VotingSignedVoteCommitment) _then; + final VotingDelegationConfirmation _self; + final $Res Function(VotingDelegationConfirmation) _then; - /// Create a copy of VotingSignedVoteCommitment + /// Create a copy of VotingDelegationConfirmation /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ - Object? proposalId = null, - Object? choice = null, - Object? voteRoundId = null, - Object? vanNullifier = null, - Object? voteAuthorityNoteNew = null, - Object? voteCommitment = null, - Object? proof = null, - Object? anchorHeight = null, - Object? rVpk = null, - Object? voteAuthSig = null, - Object? commitmentBundleJson = null, + Object? txHash = null, + Object? vanLeafPosition = null, }) { return _then(_self.copyWith( - proposalId: null == proposalId - ? _self.proposalId - : proposalId // ignore: cast_nullable_to_non_nullable - as int, - choice: null == choice - ? _self.choice - : choice // ignore: cast_nullable_to_non_nullable - as int, - voteRoundId: null == voteRoundId - ? _self.voteRoundId - : voteRoundId // ignore: cast_nullable_to_non_nullable + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable as String, - vanNullifier: null == vanNullifier - ? _self.vanNullifier - : vanNullifier // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteAuthorityNoteNew: null == voteAuthorityNoteNew - ? _self.voteAuthorityNoteNew - : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteCommitment: null == voteCommitment - ? _self.voteCommitment - : voteCommitment // ignore: cast_nullable_to_non_nullable - as Uint8List, - proof: null == proof - ? _self.proof - : proof // ignore: cast_nullable_to_non_nullable - as Uint8List, - anchorHeight: null == anchorHeight - ? _self.anchorHeight - : anchorHeight // ignore: cast_nullable_to_non_nullable + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable as int, - rVpk: null == rVpk - ? _self.rVpk - : rVpk // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteAuthSig: null == voteAuthSig - ? _self.voteAuthSig - : voteAuthSig // ignore: cast_nullable_to_non_nullable - as Uint8List, - commitmentBundleJson: null == commitmentBundleJson - ? _self.commitmentBundleJson - : commitmentBundleJson // ignore: cast_nullable_to_non_nullable - as String, )); } } -/// Adds pattern-matching-related methods to [VotingSignedVoteCommitment]. -extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { +/// Adds pattern-matching-related methods to [VotingDelegationConfirmation]. +extension VotingDelegationConfirmationPatterns on VotingDelegationConfirmation { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -3093,12 +2510,12 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingSignedVoteCommitment value)? $default, { + TResult Function(_VotingDelegationConfirmation value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment() when $default != null: + case _VotingDelegationConfirmation() when $default != null: return $default(_that); case _: return orElse(); @@ -3120,11 +2537,11 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult map( - TResult Function(_VotingSignedVoteCommitment value) $default, + TResult Function(_VotingDelegationConfirmation value) $default, ) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment(): + case _VotingDelegationConfirmation(): return $default(_that); } } @@ -3143,11 +2560,11 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingSignedVoteCommitment value)? $default, + TResult? Function(_VotingDelegationConfirmation value)? $default, ) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment() when $default != null: + case _VotingDelegationConfirmation() when $default != null: return $default(_that); case _: return null; @@ -3168,36 +2585,13 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult maybeWhen( - TResult Function( - int proposalId, - int choice, - String voteRoundId, - Uint8List vanNullifier, - Uint8List voteAuthorityNoteNew, - Uint8List voteCommitment, - Uint8List proof, - int anchorHeight, - Uint8List rVpk, - Uint8List voteAuthSig, - String commitmentBundleJson)? - $default, { + TResult Function(String txHash, int vanLeafPosition)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment() when $default != null: - return $default( - _that.proposalId, - _that.choice, - _that.voteRoundId, - _that.vanNullifier, - _that.voteAuthorityNoteNew, - _that.voteCommitment, - _that.proof, - _that.anchorHeight, - _that.rVpk, - _that.voteAuthSig, - _that.commitmentBundleJson); + case _VotingDelegationConfirmation() when $default != null: + return $default(_that.txHash, _that.vanLeafPosition); case _: return orElse(); } @@ -3218,35 +2612,12 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult when( - TResult Function( - int proposalId, - int choice, - String voteRoundId, - Uint8List vanNullifier, - Uint8List voteAuthorityNoteNew, - Uint8List voteCommitment, - Uint8List proof, - int anchorHeight, - Uint8List rVpk, - Uint8List voteAuthSig, - String commitmentBundleJson) - $default, + TResult Function(String txHash, int vanLeafPosition) $default, ) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment(): - return $default( - _that.proposalId, - _that.choice, - _that.voteRoundId, - _that.vanNullifier, - _that.voteAuthorityNoteNew, - _that.voteCommitment, - _that.proof, - _that.anchorHeight, - _that.rVpk, - _that.voteAuthSig, - _that.commitmentBundleJson); + case _VotingDelegationConfirmation(): + return $default(_that.txHash, _that.vanLeafPosition); } } @@ -3264,35 +2635,12 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - int proposalId, - int choice, - String voteRoundId, - Uint8List vanNullifier, - Uint8List voteAuthorityNoteNew, - Uint8List voteCommitment, - Uint8List proof, - int anchorHeight, - Uint8List rVpk, - Uint8List voteAuthSig, - String commitmentBundleJson)? - $default, + TResult? Function(String txHash, int vanLeafPosition)? $default, ) { final _that = this; switch (_that) { - case _VotingSignedVoteCommitment() when $default != null: - return $default( - _that.proposalId, - _that.choice, - _that.voteRoundId, - _that.vanNullifier, - _that.voteAuthorityNoteNew, - _that.voteCommitment, - _that.proof, - _that.anchorHeight, - _that.rVpk, - _that.voteAuthSig, - _that.commitmentBundleJson); + case _VotingDelegationConfirmation() when $default != null: + return $default(_that.txHash, _that.vanLeafPosition); case _: return null; } @@ -3301,277 +2649,109 @@ extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { /// @nodoc -class _VotingSignedVoteCommitment implements VotingSignedVoteCommitment { - const _VotingSignedVoteCommitment( - {required this.proposalId, - required this.choice, - required this.voteRoundId, - required this.vanNullifier, - required this.voteAuthorityNoteNew, - required this.voteCommitment, - required this.proof, - required this.anchorHeight, - required this.rVpk, - required this.voteAuthSig, - required this.commitmentBundleJson}); +class _VotingDelegationConfirmation implements VotingDelegationConfirmation { + const _VotingDelegationConfirmation( + {required this.txHash, required this.vanLeafPosition}); @override - final int proposalId; - @override - final int choice; - @override - final String voteRoundId; - @override - final Uint8List vanNullifier; - @override - final Uint8List voteAuthorityNoteNew; - @override - final Uint8List voteCommitment; - @override - final Uint8List proof; - @override - final int anchorHeight; - @override - final Uint8List rVpk; - @override - final Uint8List voteAuthSig; + final String txHash; @override - final String commitmentBundleJson; + final int vanLeafPosition; - /// Create a copy of VotingSignedVoteCommitment + /// Create a copy of VotingDelegationConfirmation /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingSignedVoteCommitmentCopyWith<_VotingSignedVoteCommitment> - get copyWith => __$VotingSignedVoteCommitmentCopyWithImpl< - _VotingSignedVoteCommitment>(this, _$identity); - + _$VotingDelegationConfirmationCopyWith<_VotingDelegationConfirmation> + get copyWith => __$VotingDelegationConfirmationCopyWithImpl< + _VotingDelegationConfirmation>(this, _$identity); + @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingSignedVoteCommitment && - (identical(other.proposalId, proposalId) || - other.proposalId == proposalId) && - (identical(other.choice, choice) || other.choice == choice) && - (identical(other.voteRoundId, voteRoundId) || - other.voteRoundId == voteRoundId) && - const DeepCollectionEquality() - .equals(other.vanNullifier, vanNullifier) && - const DeepCollectionEquality() - .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && - const DeepCollectionEquality() - .equals(other.voteCommitment, voteCommitment) && - const DeepCollectionEquality().equals(other.proof, proof) && - (identical(other.anchorHeight, anchorHeight) || - other.anchorHeight == anchorHeight) && - const DeepCollectionEquality().equals(other.rVpk, rVpk) && - const DeepCollectionEquality() - .equals(other.voteAuthSig, voteAuthSig) && - (identical(other.commitmentBundleJson, commitmentBundleJson) || - other.commitmentBundleJson == commitmentBundleJson)); + other is _VotingDelegationConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); } @override - int get hashCode => Object.hash( - runtimeType, - proposalId, - choice, - voteRoundId, - const DeepCollectionEquality().hash(vanNullifier), - const DeepCollectionEquality().hash(voteAuthorityNoteNew), - const DeepCollectionEquality().hash(voteCommitment), - const DeepCollectionEquality().hash(proof), - anchorHeight, - const DeepCollectionEquality().hash(rVpk), - const DeepCollectionEquality().hash(voteAuthSig), - commitmentBundleJson); + int get hashCode => Object.hash(runtimeType, txHash, vanLeafPosition); @override String toString() { - return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + return 'VotingDelegationConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; } } /// @nodoc -abstract mixin class _$VotingSignedVoteCommitmentCopyWith<$Res> - implements $VotingSignedVoteCommitmentCopyWith<$Res> { - factory _$VotingSignedVoteCommitmentCopyWith( - _VotingSignedVoteCommitment value, - $Res Function(_VotingSignedVoteCommitment) _then) = - __$VotingSignedVoteCommitmentCopyWithImpl; +abstract mixin class _$VotingDelegationConfirmationCopyWith<$Res> + implements $VotingDelegationConfirmationCopyWith<$Res> { + factory _$VotingDelegationConfirmationCopyWith( + _VotingDelegationConfirmation value, + $Res Function(_VotingDelegationConfirmation) _then) = + __$VotingDelegationConfirmationCopyWithImpl; @override @useResult - $Res call( - {int proposalId, - int choice, - String voteRoundId, - Uint8List vanNullifier, - Uint8List voteAuthorityNoteNew, - Uint8List voteCommitment, - Uint8List proof, - int anchorHeight, - Uint8List rVpk, - Uint8List voteAuthSig, - String commitmentBundleJson}); + $Res call({String txHash, int vanLeafPosition}); } /// @nodoc -class __$VotingSignedVoteCommitmentCopyWithImpl<$Res> - implements _$VotingSignedVoteCommitmentCopyWith<$Res> { - __$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); +class __$VotingDelegationConfirmationCopyWithImpl<$Res> + implements _$VotingDelegationConfirmationCopyWith<$Res> { + __$VotingDelegationConfirmationCopyWithImpl(this._self, this._then); - final _VotingSignedVoteCommitment _self; - final $Res Function(_VotingSignedVoteCommitment) _then; + final _VotingDelegationConfirmation _self; + final $Res Function(_VotingDelegationConfirmation) _then; - /// Create a copy of VotingSignedVoteCommitment + /// Create a copy of VotingDelegationConfirmation /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? proposalId = null, - Object? choice = null, - Object? voteRoundId = null, - Object? vanNullifier = null, - Object? voteAuthorityNoteNew = null, - Object? voteCommitment = null, - Object? proof = null, - Object? anchorHeight = null, - Object? rVpk = null, - Object? voteAuthSig = null, - Object? commitmentBundleJson = null, + Object? txHash = null, + Object? vanLeafPosition = null, }) { - return _then(_VotingSignedVoteCommitment( - proposalId: null == proposalId - ? _self.proposalId - : proposalId // ignore: cast_nullable_to_non_nullable - as int, - choice: null == choice - ? _self.choice - : choice // ignore: cast_nullable_to_non_nullable - as int, - voteRoundId: null == voteRoundId - ? _self.voteRoundId - : voteRoundId // ignore: cast_nullable_to_non_nullable + return _then(_VotingDelegationConfirmation( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable as String, - vanNullifier: null == vanNullifier - ? _self.vanNullifier - : vanNullifier // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteAuthorityNoteNew: null == voteAuthorityNoteNew - ? _self.voteAuthorityNoteNew - : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteCommitment: null == voteCommitment - ? _self.voteCommitment - : voteCommitment // ignore: cast_nullable_to_non_nullable - as Uint8List, - proof: null == proof - ? _self.proof - : proof // ignore: cast_nullable_to_non_nullable - as Uint8List, - anchorHeight: null == anchorHeight - ? _self.anchorHeight - : anchorHeight // ignore: cast_nullable_to_non_nullable + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable as int, - rVpk: null == rVpk - ? _self.rVpk - : rVpk // ignore: cast_nullable_to_non_nullable - as Uint8List, - voteAuthSig: null == voteAuthSig - ? _self.voteAuthSig - : voteAuthSig // ignore: cast_nullable_to_non_nullable - as Uint8List, - commitmentBundleJson: null == commitmentBundleJson - ? _self.commitmentBundleJson - : commitmentBundleJson // ignore: cast_nullable_to_non_nullable - as String, )); } } /// @nodoc -mixin _$VotingVanWitness { - List get authPath; - int get position; - int get anchorHeight; - - /// Create a copy of VotingVanWitness - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - @pragma('vm:prefer-inline') - $VotingVanWitnessCopyWith get copyWith => - _$VotingVanWitnessCopyWithImpl( - this as VotingVanWitness, _$identity); - +mixin _$VotingDelegationProgress { @override bool operator ==(Object other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is VotingVanWitness && - const DeepCollectionEquality().equals(other.authPath, authPath) && - (identical(other.position, position) || - other.position == position) && - (identical(other.anchorHeight, anchorHeight) || - other.anchorHeight == anchorHeight)); + (other.runtimeType == runtimeType && other is VotingDelegationProgress); } @override - int get hashCode => Object.hash(runtimeType, - const DeepCollectionEquality().hash(authPath), position, anchorHeight); + int get hashCode => runtimeType.hashCode; @override String toString() { - return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + return 'VotingDelegationProgress()'; } } /// @nodoc -abstract mixin class $VotingVanWitnessCopyWith<$Res> { - factory $VotingVanWitnessCopyWith( - VotingVanWitness value, $Res Function(VotingVanWitness) _then) = - _$VotingVanWitnessCopyWithImpl; - @useResult - $Res call({List authPath, int position, int anchorHeight}); -} - -/// @nodoc -class _$VotingVanWitnessCopyWithImpl<$Res> - implements $VotingVanWitnessCopyWith<$Res> { - _$VotingVanWitnessCopyWithImpl(this._self, this._then); - - final VotingVanWitness _self; - final $Res Function(VotingVanWitness) _then; - - /// Create a copy of VotingVanWitness - /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? authPath = null, - Object? position = null, - Object? anchorHeight = null, - }) { - return _then(_self.copyWith( - authPath: null == authPath - ? _self.authPath - : authPath // ignore: cast_nullable_to_non_nullable - as List, - position: null == position - ? _self.position - : position // ignore: cast_nullable_to_non_nullable - as int, - anchorHeight: null == anchorHeight - ? _self.anchorHeight - : anchorHeight // ignore: cast_nullable_to_non_nullable - as int, - )); - } +class $VotingDelegationProgressCopyWith<$Res> { + $VotingDelegationProgressCopyWith( + VotingDelegationProgress _, $Res Function(VotingDelegationProgress) __); } -/// Adds pattern-matching-related methods to [VotingVanWitness]. -extension VotingVanWitnessPatterns on VotingVanWitness { +/// Adds pattern-matching-related methods to [VotingDelegationProgress]. +extension VotingDelegationProgressPatterns on VotingDelegationProgress { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -3585,14 +2765,42 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult maybeMap( - TResult Function(_VotingVanWitness value)? $default, { + TResult maybeMap({ + TResult Function(VotingDelegationProgress_SelectingNotes value)? + selectingNotes, + TResult Function(VotingDelegationProgress_PcztBuilding value)? pcztBuilding, + TResult Function(VotingDelegationProgress_PcztBuilt value)? pcztBuilt, + TResult Function(VotingDelegationProgress_ProofStarting value)? + proofStarting, + TResult Function(VotingDelegationProgress_ProofProgress value)? + proofProgress, + TResult Function(VotingDelegationProgress_ProofComplete value)? + proofComplete, + TResult Function(VotingDelegationProgress_SigningPayload value)? + signingPayload, + TResult Function(VotingDelegationProgress_PayloadReady value)? payloadReady, required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVanWitness() when $default != null: - return $default(_that); + case VotingDelegationProgress_SelectingNotes() + when selectingNotes != null: + return selectingNotes(_that); + case VotingDelegationProgress_PcztBuilding() when pcztBuilding != null: + return pcztBuilding(_that); + case VotingDelegationProgress_PcztBuilt() when pcztBuilt != null: + return pcztBuilt(_that); + case VotingDelegationProgress_ProofStarting() when proofStarting != null: + return proofStarting(_that); + case VotingDelegationProgress_ProofProgress() when proofProgress != null: + return proofProgress(_that); + case VotingDelegationProgress_ProofComplete() when proofComplete != null: + return proofComplete(_that); + case VotingDelegationProgress_SigningPayload() + when signingPayload != null: + return signingPayload(_that); + case VotingDelegationProgress_PayloadReady() when payloadReady != null: + return payloadReady(_that); case _: return orElse(); } @@ -3612,13 +2820,42 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult map( - TResult Function(_VotingVanWitness value) $default, - ) { + TResult map({ + required TResult Function(VotingDelegationProgress_SelectingNotes value) + selectingNotes, + required TResult Function(VotingDelegationProgress_PcztBuilding value) + pcztBuilding, + required TResult Function(VotingDelegationProgress_PcztBuilt value) + pcztBuilt, + required TResult Function(VotingDelegationProgress_ProofStarting value) + proofStarting, + required TResult Function(VotingDelegationProgress_ProofProgress value) + proofProgress, + required TResult Function(VotingDelegationProgress_ProofComplete value) + proofComplete, + required TResult Function(VotingDelegationProgress_SigningPayload value) + signingPayload, + required TResult Function(VotingDelegationProgress_PayloadReady value) + payloadReady, + }) { final _that = this; switch (_that) { - case _VotingVanWitness(): - return $default(_that); + case VotingDelegationProgress_SelectingNotes(): + return selectingNotes(_that); + case VotingDelegationProgress_PcztBuilding(): + return pcztBuilding(_that); + case VotingDelegationProgress_PcztBuilt(): + return pcztBuilt(_that); + case VotingDelegationProgress_ProofStarting(): + return proofStarting(_that); + case VotingDelegationProgress_ProofProgress(): + return proofProgress(_that); + case VotingDelegationProgress_ProofComplete(): + return proofComplete(_that); + case VotingDelegationProgress_SigningPayload(): + return signingPayload(_that); + case VotingDelegationProgress_PayloadReady(): + return payloadReady(_that); } } @@ -3635,13 +2872,43 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult? mapOrNull( - TResult? Function(_VotingVanWitness value)? $default, - ) { + TResult? mapOrNull({ + TResult? Function(VotingDelegationProgress_SelectingNotes value)? + selectingNotes, + TResult? Function(VotingDelegationProgress_PcztBuilding value)? + pcztBuilding, + TResult? Function(VotingDelegationProgress_PcztBuilt value)? pcztBuilt, + TResult? Function(VotingDelegationProgress_ProofStarting value)? + proofStarting, + TResult? Function(VotingDelegationProgress_ProofProgress value)? + proofProgress, + TResult? Function(VotingDelegationProgress_ProofComplete value)? + proofComplete, + TResult? Function(VotingDelegationProgress_SigningPayload value)? + signingPayload, + TResult? Function(VotingDelegationProgress_PayloadReady value)? + payloadReady, + }) { final _that = this; switch (_that) { - case _VotingVanWitness() when $default != null: - return $default(_that); + case VotingDelegationProgress_SelectingNotes() + when selectingNotes != null: + return selectingNotes(_that); + case VotingDelegationProgress_PcztBuilding() when pcztBuilding != null: + return pcztBuilding(_that); + case VotingDelegationProgress_PcztBuilt() when pcztBuilt != null: + return pcztBuilt(_that); + case VotingDelegationProgress_ProofStarting() when proofStarting != null: + return proofStarting(_that); + case VotingDelegationProgress_ProofProgress() when proofProgress != null: + return proofProgress(_that); + case VotingDelegationProgress_ProofComplete() when proofComplete != null: + return proofComplete(_that); + case VotingDelegationProgress_SigningPayload() + when signingPayload != null: + return signingPayload(_that); + case VotingDelegationProgress_PayloadReady() when payloadReady != null: + return payloadReady(_that); case _: return null; } @@ -3660,15 +2927,37 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult maybeWhen( - TResult Function(List authPath, int position, int anchorHeight)? - $default, { + TResult maybeWhen({ + TResult Function()? selectingNotes, + TResult Function()? pcztBuilding, + TResult Function()? pcztBuilt, + TResult Function()? proofStarting, + TResult Function(double progress)? proofProgress, + TResult Function()? proofComplete, + TResult Function()? signingPayload, + TResult Function()? payloadReady, required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVanWitness() when $default != null: - return $default(_that.authPath, _that.position, _that.anchorHeight); + case VotingDelegationProgress_SelectingNotes() + when selectingNotes != null: + return selectingNotes(); + case VotingDelegationProgress_PcztBuilding() when pcztBuilding != null: + return pcztBuilding(); + case VotingDelegationProgress_PcztBuilt() when pcztBuilt != null: + return pcztBuilt(); + case VotingDelegationProgress_ProofStarting() when proofStarting != null: + return proofStarting(); + case VotingDelegationProgress_ProofProgress() when proofProgress != null: + return proofProgress(_that.progress); + case VotingDelegationProgress_ProofComplete() when proofComplete != null: + return proofComplete(); + case VotingDelegationProgress_SigningPayload() + when signingPayload != null: + return signingPayload(); + case VotingDelegationProgress_PayloadReady() when payloadReady != null: + return payloadReady(); case _: return orElse(); } @@ -3688,14 +2977,34 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult when( - TResult Function(List authPath, int position, int anchorHeight) - $default, - ) { + TResult when({ + required TResult Function() selectingNotes, + required TResult Function() pcztBuilding, + required TResult Function() pcztBuilt, + required TResult Function() proofStarting, + required TResult Function(double progress) proofProgress, + required TResult Function() proofComplete, + required TResult Function() signingPayload, + required TResult Function() payloadReady, + }) { final _that = this; switch (_that) { - case _VotingVanWitness(): - return $default(_that.authPath, _that.position, _that.anchorHeight); + case VotingDelegationProgress_SelectingNotes(): + return selectingNotes(); + case VotingDelegationProgress_PcztBuilding(): + return pcztBuilding(); + case VotingDelegationProgress_PcztBuilt(): + return pcztBuilt(); + case VotingDelegationProgress_ProofStarting(): + return proofStarting(); + case VotingDelegationProgress_ProofProgress(): + return proofProgress(_that.progress); + case VotingDelegationProgress_ProofComplete(): + return proofComplete(); + case VotingDelegationProgress_SigningPayload(): + return signingPayload(); + case VotingDelegationProgress_PayloadReady(): + return payloadReady(); } } @@ -3712,14 +3021,36 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// ``` @optionalTypeArgs - TResult? whenOrNull( - TResult? Function(List authPath, int position, int anchorHeight)? - $default, - ) { + TResult? whenOrNull({ + TResult? Function()? selectingNotes, + TResult? Function()? pcztBuilding, + TResult? Function()? pcztBuilt, + TResult? Function()? proofStarting, + TResult? Function(double progress)? proofProgress, + TResult? Function()? proofComplete, + TResult? Function()? signingPayload, + TResult? Function()? payloadReady, + }) { final _that = this; switch (_that) { - case _VotingVanWitness() when $default != null: - return $default(_that.authPath, _that.position, _that.anchorHeight); + case VotingDelegationProgress_SelectingNotes() + when selectingNotes != null: + return selectingNotes(); + case VotingDelegationProgress_PcztBuilding() when pcztBuilding != null: + return pcztBuilding(); + case VotingDelegationProgress_PcztBuilt() when pcztBuilt != null: + return pcztBuilt(); + case VotingDelegationProgress_ProofStarting() when proofStarting != null: + return proofStarting(); + case VotingDelegationProgress_ProofProgress() when proofProgress != null: + return proofProgress(_that.progress); + case VotingDelegationProgress_ProofComplete() when proofComplete != null: + return proofComplete(); + case VotingDelegationProgress_SigningPayload() + when signingPayload != null: + return signingPayload(); + case VotingDelegationProgress_PayloadReady() when payloadReady != null: + return payloadReady(); case _: return null; } @@ -3728,96 +3059,9382 @@ extension VotingVanWitnessPatterns on VotingVanWitness { /// @nodoc -class _VotingVanWitness implements VotingVanWitness { - const _VotingVanWitness( - {required final List authPath, - required this.position, - required this.anchorHeight}) - : _authPath = authPath; +class VotingDelegationProgress_SelectingNotes extends VotingDelegationProgress { + const VotingDelegationProgress_SelectingNotes() : super._(); - final List _authPath; @override - List get authPath { - if (_authPath is EqualUnmodifiableListView) return _authPath; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_authPath); - } + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_SelectingNotes); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.selectingNotes()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_PcztBuilding extends VotingDelegationProgress { + const VotingDelegationProgress_PcztBuilding() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_PcztBuilding); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.pcztBuilding()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_PcztBuilt extends VotingDelegationProgress { + const VotingDelegationProgress_PcztBuilt() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_PcztBuilt); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.pcztBuilt()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_ProofStarting extends VotingDelegationProgress { + const VotingDelegationProgress_ProofStarting() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_ProofStarting); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.proofStarting()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_ProofProgress extends VotingDelegationProgress { + const VotingDelegationProgress_ProofProgress({required this.progress}) + : super._(); + + final double progress; + + /// Create a copy of VotingDelegationProgress + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationProgress_ProofProgressCopyWith< + VotingDelegationProgress_ProofProgress> + get copyWith => _$VotingDelegationProgress_ProofProgressCopyWithImpl< + VotingDelegationProgress_ProofProgress>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_ProofProgress && + (identical(other.progress, progress) || + other.progress == progress)); + } + + @override + int get hashCode => Object.hash(runtimeType, progress); + + @override + String toString() { + return 'VotingDelegationProgress.proofProgress(progress: $progress)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationProgress_ProofProgressCopyWith<$Res> + implements $VotingDelegationProgressCopyWith<$Res> { + factory $VotingDelegationProgress_ProofProgressCopyWith( + VotingDelegationProgress_ProofProgress value, + $Res Function(VotingDelegationProgress_ProofProgress) _then) = + _$VotingDelegationProgress_ProofProgressCopyWithImpl; + @useResult + $Res call({double progress}); +} + +/// @nodoc +class _$VotingDelegationProgress_ProofProgressCopyWithImpl<$Res> + implements $VotingDelegationProgress_ProofProgressCopyWith<$Res> { + _$VotingDelegationProgress_ProofProgressCopyWithImpl(this._self, this._then); + + final VotingDelegationProgress_ProofProgress _self; + final $Res Function(VotingDelegationProgress_ProofProgress) _then; + + /// Create a copy of VotingDelegationProgress + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + $Res call({ + Object? progress = null, + }) { + return _then(VotingDelegationProgress_ProofProgress( + progress: null == progress + ? _self.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc + +class VotingDelegationProgress_ProofComplete extends VotingDelegationProgress { + const VotingDelegationProgress_ProofComplete() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_ProofComplete); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.proofComplete()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_SigningPayload extends VotingDelegationProgress { + const VotingDelegationProgress_SigningPayload() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_SigningPayload); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.signingPayload()'; + } +} + +/// @nodoc + +class VotingDelegationProgress_PayloadReady extends VotingDelegationProgress { + const VotingDelegationProgress_PayloadReady() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationProgress_PayloadReady); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'VotingDelegationProgress.payloadReady()'; + } +} + +/// @nodoc +mixin _$VotingDelegationRecovery { + int get bundleIndex; + String get phase; + String get workflowPhase; + String? get txHash; + int? get vanLeafPosition; + + /// Create a copy of VotingDelegationRecovery + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationRecoveryCopyWith get copyWith => + _$VotingDelegationRecoveryCopyWithImpl( + this as VotingDelegationRecovery, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationRecovery && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.workflowPhase, workflowPhase) || + other.workflowPhase == workflowPhase) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash( + runtimeType, bundleIndex, phase, workflowPhase, txHash, vanLeafPosition); + + @override + String toString() { + return 'VotingDelegationRecovery(bundleIndex: $bundleIndex, phase: $phase, workflowPhase: $workflowPhase, txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationRecoveryCopyWith<$Res> { + factory $VotingDelegationRecoveryCopyWith(VotingDelegationRecovery value, + $Res Function(VotingDelegationRecovery) _then) = + _$VotingDelegationRecoveryCopyWithImpl; + @useResult + $Res call( + {int bundleIndex, + String phase, + String workflowPhase, + String? txHash, + int? vanLeafPosition}); +} + +/// @nodoc +class _$VotingDelegationRecoveryCopyWithImpl<$Res> + implements $VotingDelegationRecoveryCopyWith<$Res> { + _$VotingDelegationRecoveryCopyWithImpl(this._self, this._then); + + final VotingDelegationRecovery _self; + final $Res Function(VotingDelegationRecovery) _then; + + /// Create a copy of VotingDelegationRecovery + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? phase = null, + Object? workflowPhase = null, + Object? txHash = freezed, + Object? vanLeafPosition = freezed, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + workflowPhase: null == workflowPhase + ? _self.workflowPhase + : workflowPhase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + vanLeafPosition: freezed == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationRecovery]. +extension VotingDelegationRecoveryPatterns on VotingDelegationRecovery { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationRecovery value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationRecovery value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationRecovery value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(int bundleIndex, String phase, String workflowPhase, + String? txHash, int? vanLeafPosition)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery() when $default != null: + return $default(_that.bundleIndex, _that.phase, _that.workflowPhase, + _that.txHash, _that.vanLeafPosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(int bundleIndex, String phase, String workflowPhase, + String? txHash, int? vanLeafPosition) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery(): + return $default(_that.bundleIndex, _that.phase, _that.workflowPhase, + _that.txHash, _that.vanLeafPosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(int bundleIndex, String phase, String workflowPhase, + String? txHash, int? vanLeafPosition)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationRecovery() when $default != null: + return $default(_that.bundleIndex, _that.phase, _that.workflowPhase, + _that.txHash, _that.vanLeafPosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationRecovery implements VotingDelegationRecovery { + const _VotingDelegationRecovery( + {required this.bundleIndex, + required this.phase, + required this.workflowPhase, + this.txHash, + this.vanLeafPosition}); + + @override + final int bundleIndex; + @override + final String phase; + @override + final String workflowPhase; + @override + final String? txHash; + @override + final int? vanLeafPosition; + + /// Create a copy of VotingDelegationRecovery + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationRecoveryCopyWith<_VotingDelegationRecovery> get copyWith => + __$VotingDelegationRecoveryCopyWithImpl<_VotingDelegationRecovery>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationRecovery && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.workflowPhase, workflowPhase) || + other.workflowPhase == workflowPhase) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash( + runtimeType, bundleIndex, phase, workflowPhase, txHash, vanLeafPosition); + + @override + String toString() { + return 'VotingDelegationRecovery(bundleIndex: $bundleIndex, phase: $phase, workflowPhase: $workflowPhase, txHash: $txHash, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationRecoveryCopyWith<$Res> + implements $VotingDelegationRecoveryCopyWith<$Res> { + factory _$VotingDelegationRecoveryCopyWith(_VotingDelegationRecovery value, + $Res Function(_VotingDelegationRecovery) _then) = + __$VotingDelegationRecoveryCopyWithImpl; + @override + @useResult + $Res call( + {int bundleIndex, + String phase, + String workflowPhase, + String? txHash, + int? vanLeafPosition}); +} + +/// @nodoc +class __$VotingDelegationRecoveryCopyWithImpl<$Res> + implements _$VotingDelegationRecoveryCopyWith<$Res> { + __$VotingDelegationRecoveryCopyWithImpl(this._self, this._then); + + final _VotingDelegationRecovery _self; + final $Res Function(_VotingDelegationRecovery) _then; + + /// Create a copy of VotingDelegationRecovery + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? bundleIndex = null, + Object? phase = null, + Object? workflowPhase = null, + Object? txHash = freezed, + Object? vanLeafPosition = freezed, + }) { + return _then(_VotingDelegationRecovery( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + workflowPhase: null == workflowPhase + ? _self.workflowPhase + : workflowPhase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + vanLeafPosition: freezed == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +mixin _$VotingDelegationSetup { + Uint8List get pcztBytes; + Uint8List get pcztSighash; + Uint8List get rk; + int get actionIndex; + Uint8List get actionBytes; + Uint8List get tx1Effects; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationSetupCopyWith get copyWith => + _$VotingDelegationSetupCopyWithImpl( + this as VotingDelegationSetup, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationSetup && + const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && + const DeepCollectionEquality() + .equals(other.pcztSighash, pcztSighash) && + const DeepCollectionEquality().equals(other.rk, rk) && + (identical(other.actionIndex, actionIndex) || + other.actionIndex == actionIndex) && + const DeepCollectionEquality() + .equals(other.actionBytes, actionBytes) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(pcztBytes), + const DeepCollectionEquality().hash(pcztSighash), + const DeepCollectionEquality().hash(rk), + actionIndex, + const DeepCollectionEquality().hash(actionBytes), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationSetupCopyWith<$Res> { + factory $VotingDelegationSetupCopyWith(VotingDelegationSetup value, + $Res Function(VotingDelegationSetup) _then) = + _$VotingDelegationSetupCopyWithImpl; + @useResult + $Res call( + {Uint8List pcztBytes, + Uint8List pcztSighash, + Uint8List rk, + int actionIndex, + Uint8List actionBytes, + Uint8List tx1Effects}); +} + +/// @nodoc +class _$VotingDelegationSetupCopyWithImpl<$Res> + implements $VotingDelegationSetupCopyWith<$Res> { + _$VotingDelegationSetupCopyWithImpl(this._self, this._then); + + final VotingDelegationSetup _self; + final $Res Function(VotingDelegationSetup) _then; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pcztBytes = null, + Object? pcztSighash = null, + Object? rk = null, + Object? actionIndex = null, + Object? actionBytes = null, + Object? tx1Effects = null, + }) { + return _then(_self.copyWith( + pcztBytes: null == pcztBytes + ? _self.pcztBytes + : pcztBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + pcztSighash: null == pcztSighash + ? _self.pcztSighash + : pcztSighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + actionIndex: null == actionIndex + ? _self.actionIndex + : actionIndex // ignore: cast_nullable_to_non_nullable + as int, + actionBytes: null == actionBytes + ? _self.actionBytes + : actionBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationSetup]. +extension VotingDelegationSetupPatterns on VotingDelegationSetup { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationSetup value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationSetup value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationSetup value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup(): + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(Uint8List pcztBytes, Uint8List pcztSighash, Uint8List rk, + int actionIndex, Uint8List actionBytes, Uint8List tx1Effects)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSetup() when $default != null: + return $default(_that.pcztBytes, _that.pcztSighash, _that.rk, + _that.actionIndex, _that.actionBytes, _that.tx1Effects); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationSetup implements VotingDelegationSetup { + const _VotingDelegationSetup( + {required this.pcztBytes, + required this.pcztSighash, + required this.rk, + required this.actionIndex, + required this.actionBytes, + required this.tx1Effects}); + + @override + final Uint8List pcztBytes; + @override + final Uint8List pcztSighash; + @override + final Uint8List rk; + @override + final int actionIndex; + @override + final Uint8List actionBytes; + @override + final Uint8List tx1Effects; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationSetupCopyWith<_VotingDelegationSetup> get copyWith => + __$VotingDelegationSetupCopyWithImpl<_VotingDelegationSetup>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationSetup && + const DeepCollectionEquality().equals(other.pcztBytes, pcztBytes) && + const DeepCollectionEquality() + .equals(other.pcztSighash, pcztSighash) && + const DeepCollectionEquality().equals(other.rk, rk) && + (identical(other.actionIndex, actionIndex) || + other.actionIndex == actionIndex) && + const DeepCollectionEquality() + .equals(other.actionBytes, actionBytes) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(pcztBytes), + const DeepCollectionEquality().hash(pcztSighash), + const DeepCollectionEquality().hash(rk), + actionIndex, + const DeepCollectionEquality().hash(actionBytes), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSetup(pcztBytes: $pcztBytes, pcztSighash: $pcztSighash, rk: $rk, actionIndex: $actionIndex, actionBytes: $actionBytes, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationSetupCopyWith<$Res> + implements $VotingDelegationSetupCopyWith<$Res> { + factory _$VotingDelegationSetupCopyWith(_VotingDelegationSetup value, + $Res Function(_VotingDelegationSetup) _then) = + __$VotingDelegationSetupCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List pcztBytes, + Uint8List pcztSighash, + Uint8List rk, + int actionIndex, + Uint8List actionBytes, + Uint8List tx1Effects}); +} + +/// @nodoc +class __$VotingDelegationSetupCopyWithImpl<$Res> + implements _$VotingDelegationSetupCopyWith<$Res> { + __$VotingDelegationSetupCopyWithImpl(this._self, this._then); + + final _VotingDelegationSetup _self; + final $Res Function(_VotingDelegationSetup) _then; + + /// Create a copy of VotingDelegationSetup + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? pcztBytes = null, + Object? pcztSighash = null, + Object? rk = null, + Object? actionIndex = null, + Object? actionBytes = null, + Object? tx1Effects = null, + }) { + return _then(_VotingDelegationSetup( + pcztBytes: null == pcztBytes + ? _self.pcztBytes + : pcztBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + pcztSighash: null == pcztSighash + ? _self.pcztSighash + : pcztSighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + actionIndex: null == actionIndex + ? _self.actionIndex + : actionIndex // ignore: cast_nullable_to_non_nullable + as int, + actionBytes: null == actionBytes + ? _self.actionBytes + : actionBytes // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// @nodoc +mixin _$VotingDelegationStatus { + int get bundleIndex; + String get phase; + String? get txHash; + + /// Create a copy of VotingDelegationStatus + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationStatusCopyWith get copyWith => + _$VotingDelegationStatusCopyWithImpl( + this as VotingDelegationStatus, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationStatus && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.txHash, txHash) || other.txHash == txHash)); + } + + @override + int get hashCode => Object.hash(runtimeType, bundleIndex, phase, txHash); + + @override + String toString() { + return 'VotingDelegationStatus(bundleIndex: $bundleIndex, phase: $phase, txHash: $txHash)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationStatusCopyWith<$Res> { + factory $VotingDelegationStatusCopyWith(VotingDelegationStatus value, + $Res Function(VotingDelegationStatus) _then) = + _$VotingDelegationStatusCopyWithImpl; + @useResult + $Res call({int bundleIndex, String phase, String? txHash}); +} + +/// @nodoc +class _$VotingDelegationStatusCopyWithImpl<$Res> + implements $VotingDelegationStatusCopyWith<$Res> { + _$VotingDelegationStatusCopyWithImpl(this._self, this._then); + + final VotingDelegationStatus _self; + final $Res Function(VotingDelegationStatus) _then; + + /// Create a copy of VotingDelegationStatus + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? phase = null, + Object? txHash = freezed, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationStatus]. +extension VotingDelegationStatusPatterns on VotingDelegationStatus { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationStatus value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationStatus value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationStatus value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(int bundleIndex, String phase, String? txHash)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus() when $default != null: + return $default(_that.bundleIndex, _that.phase, _that.txHash); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(int bundleIndex, String phase, String? txHash) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus(): + return $default(_that.bundleIndex, _that.phase, _that.txHash); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(int bundleIndex, String phase, String? txHash)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationStatus() when $default != null: + return $default(_that.bundleIndex, _that.phase, _that.txHash); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationStatus implements VotingDelegationStatus { + const _VotingDelegationStatus( + {required this.bundleIndex, required this.phase, this.txHash}); + + @override + final int bundleIndex; + @override + final String phase; + @override + final String? txHash; + + /// Create a copy of VotingDelegationStatus + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationStatusCopyWith<_VotingDelegationStatus> get copyWith => + __$VotingDelegationStatusCopyWithImpl<_VotingDelegationStatus>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationStatus && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.txHash, txHash) || other.txHash == txHash)); + } + + @override + int get hashCode => Object.hash(runtimeType, bundleIndex, phase, txHash); + + @override + String toString() { + return 'VotingDelegationStatus(bundleIndex: $bundleIndex, phase: $phase, txHash: $txHash)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationStatusCopyWith<$Res> + implements $VotingDelegationStatusCopyWith<$Res> { + factory _$VotingDelegationStatusCopyWith(_VotingDelegationStatus value, + $Res Function(_VotingDelegationStatus) _then) = + __$VotingDelegationStatusCopyWithImpl; + @override + @useResult + $Res call({int bundleIndex, String phase, String? txHash}); +} + +/// @nodoc +class __$VotingDelegationStatusCopyWithImpl<$Res> + implements _$VotingDelegationStatusCopyWith<$Res> { + __$VotingDelegationStatusCopyWithImpl(this._self, this._then); + + final _VotingDelegationStatus _self; + final $Res Function(_VotingDelegationStatus) _then; + + /// Create a copy of VotingDelegationStatus + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? bundleIndex = null, + Object? phase = null, + Object? txHash = freezed, + }) { + return _then(_VotingDelegationStatus( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +mixin _$VotingDelegationSubmission { + Uint8List get proof; + Uint8List get rk; + Uint8List get nfSigned; + Uint8List get cmxNew; + Uint8List get govComm; + List get govNullifiers; + Uint8List get alpha; + String get voteRoundId; + Uint8List get spendAuthSig; + Uint8List get sighash; + Uint8List get tx1Effects; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingDelegationSubmissionCopyWith + get copyWith => + _$VotingDelegationSubmissionCopyWithImpl( + this as VotingDelegationSubmission, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingDelegationSubmission && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rk, rk) && + const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && + const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && + const DeepCollectionEquality().equals(other.govComm, govComm) && + const DeepCollectionEquality() + .equals(other.govNullifiers, govNullifiers) && + const DeepCollectionEquality().equals(other.alpha, alpha) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.spendAuthSig, spendAuthSig) && + const DeepCollectionEquality().equals(other.sighash, sighash) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rk), + const DeepCollectionEquality().hash(nfSigned), + const DeepCollectionEquality().hash(cmxNew), + const DeepCollectionEquality().hash(govComm), + const DeepCollectionEquality().hash(govNullifiers), + const DeepCollectionEquality().hash(alpha), + voteRoundId, + const DeepCollectionEquality().hash(spendAuthSig), + const DeepCollectionEquality().hash(sighash), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class $VotingDelegationSubmissionCopyWith<$Res> { + factory $VotingDelegationSubmissionCopyWith(VotingDelegationSubmission value, + $Res Function(VotingDelegationSubmission) _then) = + _$VotingDelegationSubmissionCopyWithImpl; + @useResult + $Res call( + {Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects}); +} + +/// @nodoc +class _$VotingDelegationSubmissionCopyWithImpl<$Res> + implements $VotingDelegationSubmissionCopyWith<$Res> { + _$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); + + final VotingDelegationSubmission _self; + final $Res Function(VotingDelegationSubmission) _then; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proof = null, + Object? rk = null, + Object? nfSigned = null, + Object? cmxNew = null, + Object? govComm = null, + Object? govNullifiers = null, + Object? alpha = null, + Object? voteRoundId = null, + Object? spendAuthSig = null, + Object? sighash = null, + Object? tx1Effects = null, + }) { + return _then(_self.copyWith( + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + nfSigned: null == nfSigned + ? _self.nfSigned + : nfSigned // ignore: cast_nullable_to_non_nullable + as Uint8List, + cmxNew: null == cmxNew + ? _self.cmxNew + : cmxNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + govComm: null == govComm + ? _self.govComm + : govComm // ignore: cast_nullable_to_non_nullable + as Uint8List, + govNullifiers: null == govNullifiers + ? _self.govNullifiers + : govNullifiers // ignore: cast_nullable_to_non_nullable + as List, + alpha: null == alpha + ? _self.alpha + : alpha // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + spendAuthSig: null == spendAuthSig + ? _self.spendAuthSig + : spendAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + sighash: null == sighash + ? _self.sighash + : sighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingDelegationSubmission]. +extension VotingDelegationSubmissionPatterns on VotingDelegationSubmission { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingDelegationSubmission value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingDelegationSubmission value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingDelegationSubmission value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission(): + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingDelegationSubmission() when $default != null: + return $default( + _that.proof, + _that.rk, + _that.nfSigned, + _that.cmxNew, + _that.govComm, + _that.govNullifiers, + _that.alpha, + _that.voteRoundId, + _that.spendAuthSig, + _that.sighash, + _that.tx1Effects); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingDelegationSubmission implements VotingDelegationSubmission { + const _VotingDelegationSubmission( + {required this.proof, + required this.rk, + required this.nfSigned, + required this.cmxNew, + required this.govComm, + required final List govNullifiers, + required this.alpha, + required this.voteRoundId, + required this.spendAuthSig, + required this.sighash, + required this.tx1Effects}) + : _govNullifiers = govNullifiers; + + @override + final Uint8List proof; + @override + final Uint8List rk; + @override + final Uint8List nfSigned; + @override + final Uint8List cmxNew; + @override + final Uint8List govComm; + final List _govNullifiers; + @override + List get govNullifiers { + if (_govNullifiers is EqualUnmodifiableListView) return _govNullifiers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_govNullifiers); + } + + @override + final Uint8List alpha; + @override + final String voteRoundId; + @override + final Uint8List spendAuthSig; + @override + final Uint8List sighash; + @override + final Uint8List tx1Effects; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingDelegationSubmissionCopyWith<_VotingDelegationSubmission> + get copyWith => __$VotingDelegationSubmissionCopyWithImpl< + _VotingDelegationSubmission>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingDelegationSubmission && + const DeepCollectionEquality().equals(other.proof, proof) && + const DeepCollectionEquality().equals(other.rk, rk) && + const DeepCollectionEquality().equals(other.nfSigned, nfSigned) && + const DeepCollectionEquality().equals(other.cmxNew, cmxNew) && + const DeepCollectionEquality().equals(other.govComm, govComm) && + const DeepCollectionEquality() + .equals(other._govNullifiers, _govNullifiers) && + const DeepCollectionEquality().equals(other.alpha, alpha) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.spendAuthSig, spendAuthSig) && + const DeepCollectionEquality().equals(other.sighash, sighash) && + const DeepCollectionEquality() + .equals(other.tx1Effects, tx1Effects)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(proof), + const DeepCollectionEquality().hash(rk), + const DeepCollectionEquality().hash(nfSigned), + const DeepCollectionEquality().hash(cmxNew), + const DeepCollectionEquality().hash(govComm), + const DeepCollectionEquality().hash(_govNullifiers), + const DeepCollectionEquality().hash(alpha), + voteRoundId, + const DeepCollectionEquality().hash(spendAuthSig), + const DeepCollectionEquality().hash(sighash), + const DeepCollectionEquality().hash(tx1Effects)); + + @override + String toString() { + return 'VotingDelegationSubmission(proof: $proof, rk: $rk, nfSigned: $nfSigned, cmxNew: $cmxNew, govComm: $govComm, govNullifiers: $govNullifiers, alpha: $alpha, voteRoundId: $voteRoundId, spendAuthSig: $spendAuthSig, sighash: $sighash, tx1Effects: $tx1Effects)'; + } +} + +/// @nodoc +abstract mixin class _$VotingDelegationSubmissionCopyWith<$Res> + implements $VotingDelegationSubmissionCopyWith<$Res> { + factory _$VotingDelegationSubmissionCopyWith( + _VotingDelegationSubmission value, + $Res Function(_VotingDelegationSubmission) _then) = + __$VotingDelegationSubmissionCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List proof, + Uint8List rk, + Uint8List nfSigned, + Uint8List cmxNew, + Uint8List govComm, + List govNullifiers, + Uint8List alpha, + String voteRoundId, + Uint8List spendAuthSig, + Uint8List sighash, + Uint8List tx1Effects}); +} + +/// @nodoc +class __$VotingDelegationSubmissionCopyWithImpl<$Res> + implements _$VotingDelegationSubmissionCopyWith<$Res> { + __$VotingDelegationSubmissionCopyWithImpl(this._self, this._then); + + final _VotingDelegationSubmission _self; + final $Res Function(_VotingDelegationSubmission) _then; + + /// Create a copy of VotingDelegationSubmission + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proof = null, + Object? rk = null, + Object? nfSigned = null, + Object? cmxNew = null, + Object? govComm = null, + Object? govNullifiers = null, + Object? alpha = null, + Object? voteRoundId = null, + Object? spendAuthSig = null, + Object? sighash = null, + Object? tx1Effects = null, + }) { + return _then(_VotingDelegationSubmission( + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + rk: null == rk + ? _self.rk + : rk // ignore: cast_nullable_to_non_nullable + as Uint8List, + nfSigned: null == nfSigned + ? _self.nfSigned + : nfSigned // ignore: cast_nullable_to_non_nullable + as Uint8List, + cmxNew: null == cmxNew + ? _self.cmxNew + : cmxNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + govComm: null == govComm + ? _self.govComm + : govComm // ignore: cast_nullable_to_non_nullable + as Uint8List, + govNullifiers: null == govNullifiers + ? _self._govNullifiers + : govNullifiers // ignore: cast_nullable_to_non_nullable + as List, + alpha: null == alpha + ? _self.alpha + : alpha // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + spendAuthSig: null == spendAuthSig + ? _self.spendAuthSig + : spendAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + sighash: null == sighash + ? _self.sighash + : sighash // ignore: cast_nullable_to_non_nullable + as Uint8List, + tx1Effects: null == tx1Effects + ? _self.tx1Effects + : tx1Effects // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } +} + +/// @nodoc +mixin _$VotingEncryptedShare { + Uint8List get c1; + Uint8List get c2; + int get shareIndex; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith get copyWith => + _$VotingEncryptedShareCopyWithImpl( + this as VotingEncryptedShare, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingEncryptedShare && + const DeepCollectionEquality().equals(other.c1, c1) && + const DeepCollectionEquality().equals(other.c2, c2) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(c1), + const DeepCollectionEquality().hash(c2), + shareIndex); + + @override + String toString() { + return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingEncryptedShareCopyWith<$Res> { + factory $VotingEncryptedShareCopyWith(VotingEncryptedShare value, + $Res Function(VotingEncryptedShare) _then) = + _$VotingEncryptedShareCopyWithImpl; + @useResult + $Res call({Uint8List c1, Uint8List c2, int shareIndex}); +} + +/// @nodoc +class _$VotingEncryptedShareCopyWithImpl<$Res> + implements $VotingEncryptedShareCopyWith<$Res> { + _$VotingEncryptedShareCopyWithImpl(this._self, this._then); + + final VotingEncryptedShare _self; + final $Res Function(VotingEncryptedShare) _then; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? c1 = null, + Object? c2 = null, + Object? shareIndex = null, + }) { + return _then(_self.copyWith( + c1: null == c1 + ? _self.c1 + : c1 // ignore: cast_nullable_to_non_nullable + as Uint8List, + c2: null == c2 + ? _self.c2 + : c2 // ignore: cast_nullable_to_non_nullable + as Uint8List, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingEncryptedShare]. +extension VotingEncryptedSharePatterns on VotingEncryptedShare { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingEncryptedShare value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingEncryptedShare value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingEncryptedShare value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that.c1, _that.c2, _that.shareIndex); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(Uint8List c1, Uint8List c2, int shareIndex) $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare(): + return $default(_that.c1, _that.c2, _that.shareIndex); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(Uint8List c1, Uint8List c2, int shareIndex)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingEncryptedShare() when $default != null: + return $default(_that.c1, _that.c2, _that.shareIndex); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingEncryptedShare implements VotingEncryptedShare { + const _VotingEncryptedShare( + {required this.c1, required this.c2, required this.shareIndex}); + + @override + final Uint8List c1; + @override + final Uint8List c2; + @override + final int shareIndex; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingEncryptedShareCopyWith<_VotingEncryptedShare> get copyWith => + __$VotingEncryptedShareCopyWithImpl<_VotingEncryptedShare>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingEncryptedShare && + const DeepCollectionEquality().equals(other.c1, c1) && + const DeepCollectionEquality().equals(other.c2, c2) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(c1), + const DeepCollectionEquality().hash(c2), + shareIndex); + + @override + String toString() { + return 'VotingEncryptedShare(c1: $c1, c2: $c2, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class _$VotingEncryptedShareCopyWith<$Res> + implements $VotingEncryptedShareCopyWith<$Res> { + factory _$VotingEncryptedShareCopyWith(_VotingEncryptedShare value, + $Res Function(_VotingEncryptedShare) _then) = + __$VotingEncryptedShareCopyWithImpl; + @override + @useResult + $Res call({Uint8List c1, Uint8List c2, int shareIndex}); +} + +/// @nodoc +class __$VotingEncryptedShareCopyWithImpl<$Res> + implements _$VotingEncryptedShareCopyWith<$Res> { + __$VotingEncryptedShareCopyWithImpl(this._self, this._then); + + final _VotingEncryptedShare _self; + final $Res Function(_VotingEncryptedShare) _then; + + /// Create a copy of VotingEncryptedShare + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? c1 = null, + Object? c2 = null, + Object? shareIndex = null, + }) { + return _then(_VotingEncryptedShare( + c1: null == c1 + ? _self.c1 + : c1 // ignore: cast_nullable_to_non_nullable + as Uint8List, + c2: null == c2 + ? _self.c2 + : c2 // ignore: cast_nullable_to_non_nullable + as Uint8List, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingNextStep { + String get kind; + int get bundleIndex; + int get proposalId; + int get choice; + int get shareIndex; + + /// Create a copy of VotingNextStep + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingNextStepCopyWith get copyWith => + _$VotingNextStepCopyWithImpl( + this as VotingNextStep, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingNextStep && + (identical(other.kind, kind) || other.kind == kind) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, kind, bundleIndex, proposalId, choice, shareIndex); + + @override + String toString() { + return 'VotingNextStep(kind: $kind, bundleIndex: $bundleIndex, proposalId: $proposalId, choice: $choice, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingNextStepCopyWith<$Res> { + factory $VotingNextStepCopyWith( + VotingNextStep value, $Res Function(VotingNextStep) _then) = + _$VotingNextStepCopyWithImpl; + @useResult + $Res call( + {String kind, + int bundleIndex, + int proposalId, + int choice, + int shareIndex}); +} + +/// @nodoc +class _$VotingNextStepCopyWithImpl<$Res> + implements $VotingNextStepCopyWith<$Res> { + _$VotingNextStepCopyWithImpl(this._self, this._then); + + final VotingNextStep _self; + final $Res Function(VotingNextStep) _then; + + /// Create a copy of VotingNextStep + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? kind = null, + Object? bundleIndex = null, + Object? proposalId = null, + Object? choice = null, + Object? shareIndex = null, + }) { + return _then(_self.copyWith( + kind: null == kind + ? _self.kind + : kind // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingNextStep]. +extension VotingNextStepPatterns on VotingNextStep { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingNextStep value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingNextStep() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingNextStep value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingNextStep(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingNextStep value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingNextStep() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String kind, int bundleIndex, int proposalId, int choice, + int shareIndex)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingNextStep() when $default != null: + return $default(_that.kind, _that.bundleIndex, _that.proposalId, + _that.choice, _that.shareIndex); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String kind, int bundleIndex, int proposalId, int choice, + int shareIndex) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingNextStep(): + return $default(_that.kind, _that.bundleIndex, _that.proposalId, + _that.choice, _that.shareIndex); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String kind, int bundleIndex, int proposalId, int choice, + int shareIndex)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingNextStep() when $default != null: + return $default(_that.kind, _that.bundleIndex, _that.proposalId, + _that.choice, _that.shareIndex); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingNextStep implements VotingNextStep { + const _VotingNextStep( + {required this.kind, + required this.bundleIndex, + required this.proposalId, + required this.choice, + required this.shareIndex}); + + @override + final String kind; + @override + final int bundleIndex; + @override + final int proposalId; + @override + final int choice; + @override + final int shareIndex; + + /// Create a copy of VotingNextStep + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingNextStepCopyWith<_VotingNextStep> get copyWith => + __$VotingNextStepCopyWithImpl<_VotingNextStep>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingNextStep && + (identical(other.kind, kind) || other.kind == kind) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex)); + } + + @override + int get hashCode => Object.hash( + runtimeType, kind, bundleIndex, proposalId, choice, shareIndex); + + @override + String toString() { + return 'VotingNextStep(kind: $kind, bundleIndex: $bundleIndex, proposalId: $proposalId, choice: $choice, shareIndex: $shareIndex)'; + } +} + +/// @nodoc +abstract mixin class _$VotingNextStepCopyWith<$Res> + implements $VotingNextStepCopyWith<$Res> { + factory _$VotingNextStepCopyWith( + _VotingNextStep value, $Res Function(_VotingNextStep) _then) = + __$VotingNextStepCopyWithImpl; + @override + @useResult + $Res call( + {String kind, + int bundleIndex, + int proposalId, + int choice, + int shareIndex}); +} + +/// @nodoc +class __$VotingNextStepCopyWithImpl<$Res> + implements _$VotingNextStepCopyWith<$Res> { + __$VotingNextStepCopyWithImpl(this._self, this._then); + + final _VotingNextStep _self; + final $Res Function(_VotingNextStep) _then; + + /// Create a copy of VotingNextStep + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? kind = null, + Object? bundleIndex = null, + Object? proposalId = null, + Object? choice = null, + Object? shareIndex = null, + }) { + return _then(_VotingNextStep( + kind: null == kind + ? _self.kind + : kind // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingPirLayout { + int get pirDepth; + int get tier0Layers; + int get tier1Layers; + int get polyLen; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingPirLayoutCopyWith get copyWith => + _$VotingPirLayoutCopyWithImpl( + this as VotingPirLayout, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingPirLayout && + (identical(other.pirDepth, pirDepth) || + other.pirDepth == pirDepth) && + (identical(other.tier0Layers, tier0Layers) || + other.tier0Layers == tier0Layers) && + (identical(other.tier1Layers, tier1Layers) || + other.tier1Layers == tier1Layers) && + (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + } + + @override + int get hashCode => + Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + + @override + String toString() { + return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + } +} + +/// @nodoc +abstract mixin class $VotingPirLayoutCopyWith<$Res> { + factory $VotingPirLayoutCopyWith( + VotingPirLayout value, $Res Function(VotingPirLayout) _then) = + _$VotingPirLayoutCopyWithImpl; + @useResult + $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); +} + +/// @nodoc +class _$VotingPirLayoutCopyWithImpl<$Res> + implements $VotingPirLayoutCopyWith<$Res> { + _$VotingPirLayoutCopyWithImpl(this._self, this._then); + + final VotingPirLayout _self; + final $Res Function(VotingPirLayout) _then; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pirDepth = null, + Object? tier0Layers = null, + Object? tier1Layers = null, + Object? polyLen = null, + }) { + return _then(_self.copyWith( + pirDepth: null == pirDepth + ? _self.pirDepth + : pirDepth // ignore: cast_nullable_to_non_nullable + as int, + tier0Layers: null == tier0Layers + ? _self.tier0Layers + : tier0Layers // ignore: cast_nullable_to_non_nullable + as int, + tier1Layers: null == tier1Layers + ? _self.tier1Layers + : tier1Layers // ignore: cast_nullable_to_non_nullable + as int, + polyLen: null == polyLen + ? _self.polyLen + : polyLen // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingPirLayout]. +extension VotingPirLayoutPatterns on VotingPirLayout { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingPirLayout value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingPirLayout value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingPirLayout value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout(): + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int pirDepth, int tier0Layers, int tier1Layers, int polyLen)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPirLayout() when $default != null: + return $default(_that.pirDepth, _that.tier0Layers, _that.tier1Layers, + _that.polyLen); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingPirLayout implements VotingPirLayout { + const _VotingPirLayout( + {required this.pirDepth, + required this.tier0Layers, + required this.tier1Layers, + required this.polyLen}); + + @override + final int pirDepth; + @override + final int tier0Layers; + @override + final int tier1Layers; + @override + final int polyLen; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingPirLayoutCopyWith<_VotingPirLayout> get copyWith => + __$VotingPirLayoutCopyWithImpl<_VotingPirLayout>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingPirLayout && + (identical(other.pirDepth, pirDepth) || + other.pirDepth == pirDepth) && + (identical(other.tier0Layers, tier0Layers) || + other.tier0Layers == tier0Layers) && + (identical(other.tier1Layers, tier1Layers) || + other.tier1Layers == tier1Layers) && + (identical(other.polyLen, polyLen) || other.polyLen == polyLen)); + } + + @override + int get hashCode => + Object.hash(runtimeType, pirDepth, tier0Layers, tier1Layers, polyLen); + + @override + String toString() { + return 'VotingPirLayout(pirDepth: $pirDepth, tier0Layers: $tier0Layers, tier1Layers: $tier1Layers, polyLen: $polyLen)'; + } +} + +/// @nodoc +abstract mixin class _$VotingPirLayoutCopyWith<$Res> + implements $VotingPirLayoutCopyWith<$Res> { + factory _$VotingPirLayoutCopyWith( + _VotingPirLayout value, $Res Function(_VotingPirLayout) _then) = + __$VotingPirLayoutCopyWithImpl; + @override + @useResult + $Res call({int pirDepth, int tier0Layers, int tier1Layers, int polyLen}); +} + +/// @nodoc +class __$VotingPirLayoutCopyWithImpl<$Res> + implements _$VotingPirLayoutCopyWith<$Res> { + __$VotingPirLayoutCopyWithImpl(this._self, this._then); + + final _VotingPirLayout _self; + final $Res Function(_VotingPirLayout) _then; + + /// Create a copy of VotingPirLayout + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? pirDepth = null, + Object? tier0Layers = null, + Object? tier1Layers = null, + Object? polyLen = null, + }) { + return _then(_VotingPirLayout( + pirDepth: null == pirDepth + ? _self.pirDepth + : pirDepth // ignore: cast_nullable_to_non_nullable + as int, + tier0Layers: null == tier0Layers + ? _self.tier0Layers + : tier0Layers // ignore: cast_nullable_to_non_nullable + as int, + tier1Layers: null == tier1Layers + ? _self.tier1Layers + : tier1Layers // ignore: cast_nullable_to_non_nullable + as int, + polyLen: null == polyLen + ? _self.polyLen + : polyLen // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingPreparedInfo { + String get roundId; + int get bundleIndex; + BigInt get eligibleWeightZatoshi; + BigInt get delegatedWeightZatoshi; + String get roundName; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingPreparedInfoCopyWith get copyWith => + _$VotingPreparedInfoCopyWithImpl( + this as VotingPreparedInfo, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingPreparedInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || + other.delegatedWeightZatoshi == delegatedWeightZatoshi) && + (identical(other.roundName, roundName) || + other.roundName == roundName)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, + eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + + @override + String toString() { + return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + } +} + +/// @nodoc +abstract mixin class $VotingPreparedInfoCopyWith<$Res> { + factory $VotingPreparedInfoCopyWith( + VotingPreparedInfo value, $Res Function(VotingPreparedInfo) _then) = + _$VotingPreparedInfoCopyWithImpl; + @useResult + $Res call( + {String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName}); +} + +/// @nodoc +class _$VotingPreparedInfoCopyWithImpl<$Res> + implements $VotingPreparedInfoCopyWith<$Res> { + _$VotingPreparedInfoCopyWithImpl(this._self, this._then); + + final VotingPreparedInfo _self; + final $Res Function(VotingPreparedInfo) _then; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? eligibleWeightZatoshi = null, + Object? delegatedWeightZatoshi = null, + Object? roundName = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + eligibleWeightZatoshi: null == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + delegatedWeightZatoshi: null == delegatedWeightZatoshi + ? _self.delegatedWeightZatoshi + : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + roundName: null == roundName + ? _self.roundName + : roundName // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingPreparedInfo]. +extension VotingPreparedInfoPatterns on VotingPreparedInfo { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingPreparedInfo value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingPreparedInfo value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingPreparedInfo value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo(): + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingPreparedInfo() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.eligibleWeightZatoshi, + _that.delegatedWeightZatoshi, + _that.roundName); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingPreparedInfo implements VotingPreparedInfo { + const _VotingPreparedInfo( + {required this.roundId, + required this.bundleIndex, + required this.eligibleWeightZatoshi, + required this.delegatedWeightZatoshi, + required this.roundName}); + + @override + final String roundId; + @override + final int bundleIndex; + @override + final BigInt eligibleWeightZatoshi; + @override + final BigInt delegatedWeightZatoshi; + @override + final String roundName; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingPreparedInfoCopyWith<_VotingPreparedInfo> get copyWith => + __$VotingPreparedInfoCopyWithImpl<_VotingPreparedInfo>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingPreparedInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.delegatedWeightZatoshi, delegatedWeightZatoshi) || + other.delegatedWeightZatoshi == delegatedWeightZatoshi) && + (identical(other.roundName, roundName) || + other.roundName == roundName)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, bundleIndex, + eligibleWeightZatoshi, delegatedWeightZatoshi, roundName); + + @override + String toString() { + return 'VotingPreparedInfo(roundId: $roundId, bundleIndex: $bundleIndex, eligibleWeightZatoshi: $eligibleWeightZatoshi, delegatedWeightZatoshi: $delegatedWeightZatoshi, roundName: $roundName)'; + } +} + +/// @nodoc +abstract mixin class _$VotingPreparedInfoCopyWith<$Res> + implements $VotingPreparedInfoCopyWith<$Res> { + factory _$VotingPreparedInfoCopyWith( + _VotingPreparedInfo value, $Res Function(_VotingPreparedInfo) _then) = + __$VotingPreparedInfoCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + int bundleIndex, + BigInt eligibleWeightZatoshi, + BigInt delegatedWeightZatoshi, + String roundName}); +} + +/// @nodoc +class __$VotingPreparedInfoCopyWithImpl<$Res> + implements _$VotingPreparedInfoCopyWith<$Res> { + __$VotingPreparedInfoCopyWithImpl(this._self, this._then); + + final _VotingPreparedInfo _self; + final $Res Function(_VotingPreparedInfo) _then; + + /// Create a copy of VotingPreparedInfo + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? eligibleWeightZatoshi = null, + Object? delegatedWeightZatoshi = null, + Object? roundName = null, + }) { + return _then(_VotingPreparedInfo( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + eligibleWeightZatoshi: null == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + delegatedWeightZatoshi: null == delegatedWeightZatoshi + ? _self.delegatedWeightZatoshi + : delegatedWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt, + roundName: null == roundName + ? _self.roundName + : roundName // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingRoundInfo { + String get roundId; + String get network; + BigInt get snapshotHeight; + String? get hotkeyAddress; + BigInt? get eligibleWeightZatoshi; + int get bundleCount; + BigInt get createdAt; + + /// Create a copy of VotingRoundInfo + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingRoundInfoCopyWith get copyWith => + _$VotingRoundInfoCopyWithImpl( + this as VotingRoundInfo, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingRoundInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.network, network) || other.network == network) && + (identical(other.snapshotHeight, snapshotHeight) || + other.snapshotHeight == snapshotHeight) && + (identical(other.hotkeyAddress, hotkeyAddress) || + other.hotkeyAddress == hotkeyAddress) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.bundleCount, bundleCount) || + other.bundleCount == bundleCount) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, network, snapshotHeight, + hotkeyAddress, eligibleWeightZatoshi, bundleCount, createdAt); + + @override + String toString() { + return 'VotingRoundInfo(roundId: $roundId, network: $network, snapshotHeight: $snapshotHeight, hotkeyAddress: $hotkeyAddress, eligibleWeightZatoshi: $eligibleWeightZatoshi, bundleCount: $bundleCount, createdAt: $createdAt)'; + } +} + +/// @nodoc +abstract mixin class $VotingRoundInfoCopyWith<$Res> { + factory $VotingRoundInfoCopyWith( + VotingRoundInfo value, $Res Function(VotingRoundInfo) _then) = + _$VotingRoundInfoCopyWithImpl; + @useResult + $Res call( + {String roundId, + String network, + BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + int bundleCount, + BigInt createdAt}); +} + +/// @nodoc +class _$VotingRoundInfoCopyWithImpl<$Res> + implements $VotingRoundInfoCopyWith<$Res> { + _$VotingRoundInfoCopyWithImpl(this._self, this._then); + + final VotingRoundInfo _self; + final $Res Function(VotingRoundInfo) _then; + + /// Create a copy of VotingRoundInfo + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? network = null, + Object? snapshotHeight = null, + Object? hotkeyAddress = freezed, + Object? eligibleWeightZatoshi = freezed, + Object? bundleCount = null, + Object? createdAt = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + network: null == network + ? _self.network + : network // ignore: cast_nullable_to_non_nullable + as String, + snapshotHeight: null == snapshotHeight + ? _self.snapshotHeight + : snapshotHeight // ignore: cast_nullable_to_non_nullable + as BigInt, + hotkeyAddress: freezed == hotkeyAddress + ? _self.hotkeyAddress + : hotkeyAddress // ignore: cast_nullable_to_non_nullable + as String?, + eligibleWeightZatoshi: freezed == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt?, + bundleCount: null == bundleCount + ? _self.bundleCount + : bundleCount // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _self.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingRoundInfo]. +extension VotingRoundInfoPatterns on VotingRoundInfo { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingRoundInfo value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundInfo() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingRoundInfo value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundInfo(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingRoundInfo value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundInfo() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + String network, + BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + int bundleCount, + BigInt createdAt)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundInfo() when $default != null: + return $default( + _that.roundId, + _that.network, + _that.snapshotHeight, + _that.hotkeyAddress, + _that.eligibleWeightZatoshi, + _that.bundleCount, + _that.createdAt); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + String network, + BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + int bundleCount, + BigInt createdAt) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundInfo(): + return $default( + _that.roundId, + _that.network, + _that.snapshotHeight, + _that.hotkeyAddress, + _that.eligibleWeightZatoshi, + _that.bundleCount, + _that.createdAt); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + String network, + BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + int bundleCount, + BigInt createdAt)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundInfo() when $default != null: + return $default( + _that.roundId, + _that.network, + _that.snapshotHeight, + _that.hotkeyAddress, + _that.eligibleWeightZatoshi, + _that.bundleCount, + _that.createdAt); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingRoundInfo implements VotingRoundInfo { + const _VotingRoundInfo( + {required this.roundId, + required this.network, + required this.snapshotHeight, + this.hotkeyAddress, + this.eligibleWeightZatoshi, + required this.bundleCount, + required this.createdAt}); + + @override + final String roundId; + @override + final String network; + @override + final BigInt snapshotHeight; + @override + final String? hotkeyAddress; + @override + final BigInt? eligibleWeightZatoshi; + @override + final int bundleCount; + @override + final BigInt createdAt; + + /// Create a copy of VotingRoundInfo + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingRoundInfoCopyWith<_VotingRoundInfo> get copyWith => + __$VotingRoundInfoCopyWithImpl<_VotingRoundInfo>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingRoundInfo && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.network, network) || other.network == network) && + (identical(other.snapshotHeight, snapshotHeight) || + other.snapshotHeight == snapshotHeight) && + (identical(other.hotkeyAddress, hotkeyAddress) || + other.hotkeyAddress == hotkeyAddress) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.bundleCount, bundleCount) || + other.bundleCount == bundleCount) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, network, snapshotHeight, + hotkeyAddress, eligibleWeightZatoshi, bundleCount, createdAt); + + @override + String toString() { + return 'VotingRoundInfo(roundId: $roundId, network: $network, snapshotHeight: $snapshotHeight, hotkeyAddress: $hotkeyAddress, eligibleWeightZatoshi: $eligibleWeightZatoshi, bundleCount: $bundleCount, createdAt: $createdAt)'; + } +} + +/// @nodoc +abstract mixin class _$VotingRoundInfoCopyWith<$Res> + implements $VotingRoundInfoCopyWith<$Res> { + factory _$VotingRoundInfoCopyWith( + _VotingRoundInfo value, $Res Function(_VotingRoundInfo) _then) = + __$VotingRoundInfoCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + String network, + BigInt snapshotHeight, + String? hotkeyAddress, + BigInt? eligibleWeightZatoshi, + int bundleCount, + BigInt createdAt}); +} + +/// @nodoc +class __$VotingRoundInfoCopyWithImpl<$Res> + implements _$VotingRoundInfoCopyWith<$Res> { + __$VotingRoundInfoCopyWithImpl(this._self, this._then); + + final _VotingRoundInfo _self; + final $Res Function(_VotingRoundInfo) _then; + + /// Create a copy of VotingRoundInfo + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? network = null, + Object? snapshotHeight = null, + Object? hotkeyAddress = freezed, + Object? eligibleWeightZatoshi = freezed, + Object? bundleCount = null, + Object? createdAt = null, + }) { + return _then(_VotingRoundInfo( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + network: null == network + ? _self.network + : network // ignore: cast_nullable_to_non_nullable + as String, + snapshotHeight: null == snapshotHeight + ? _self.snapshotHeight + : snapshotHeight // ignore: cast_nullable_to_non_nullable + as BigInt, + hotkeyAddress: freezed == hotkeyAddress + ? _self.hotkeyAddress + : hotkeyAddress // ignore: cast_nullable_to_non_nullable + as String?, + eligibleWeightZatoshi: freezed == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt?, + bundleCount: null == bundleCount + ? _self.bundleCount + : bundleCount // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _self.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// @nodoc +mixin _$VotingRoundPlan { + String get roundId; + bool get pendingRecovery; + List get nextSteps; + Uint32List get openProposals; + bool get allDecided; + List get delegationStatuses; + bool get blockingRecovery; + bool get blockingShareWork; + bool get hotkeyBound; + bool get completedVoteArtifact; + bool get completedForDisplay; + VotingCompletedVoteDisplay? get completedVoteDisplay; + bool get needsDraftSetup; + String get primaryAction; + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingRoundPlanCopyWith get copyWith => + _$VotingRoundPlanCopyWithImpl( + this as VotingRoundPlan, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingRoundPlan && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.pendingRecovery, pendingRecovery) || + other.pendingRecovery == pendingRecovery) && + const DeepCollectionEquality().equals(other.nextSteps, nextSteps) && + const DeepCollectionEquality() + .equals(other.openProposals, openProposals) && + (identical(other.allDecided, allDecided) || + other.allDecided == allDecided) && + const DeepCollectionEquality() + .equals(other.delegationStatuses, delegationStatuses) && + (identical(other.blockingRecovery, blockingRecovery) || + other.blockingRecovery == blockingRecovery) && + (identical(other.blockingShareWork, blockingShareWork) || + other.blockingShareWork == blockingShareWork) && + (identical(other.hotkeyBound, hotkeyBound) || + other.hotkeyBound == hotkeyBound) && + (identical(other.completedVoteArtifact, completedVoteArtifact) || + other.completedVoteArtifact == completedVoteArtifact) && + (identical(other.completedForDisplay, completedForDisplay) || + other.completedForDisplay == completedForDisplay) && + (identical(other.completedVoteDisplay, completedVoteDisplay) || + other.completedVoteDisplay == completedVoteDisplay) && + (identical(other.needsDraftSetup, needsDraftSetup) || + other.needsDraftSetup == needsDraftSetup) && + (identical(other.primaryAction, primaryAction) || + other.primaryAction == primaryAction)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + pendingRecovery, + const DeepCollectionEquality().hash(nextSteps), + const DeepCollectionEquality().hash(openProposals), + allDecided, + const DeepCollectionEquality().hash(delegationStatuses), + blockingRecovery, + blockingShareWork, + hotkeyBound, + completedVoteArtifact, + completedForDisplay, + completedVoteDisplay, + needsDraftSetup, + primaryAction); + + @override + String toString() { + return 'VotingRoundPlan(roundId: $roundId, pendingRecovery: $pendingRecovery, nextSteps: $nextSteps, openProposals: $openProposals, allDecided: $allDecided, delegationStatuses: $delegationStatuses, blockingRecovery: $blockingRecovery, blockingShareWork: $blockingShareWork, hotkeyBound: $hotkeyBound, completedVoteArtifact: $completedVoteArtifact, completedForDisplay: $completedForDisplay, completedVoteDisplay: $completedVoteDisplay, needsDraftSetup: $needsDraftSetup, primaryAction: $primaryAction)'; + } +} + +/// @nodoc +abstract mixin class $VotingRoundPlanCopyWith<$Res> { + factory $VotingRoundPlanCopyWith( + VotingRoundPlan value, $Res Function(VotingRoundPlan) _then) = + _$VotingRoundPlanCopyWithImpl; + @useResult + $Res call( + {String roundId, + bool pendingRecovery, + List nextSteps, + Uint32List openProposals, + bool allDecided, + List delegationStatuses, + bool blockingRecovery, + bool blockingShareWork, + bool hotkeyBound, + bool completedVoteArtifact, + bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + bool needsDraftSetup, + String primaryAction}); + + $VotingCompletedVoteDisplayCopyWith<$Res>? get completedVoteDisplay; +} + +/// @nodoc +class _$VotingRoundPlanCopyWithImpl<$Res> + implements $VotingRoundPlanCopyWith<$Res> { + _$VotingRoundPlanCopyWithImpl(this._self, this._then); + + final VotingRoundPlan _self; + final $Res Function(VotingRoundPlan) _then; + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? pendingRecovery = null, + Object? nextSteps = null, + Object? openProposals = null, + Object? allDecided = null, + Object? delegationStatuses = null, + Object? blockingRecovery = null, + Object? blockingShareWork = null, + Object? hotkeyBound = null, + Object? completedVoteArtifact = null, + Object? completedForDisplay = null, + Object? completedVoteDisplay = freezed, + Object? needsDraftSetup = null, + Object? primaryAction = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + pendingRecovery: null == pendingRecovery + ? _self.pendingRecovery + : pendingRecovery // ignore: cast_nullable_to_non_nullable + as bool, + nextSteps: null == nextSteps + ? _self.nextSteps + : nextSteps // ignore: cast_nullable_to_non_nullable + as List, + openProposals: null == openProposals + ? _self.openProposals + : openProposals // ignore: cast_nullable_to_non_nullable + as Uint32List, + allDecided: null == allDecided + ? _self.allDecided + : allDecided // ignore: cast_nullable_to_non_nullable + as bool, + delegationStatuses: null == delegationStatuses + ? _self.delegationStatuses + : delegationStatuses // ignore: cast_nullable_to_non_nullable + as List, + blockingRecovery: null == blockingRecovery + ? _self.blockingRecovery + : blockingRecovery // ignore: cast_nullable_to_non_nullable + as bool, + blockingShareWork: null == blockingShareWork + ? _self.blockingShareWork + : blockingShareWork // ignore: cast_nullable_to_non_nullable + as bool, + hotkeyBound: null == hotkeyBound + ? _self.hotkeyBound + : hotkeyBound // ignore: cast_nullable_to_non_nullable + as bool, + completedVoteArtifact: null == completedVoteArtifact + ? _self.completedVoteArtifact + : completedVoteArtifact // ignore: cast_nullable_to_non_nullable + as bool, + completedForDisplay: null == completedForDisplay + ? _self.completedForDisplay + : completedForDisplay // ignore: cast_nullable_to_non_nullable + as bool, + completedVoteDisplay: freezed == completedVoteDisplay + ? _self.completedVoteDisplay + : completedVoteDisplay // ignore: cast_nullable_to_non_nullable + as VotingCompletedVoteDisplay?, + needsDraftSetup: null == needsDraftSetup + ? _self.needsDraftSetup + : needsDraftSetup // ignore: cast_nullable_to_non_nullable + as bool, + primaryAction: null == primaryAction + ? _self.primaryAction + : primaryAction // ignore: cast_nullable_to_non_nullable + as String, + )); + } + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingCompletedVoteDisplayCopyWith<$Res>? get completedVoteDisplay { + if (_self.completedVoteDisplay == null) { + return null; + } + + return $VotingCompletedVoteDisplayCopyWith<$Res>( + _self.completedVoteDisplay!, (value) { + return _then(_self.copyWith(completedVoteDisplay: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingRoundPlan]. +extension VotingRoundPlanPatterns on VotingRoundPlan { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingRoundPlan value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundPlan() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingRoundPlan value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundPlan(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingRoundPlan value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundPlan() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + bool pendingRecovery, + List nextSteps, + Uint32List openProposals, + bool allDecided, + List delegationStatuses, + bool blockingRecovery, + bool blockingShareWork, + bool hotkeyBound, + bool completedVoteArtifact, + bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + bool needsDraftSetup, + String primaryAction)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundPlan() when $default != null: + return $default( + _that.roundId, + _that.pendingRecovery, + _that.nextSteps, + _that.openProposals, + _that.allDecided, + _that.delegationStatuses, + _that.blockingRecovery, + _that.blockingShareWork, + _that.hotkeyBound, + _that.completedVoteArtifact, + _that.completedForDisplay, + _that.completedVoteDisplay, + _that.needsDraftSetup, + _that.primaryAction); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + bool pendingRecovery, + List nextSteps, + Uint32List openProposals, + bool allDecided, + List delegationStatuses, + bool blockingRecovery, + bool blockingShareWork, + bool hotkeyBound, + bool completedVoteArtifact, + bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + bool needsDraftSetup, + String primaryAction) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundPlan(): + return $default( + _that.roundId, + _that.pendingRecovery, + _that.nextSteps, + _that.openProposals, + _that.allDecided, + _that.delegationStatuses, + _that.blockingRecovery, + _that.blockingShareWork, + _that.hotkeyBound, + _that.completedVoteArtifact, + _that.completedForDisplay, + _that.completedVoteDisplay, + _that.needsDraftSetup, + _that.primaryAction); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + bool pendingRecovery, + List nextSteps, + Uint32List openProposals, + bool allDecided, + List delegationStatuses, + bool blockingRecovery, + bool blockingShareWork, + bool hotkeyBound, + bool completedVoteArtifact, + bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + bool needsDraftSetup, + String primaryAction)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundPlan() when $default != null: + return $default( + _that.roundId, + _that.pendingRecovery, + _that.nextSteps, + _that.openProposals, + _that.allDecided, + _that.delegationStatuses, + _that.blockingRecovery, + _that.blockingShareWork, + _that.hotkeyBound, + _that.completedVoteArtifact, + _that.completedForDisplay, + _that.completedVoteDisplay, + _that.needsDraftSetup, + _that.primaryAction); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingRoundPlan implements VotingRoundPlan { + const _VotingRoundPlan( + {required this.roundId, + required this.pendingRecovery, + required final List nextSteps, + required this.openProposals, + required this.allDecided, + required final List delegationStatuses, + required this.blockingRecovery, + required this.blockingShareWork, + required this.hotkeyBound, + required this.completedVoteArtifact, + required this.completedForDisplay, + this.completedVoteDisplay, + required this.needsDraftSetup, + required this.primaryAction}) + : _nextSteps = nextSteps, + _delegationStatuses = delegationStatuses; + + @override + final String roundId; + @override + final bool pendingRecovery; + final List _nextSteps; + @override + List get nextSteps { + if (_nextSteps is EqualUnmodifiableListView) return _nextSteps; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_nextSteps); + } + + @override + final Uint32List openProposals; + @override + final bool allDecided; + final List _delegationStatuses; + @override + List get delegationStatuses { + if (_delegationStatuses is EqualUnmodifiableListView) + return _delegationStatuses; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_delegationStatuses); + } + + @override + final bool blockingRecovery; + @override + final bool blockingShareWork; + @override + final bool hotkeyBound; + @override + final bool completedVoteArtifact; + @override + final bool completedForDisplay; + @override + final VotingCompletedVoteDisplay? completedVoteDisplay; + @override + final bool needsDraftSetup; + @override + final String primaryAction; + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingRoundPlanCopyWith<_VotingRoundPlan> get copyWith => + __$VotingRoundPlanCopyWithImpl<_VotingRoundPlan>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingRoundPlan && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.pendingRecovery, pendingRecovery) || + other.pendingRecovery == pendingRecovery) && + const DeepCollectionEquality() + .equals(other._nextSteps, _nextSteps) && + const DeepCollectionEquality() + .equals(other.openProposals, openProposals) && + (identical(other.allDecided, allDecided) || + other.allDecided == allDecided) && + const DeepCollectionEquality() + .equals(other._delegationStatuses, _delegationStatuses) && + (identical(other.blockingRecovery, blockingRecovery) || + other.blockingRecovery == blockingRecovery) && + (identical(other.blockingShareWork, blockingShareWork) || + other.blockingShareWork == blockingShareWork) && + (identical(other.hotkeyBound, hotkeyBound) || + other.hotkeyBound == hotkeyBound) && + (identical(other.completedVoteArtifact, completedVoteArtifact) || + other.completedVoteArtifact == completedVoteArtifact) && + (identical(other.completedForDisplay, completedForDisplay) || + other.completedForDisplay == completedForDisplay) && + (identical(other.completedVoteDisplay, completedVoteDisplay) || + other.completedVoteDisplay == completedVoteDisplay) && + (identical(other.needsDraftSetup, needsDraftSetup) || + other.needsDraftSetup == needsDraftSetup) && + (identical(other.primaryAction, primaryAction) || + other.primaryAction == primaryAction)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + pendingRecovery, + const DeepCollectionEquality().hash(_nextSteps), + const DeepCollectionEquality().hash(openProposals), + allDecided, + const DeepCollectionEquality().hash(_delegationStatuses), + blockingRecovery, + blockingShareWork, + hotkeyBound, + completedVoteArtifact, + completedForDisplay, + completedVoteDisplay, + needsDraftSetup, + primaryAction); + + @override + String toString() { + return 'VotingRoundPlan(roundId: $roundId, pendingRecovery: $pendingRecovery, nextSteps: $nextSteps, openProposals: $openProposals, allDecided: $allDecided, delegationStatuses: $delegationStatuses, blockingRecovery: $blockingRecovery, blockingShareWork: $blockingShareWork, hotkeyBound: $hotkeyBound, completedVoteArtifact: $completedVoteArtifact, completedForDisplay: $completedForDisplay, completedVoteDisplay: $completedVoteDisplay, needsDraftSetup: $needsDraftSetup, primaryAction: $primaryAction)'; + } +} + +/// @nodoc +abstract mixin class _$VotingRoundPlanCopyWith<$Res> + implements $VotingRoundPlanCopyWith<$Res> { + factory _$VotingRoundPlanCopyWith( + _VotingRoundPlan value, $Res Function(_VotingRoundPlan) _then) = + __$VotingRoundPlanCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + bool pendingRecovery, + List nextSteps, + Uint32List openProposals, + bool allDecided, + List delegationStatuses, + bool blockingRecovery, + bool blockingShareWork, + bool hotkeyBound, + bool completedVoteArtifact, + bool completedForDisplay, + VotingCompletedVoteDisplay? completedVoteDisplay, + bool needsDraftSetup, + String primaryAction}); + + @override + $VotingCompletedVoteDisplayCopyWith<$Res>? get completedVoteDisplay; +} + +/// @nodoc +class __$VotingRoundPlanCopyWithImpl<$Res> + implements _$VotingRoundPlanCopyWith<$Res> { + __$VotingRoundPlanCopyWithImpl(this._self, this._then); + + final _VotingRoundPlan _self; + final $Res Function(_VotingRoundPlan) _then; + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? pendingRecovery = null, + Object? nextSteps = null, + Object? openProposals = null, + Object? allDecided = null, + Object? delegationStatuses = null, + Object? blockingRecovery = null, + Object? blockingShareWork = null, + Object? hotkeyBound = null, + Object? completedVoteArtifact = null, + Object? completedForDisplay = null, + Object? completedVoteDisplay = freezed, + Object? needsDraftSetup = null, + Object? primaryAction = null, + }) { + return _then(_VotingRoundPlan( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + pendingRecovery: null == pendingRecovery + ? _self.pendingRecovery + : pendingRecovery // ignore: cast_nullable_to_non_nullable + as bool, + nextSteps: null == nextSteps + ? _self._nextSteps + : nextSteps // ignore: cast_nullable_to_non_nullable + as List, + openProposals: null == openProposals + ? _self.openProposals + : openProposals // ignore: cast_nullable_to_non_nullable + as Uint32List, + allDecided: null == allDecided + ? _self.allDecided + : allDecided // ignore: cast_nullable_to_non_nullable + as bool, + delegationStatuses: null == delegationStatuses + ? _self._delegationStatuses + : delegationStatuses // ignore: cast_nullable_to_non_nullable + as List, + blockingRecovery: null == blockingRecovery + ? _self.blockingRecovery + : blockingRecovery // ignore: cast_nullable_to_non_nullable + as bool, + blockingShareWork: null == blockingShareWork + ? _self.blockingShareWork + : blockingShareWork // ignore: cast_nullable_to_non_nullable + as bool, + hotkeyBound: null == hotkeyBound + ? _self.hotkeyBound + : hotkeyBound // ignore: cast_nullable_to_non_nullable + as bool, + completedVoteArtifact: null == completedVoteArtifact + ? _self.completedVoteArtifact + : completedVoteArtifact // ignore: cast_nullable_to_non_nullable + as bool, + completedForDisplay: null == completedForDisplay + ? _self.completedForDisplay + : completedForDisplay // ignore: cast_nullable_to_non_nullable + as bool, + completedVoteDisplay: freezed == completedVoteDisplay + ? _self.completedVoteDisplay + : completedVoteDisplay // ignore: cast_nullable_to_non_nullable + as VotingCompletedVoteDisplay?, + needsDraftSetup: null == needsDraftSetup + ? _self.needsDraftSetup + : needsDraftSetup // ignore: cast_nullable_to_non_nullable + as bool, + primaryAction: null == primaryAction + ? _self.primaryAction + : primaryAction // ignore: cast_nullable_to_non_nullable + as String, + )); + } + + /// Create a copy of VotingRoundPlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingCompletedVoteDisplayCopyWith<$Res>? get completedVoteDisplay { + if (_self.completedVoteDisplay == null) { + return null; + } + + return $VotingCompletedVoteDisplayCopyWith<$Res>( + _self.completedVoteDisplay!, (value) { + return _then(_self.copyWith(completedVoteDisplay: value)); + }); + } +} + +/// @nodoc +mixin _$VotingRoundRecovery { + String get roundId; + int get bundleCount; + List get delegation; + List get votes; + List get shares; + List get shareDelegations; + List get unconfirmedShareDelegations; + + /// Create a copy of VotingRoundRecovery + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingRoundRecoveryCopyWith get copyWith => + _$VotingRoundRecoveryCopyWithImpl( + this as VotingRoundRecovery, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingRoundRecovery && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleCount, bundleCount) || + other.bundleCount == bundleCount) && + const DeepCollectionEquality() + .equals(other.delegation, delegation) && + const DeepCollectionEquality().equals(other.votes, votes) && + const DeepCollectionEquality().equals(other.shares, shares) && + const DeepCollectionEquality() + .equals(other.shareDelegations, shareDelegations) && + const DeepCollectionEquality().equals( + other.unconfirmedShareDelegations, + unconfirmedShareDelegations)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + bundleCount, + const DeepCollectionEquality().hash(delegation), + const DeepCollectionEquality().hash(votes), + const DeepCollectionEquality().hash(shares), + const DeepCollectionEquality().hash(shareDelegations), + const DeepCollectionEquality().hash(unconfirmedShareDelegations)); + + @override + String toString() { + return 'VotingRoundRecovery(roundId: $roundId, bundleCount: $bundleCount, delegation: $delegation, votes: $votes, shares: $shares, shareDelegations: $shareDelegations, unconfirmedShareDelegations: $unconfirmedShareDelegations)'; + } +} + +/// @nodoc +abstract mixin class $VotingRoundRecoveryCopyWith<$Res> { + factory $VotingRoundRecoveryCopyWith( + VotingRoundRecovery value, $Res Function(VotingRoundRecovery) _then) = + _$VotingRoundRecoveryCopyWithImpl; + @useResult + $Res call( + {String roundId, + int bundleCount, + List delegation, + List votes, + List shares, + List shareDelegations, + List unconfirmedShareDelegations}); +} + +/// @nodoc +class _$VotingRoundRecoveryCopyWithImpl<$Res> + implements $VotingRoundRecoveryCopyWith<$Res> { + _$VotingRoundRecoveryCopyWithImpl(this._self, this._then); + + final VotingRoundRecovery _self; + final $Res Function(VotingRoundRecovery) _then; + + /// Create a copy of VotingRoundRecovery + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? bundleCount = null, + Object? delegation = null, + Object? votes = null, + Object? shares = null, + Object? shareDelegations = null, + Object? unconfirmedShareDelegations = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleCount: null == bundleCount + ? _self.bundleCount + : bundleCount // ignore: cast_nullable_to_non_nullable + as int, + delegation: null == delegation + ? _self.delegation + : delegation // ignore: cast_nullable_to_non_nullable + as List, + votes: null == votes + ? _self.votes + : votes // ignore: cast_nullable_to_non_nullable + as List, + shares: null == shares + ? _self.shares + : shares // ignore: cast_nullable_to_non_nullable + as List, + shareDelegations: null == shareDelegations + ? _self.shareDelegations + : shareDelegations // ignore: cast_nullable_to_non_nullable + as List, + unconfirmedShareDelegations: null == unconfirmedShareDelegations + ? _self.unconfirmedShareDelegations + : unconfirmedShareDelegations // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingRoundRecovery]. +extension VotingRoundRecoveryPatterns on VotingRoundRecovery { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingRoundRecovery value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingRoundRecovery value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingRoundRecovery value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + int bundleCount, + List delegation, + List votes, + List shares, + List shareDelegations, + List unconfirmedShareDelegations)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery() when $default != null: + return $default( + _that.roundId, + _that.bundleCount, + _that.delegation, + _that.votes, + _that.shares, + _that.shareDelegations, + _that.unconfirmedShareDelegations); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + int bundleCount, + List delegation, + List votes, + List shares, + List shareDelegations, + List unconfirmedShareDelegations) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery(): + return $default( + _that.roundId, + _that.bundleCount, + _that.delegation, + _that.votes, + _that.shares, + _that.shareDelegations, + _that.unconfirmedShareDelegations); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + int bundleCount, + List delegation, + List votes, + List shares, + List shareDelegations, + List unconfirmedShareDelegations)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundRecovery() when $default != null: + return $default( + _that.roundId, + _that.bundleCount, + _that.delegation, + _that.votes, + _that.shares, + _that.shareDelegations, + _that.unconfirmedShareDelegations); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingRoundRecovery implements VotingRoundRecovery { + const _VotingRoundRecovery( + {required this.roundId, + required this.bundleCount, + required final List delegation, + required final List votes, + required final List shares, + required final List shareDelegations, + required final List + unconfirmedShareDelegations}) + : _delegation = delegation, + _votes = votes, + _shares = shares, + _shareDelegations = shareDelegations, + _unconfirmedShareDelegations = unconfirmedShareDelegations; + + @override + final String roundId; + @override + final int bundleCount; + final List _delegation; + @override + List get delegation { + if (_delegation is EqualUnmodifiableListView) return _delegation; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_delegation); + } + + final List _votes; + @override + List get votes { + if (_votes is EqualUnmodifiableListView) return _votes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_votes); + } + + final List _shares; + @override + List get shares { + if (_shares is EqualUnmodifiableListView) return _shares; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_shares); + } + + final List _shareDelegations; + @override + List get shareDelegations { + if (_shareDelegations is EqualUnmodifiableListView) + return _shareDelegations; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_shareDelegations); + } + + final List _unconfirmedShareDelegations; + @override + List get unconfirmedShareDelegations { + if (_unconfirmedShareDelegations is EqualUnmodifiableListView) + return _unconfirmedShareDelegations; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_unconfirmedShareDelegations); + } + + /// Create a copy of VotingRoundRecovery + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingRoundRecoveryCopyWith<_VotingRoundRecovery> get copyWith => + __$VotingRoundRecoveryCopyWithImpl<_VotingRoundRecovery>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingRoundRecovery && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleCount, bundleCount) || + other.bundleCount == bundleCount) && + const DeepCollectionEquality() + .equals(other._delegation, _delegation) && + const DeepCollectionEquality().equals(other._votes, _votes) && + const DeepCollectionEquality().equals(other._shares, _shares) && + const DeepCollectionEquality() + .equals(other._shareDelegations, _shareDelegations) && + const DeepCollectionEquality().equals( + other._unconfirmedShareDelegations, + _unconfirmedShareDelegations)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + bundleCount, + const DeepCollectionEquality().hash(_delegation), + const DeepCollectionEquality().hash(_votes), + const DeepCollectionEquality().hash(_shares), + const DeepCollectionEquality().hash(_shareDelegations), + const DeepCollectionEquality().hash(_unconfirmedShareDelegations)); + + @override + String toString() { + return 'VotingRoundRecovery(roundId: $roundId, bundleCount: $bundleCount, delegation: $delegation, votes: $votes, shares: $shares, shareDelegations: $shareDelegations, unconfirmedShareDelegations: $unconfirmedShareDelegations)'; + } +} + +/// @nodoc +abstract mixin class _$VotingRoundRecoveryCopyWith<$Res> + implements $VotingRoundRecoveryCopyWith<$Res> { + factory _$VotingRoundRecoveryCopyWith(_VotingRoundRecovery value, + $Res Function(_VotingRoundRecovery) _then) = + __$VotingRoundRecoveryCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + int bundleCount, + List delegation, + List votes, + List shares, + List shareDelegations, + List unconfirmedShareDelegations}); +} + +/// @nodoc +class __$VotingRoundRecoveryCopyWithImpl<$Res> + implements _$VotingRoundRecoveryCopyWith<$Res> { + __$VotingRoundRecoveryCopyWithImpl(this._self, this._then); + + final _VotingRoundRecovery _self; + final $Res Function(_VotingRoundRecovery) _then; + + /// Create a copy of VotingRoundRecovery + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? bundleCount = null, + Object? delegation = null, + Object? votes = null, + Object? shares = null, + Object? shareDelegations = null, + Object? unconfirmedShareDelegations = null, + }) { + return _then(_VotingRoundRecovery( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleCount: null == bundleCount + ? _self.bundleCount + : bundleCount // ignore: cast_nullable_to_non_nullable + as int, + delegation: null == delegation + ? _self._delegation + : delegation // ignore: cast_nullable_to_non_nullable + as List, + votes: null == votes + ? _self._votes + : votes // ignore: cast_nullable_to_non_nullable + as List, + shares: null == shares + ? _self._shares + : shares // ignore: cast_nullable_to_non_nullable + as List, + shareDelegations: null == shareDelegations + ? _self._shareDelegations + : shareDelegations // ignore: cast_nullable_to_non_nullable + as List, + unconfirmedShareDelegations: null == unconfirmedShareDelegations + ? _self._unconfirmedShareDelegations + : unconfirmedShareDelegations // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +mixin _$VotingServiceEndpoint { + String get url; + String get label; + + /// Create a copy of VotingServiceEndpoint + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingServiceEndpointCopyWith get copyWith => + _$VotingServiceEndpointCopyWithImpl( + this as VotingServiceEndpoint, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingServiceEndpoint && + (identical(other.url, url) || other.url == url) && + (identical(other.label, label) || other.label == label)); + } + + @override + int get hashCode => Object.hash(runtimeType, url, label); + + @override + String toString() { + return 'VotingServiceEndpoint(url: $url, label: $label)'; + } +} + +/// @nodoc +abstract mixin class $VotingServiceEndpointCopyWith<$Res> { + factory $VotingServiceEndpointCopyWith(VotingServiceEndpoint value, + $Res Function(VotingServiceEndpoint) _then) = + _$VotingServiceEndpointCopyWithImpl; + @useResult + $Res call({String url, String label}); +} + +/// @nodoc +class _$VotingServiceEndpointCopyWithImpl<$Res> + implements $VotingServiceEndpointCopyWith<$Res> { + _$VotingServiceEndpointCopyWithImpl(this._self, this._then); + + final VotingServiceEndpoint _self; + final $Res Function(VotingServiceEndpoint) _then; + + /// Create a copy of VotingServiceEndpoint + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? url = null, + Object? label = null, + }) { + return _then(_self.copyWith( + url: null == url + ? _self.url + : url // ignore: cast_nullable_to_non_nullable + as String, + label: null == label + ? _self.label + : label // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingServiceEndpoint]. +extension VotingServiceEndpointPatterns on VotingServiceEndpoint { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingServiceEndpoint value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingServiceEndpoint value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingServiceEndpoint value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String url, String label)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint() when $default != null: + return $default(_that.url, _that.label); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String url, String label) $default, + ) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint(): + return $default(_that.url, _that.label); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String url, String label)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingServiceEndpoint() when $default != null: + return $default(_that.url, _that.label); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingServiceEndpoint implements VotingServiceEndpoint { + const _VotingServiceEndpoint({required this.url, required this.label}); + + @override + final String url; + @override + final String label; + + /// Create a copy of VotingServiceEndpoint + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingServiceEndpointCopyWith<_VotingServiceEndpoint> get copyWith => + __$VotingServiceEndpointCopyWithImpl<_VotingServiceEndpoint>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingServiceEndpoint && + (identical(other.url, url) || other.url == url) && + (identical(other.label, label) || other.label == label)); + } + + @override + int get hashCode => Object.hash(runtimeType, url, label); + + @override + String toString() { + return 'VotingServiceEndpoint(url: $url, label: $label)'; + } +} + +/// @nodoc +abstract mixin class _$VotingServiceEndpointCopyWith<$Res> + implements $VotingServiceEndpointCopyWith<$Res> { + factory _$VotingServiceEndpointCopyWith(_VotingServiceEndpoint value, + $Res Function(_VotingServiceEndpoint) _then) = + __$VotingServiceEndpointCopyWithImpl; + @override + @useResult + $Res call({String url, String label}); +} + +/// @nodoc +class __$VotingServiceEndpointCopyWithImpl<$Res> + implements _$VotingServiceEndpointCopyWith<$Res> { + __$VotingServiceEndpointCopyWithImpl(this._self, this._then); + + final _VotingServiceEndpoint _self; + final $Res Function(_VotingServiceEndpoint) _then; + + /// Create a copy of VotingServiceEndpoint + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? url = null, + Object? label = null, + }) { + return _then(_VotingServiceEndpoint( + url: null == url + ? _self.url + : url // ignore: cast_nullable_to_non_nullable + as String, + label: null == label + ? _self.label + : label // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingShareDelegationRecord { + String get roundId; + int get bundleIndex; + int get proposalId; + int get shareIndex; + List get sentToUrls; + Uint8List get nullifier; + bool get confirmed; + BigInt get submitAt; + BigInt get createdAt; + + /// Create a copy of VotingShareDelegationRecord + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingShareDelegationRecordCopyWith + get copyWith => _$VotingShareDelegationRecordCopyWithImpl< + VotingShareDelegationRecord>( + this as VotingShareDelegationRecord, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingShareDelegationRecord && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + const DeepCollectionEquality() + .equals(other.sentToUrls, sentToUrls) && + const DeepCollectionEquality().equals(other.nullifier, nullifier) && + (identical(other.confirmed, confirmed) || + other.confirmed == confirmed) && + (identical(other.submitAt, submitAt) || + other.submitAt == submitAt) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + bundleIndex, + proposalId, + shareIndex, + const DeepCollectionEquality().hash(sentToUrls), + const DeepCollectionEquality().hash(nullifier), + confirmed, + submitAt, + createdAt); + + @override + String toString() { + return 'VotingShareDelegationRecord(roundId: $roundId, bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, sentToUrls: $sentToUrls, nullifier: $nullifier, confirmed: $confirmed, submitAt: $submitAt, createdAt: $createdAt)'; + } +} + +/// @nodoc +abstract mixin class $VotingShareDelegationRecordCopyWith<$Res> { + factory $VotingShareDelegationRecordCopyWith( + VotingShareDelegationRecord value, + $Res Function(VotingShareDelegationRecord) _then) = + _$VotingShareDelegationRecordCopyWithImpl; + @useResult + $Res call( + {String roundId, + int bundleIndex, + int proposalId, + int shareIndex, + List sentToUrls, + Uint8List nullifier, + bool confirmed, + BigInt submitAt, + BigInt createdAt}); +} + +/// @nodoc +class _$VotingShareDelegationRecordCopyWithImpl<$Res> + implements $VotingShareDelegationRecordCopyWith<$Res> { + _$VotingShareDelegationRecordCopyWithImpl(this._self, this._then); + + final VotingShareDelegationRecord _self; + final $Res Function(VotingShareDelegationRecord) _then; + + /// Create a copy of VotingShareDelegationRecord + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? sentToUrls = null, + Object? nullifier = null, + Object? confirmed = null, + Object? submitAt = null, + Object? createdAt = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + sentToUrls: null == sentToUrls + ? _self.sentToUrls + : sentToUrls // ignore: cast_nullable_to_non_nullable + as List, + nullifier: null == nullifier + ? _self.nullifier + : nullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + confirmed: null == confirmed + ? _self.confirmed + : confirmed // ignore: cast_nullable_to_non_nullable + as bool, + submitAt: null == submitAt + ? _self.submitAt + : submitAt // ignore: cast_nullable_to_non_nullable + as BigInt, + createdAt: null == createdAt + ? _self.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingShareDelegationRecord]. +extension VotingShareDelegationRecordPatterns on VotingShareDelegationRecord { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingShareDelegationRecord value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingShareDelegationRecord value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingShareDelegationRecord value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String roundId, + int bundleIndex, + int proposalId, + int shareIndex, + List sentToUrls, + Uint8List nullifier, + bool confirmed, + BigInt submitAt, + BigInt createdAt)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.proposalId, + _that.shareIndex, + _that.sentToUrls, + _that.nullifier, + _that.confirmed, + _that.submitAt, + _that.createdAt); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String roundId, + int bundleIndex, + int proposalId, + int shareIndex, + List sentToUrls, + Uint8List nullifier, + bool confirmed, + BigInt submitAt, + BigInt createdAt) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord(): + return $default( + _that.roundId, + _that.bundleIndex, + _that.proposalId, + _that.shareIndex, + _that.sentToUrls, + _that.nullifier, + _that.confirmed, + _that.submitAt, + _that.createdAt); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String roundId, + int bundleIndex, + int proposalId, + int shareIndex, + List sentToUrls, + Uint8List nullifier, + bool confirmed, + BigInt submitAt, + BigInt createdAt)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareDelegationRecord() when $default != null: + return $default( + _that.roundId, + _that.bundleIndex, + _that.proposalId, + _that.shareIndex, + _that.sentToUrls, + _that.nullifier, + _that.confirmed, + _that.submitAt, + _that.createdAt); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingShareDelegationRecord implements VotingShareDelegationRecord { + const _VotingShareDelegationRecord( + {required this.roundId, + required this.bundleIndex, + required this.proposalId, + required this.shareIndex, + required final List sentToUrls, + required this.nullifier, + required this.confirmed, + required this.submitAt, + required this.createdAt}) + : _sentToUrls = sentToUrls; + + @override + final String roundId; + @override + final int bundleIndex; + @override + final int proposalId; + @override + final int shareIndex; + final List _sentToUrls; + @override + List get sentToUrls { + if (_sentToUrls is EqualUnmodifiableListView) return _sentToUrls; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_sentToUrls); + } + + @override + final Uint8List nullifier; + @override + final bool confirmed; + @override + final BigInt submitAt; + @override + final BigInt createdAt; + + /// Create a copy of VotingShareDelegationRecord + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingShareDelegationRecordCopyWith<_VotingShareDelegationRecord> + get copyWith => __$VotingShareDelegationRecordCopyWithImpl< + _VotingShareDelegationRecord>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingShareDelegationRecord && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + const DeepCollectionEquality() + .equals(other._sentToUrls, _sentToUrls) && + const DeepCollectionEquality().equals(other.nullifier, nullifier) && + (identical(other.confirmed, confirmed) || + other.confirmed == confirmed) && + (identical(other.submitAt, submitAt) || + other.submitAt == submitAt) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + roundId, + bundleIndex, + proposalId, + shareIndex, + const DeepCollectionEquality().hash(_sentToUrls), + const DeepCollectionEquality().hash(nullifier), + confirmed, + submitAt, + createdAt); + + @override + String toString() { + return 'VotingShareDelegationRecord(roundId: $roundId, bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, sentToUrls: $sentToUrls, nullifier: $nullifier, confirmed: $confirmed, submitAt: $submitAt, createdAt: $createdAt)'; + } +} + +/// @nodoc +abstract mixin class _$VotingShareDelegationRecordCopyWith<$Res> + implements $VotingShareDelegationRecordCopyWith<$Res> { + factory _$VotingShareDelegationRecordCopyWith( + _VotingShareDelegationRecord value, + $Res Function(_VotingShareDelegationRecord) _then) = + __$VotingShareDelegationRecordCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + int bundleIndex, + int proposalId, + int shareIndex, + List sentToUrls, + Uint8List nullifier, + bool confirmed, + BigInt submitAt, + BigInt createdAt}); +} + +/// @nodoc +class __$VotingShareDelegationRecordCopyWithImpl<$Res> + implements _$VotingShareDelegationRecordCopyWith<$Res> { + __$VotingShareDelegationRecordCopyWithImpl(this._self, this._then); + + final _VotingShareDelegationRecord _self; + final $Res Function(_VotingShareDelegationRecord) _then; + + /// Create a copy of VotingShareDelegationRecord + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? sentToUrls = null, + Object? nullifier = null, + Object? confirmed = null, + Object? submitAt = null, + Object? createdAt = null, + }) { + return _then(_VotingShareDelegationRecord( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + sentToUrls: null == sentToUrls + ? _self._sentToUrls + : sentToUrls // ignore: cast_nullable_to_non_nullable + as List, + nullifier: null == nullifier + ? _self.nullifier + : nullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + confirmed: null == confirmed + ? _self.confirmed + : confirmed // ignore: cast_nullable_to_non_nullable + as bool, + submitAt: null == submitAt + ? _self.submitAt + : submitAt // ignore: cast_nullable_to_non_nullable + as BigInt, + createdAt: null == createdAt + ? _self.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// @nodoc +mixin _$VotingSharePayload { + Uint8List get sharesHash; + int get proposalId; + int get voteDecision; + VotingEncryptedShare get encShare; + BigInt get treePosition; + List get allEncShares; + List get shareComms; + Uint8List get primaryBlind; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSharePayloadCopyWith get copyWith => + _$VotingSharePayloadCopyWithImpl( + this as VotingSharePayload, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSharePayload && + const DeepCollectionEquality() + .equals(other.sharesHash, sharesHash) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.voteDecision, voteDecision) || + other.voteDecision == voteDecision) && + (identical(other.encShare, encShare) || + other.encShare == encShare) && + (identical(other.treePosition, treePosition) || + other.treePosition == treePosition) && + const DeepCollectionEquality() + .equals(other.allEncShares, allEncShares) && + const DeepCollectionEquality() + .equals(other.shareComms, shareComms) && + const DeepCollectionEquality() + .equals(other.primaryBlind, primaryBlind)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(sharesHash), + proposalId, + voteDecision, + encShare, + treePosition, + const DeepCollectionEquality().hash(allEncShares), + const DeepCollectionEquality().hash(shareComms), + const DeepCollectionEquality().hash(primaryBlind)); + + @override + String toString() { + return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + } +} + +/// @nodoc +abstract mixin class $VotingSharePayloadCopyWith<$Res> { + factory $VotingSharePayloadCopyWith( + VotingSharePayload value, $Res Function(VotingSharePayload) _then) = + _$VotingSharePayloadCopyWithImpl; + @useResult + $Res call( + {Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind}); + + $VotingEncryptedShareCopyWith<$Res> get encShare; +} + +/// @nodoc +class _$VotingSharePayloadCopyWithImpl<$Res> + implements $VotingSharePayloadCopyWith<$Res> { + _$VotingSharePayloadCopyWithImpl(this._self, this._then); + + final VotingSharePayload _self; + final $Res Function(VotingSharePayload) _then; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? sharesHash = null, + Object? proposalId = null, + Object? voteDecision = null, + Object? encShare = null, + Object? treePosition = null, + Object? allEncShares = null, + Object? shareComms = null, + Object? primaryBlind = null, + }) { + return _then(_self.copyWith( + sharesHash: null == sharesHash + ? _self.sharesHash + : sharesHash // ignore: cast_nullable_to_non_nullable + as Uint8List, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + voteDecision: null == voteDecision + ? _self.voteDecision + : voteDecision // ignore: cast_nullable_to_non_nullable + as int, + encShare: null == encShare + ? _self.encShare + : encShare // ignore: cast_nullable_to_non_nullable + as VotingEncryptedShare, + treePosition: null == treePosition + ? _self.treePosition + : treePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + allEncShares: null == allEncShares + ? _self.allEncShares + : allEncShares // ignore: cast_nullable_to_non_nullable + as List, + shareComms: null == shareComms + ? _self.shareComms + : shareComms // ignore: cast_nullable_to_non_nullable + as List, + primaryBlind: null == primaryBlind + ? _self.primaryBlind + : primaryBlind // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith<$Res> get encShare { + return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { + return _then(_self.copyWith(encShare: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingSharePayload]. +extension VotingSharePayloadPatterns on VotingSharePayload { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSharePayload value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSharePayload value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSharePayload value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload(): + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePayload() when $default != null: + return $default( + _that.sharesHash, + _that.proposalId, + _that.voteDecision, + _that.encShare, + _that.treePosition, + _that.allEncShares, + _that.shareComms, + _that.primaryBlind); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSharePayload implements VotingSharePayload { + const _VotingSharePayload( + {required this.sharesHash, + required this.proposalId, + required this.voteDecision, + required this.encShare, + required this.treePosition, + required final List allEncShares, + required final List shareComms, + required this.primaryBlind}) + : _allEncShares = allEncShares, + _shareComms = shareComms; + + @override + final Uint8List sharesHash; + @override + final int proposalId; + @override + final int voteDecision; + @override + final VotingEncryptedShare encShare; + @override + final BigInt treePosition; + final List _allEncShares; + @override + List get allEncShares { + if (_allEncShares is EqualUnmodifiableListView) return _allEncShares; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_allEncShares); + } + + final List _shareComms; + @override + List get shareComms { + if (_shareComms is EqualUnmodifiableListView) return _shareComms; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_shareComms); + } + + @override + final Uint8List primaryBlind; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSharePayloadCopyWith<_VotingSharePayload> get copyWith => + __$VotingSharePayloadCopyWithImpl<_VotingSharePayload>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSharePayload && + const DeepCollectionEquality() + .equals(other.sharesHash, sharesHash) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.voteDecision, voteDecision) || + other.voteDecision == voteDecision) && + (identical(other.encShare, encShare) || + other.encShare == encShare) && + (identical(other.treePosition, treePosition) || + other.treePosition == treePosition) && + const DeepCollectionEquality() + .equals(other._allEncShares, _allEncShares) && + const DeepCollectionEquality() + .equals(other._shareComms, _shareComms) && + const DeepCollectionEquality() + .equals(other.primaryBlind, primaryBlind)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(sharesHash), + proposalId, + voteDecision, + encShare, + treePosition, + const DeepCollectionEquality().hash(_allEncShares), + const DeepCollectionEquality().hash(_shareComms), + const DeepCollectionEquality().hash(primaryBlind)); + + @override + String toString() { + return 'VotingSharePayload(sharesHash: $sharesHash, proposalId: $proposalId, voteDecision: $voteDecision, encShare: $encShare, treePosition: $treePosition, allEncShares: $allEncShares, shareComms: $shareComms, primaryBlind: $primaryBlind)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSharePayloadCopyWith<$Res> + implements $VotingSharePayloadCopyWith<$Res> { + factory _$VotingSharePayloadCopyWith( + _VotingSharePayload value, $Res Function(_VotingSharePayload) _then) = + __$VotingSharePayloadCopyWithImpl; + @override + @useResult + $Res call( + {Uint8List sharesHash, + int proposalId, + int voteDecision, + VotingEncryptedShare encShare, + BigInt treePosition, + List allEncShares, + List shareComms, + Uint8List primaryBlind}); + + @override + $VotingEncryptedShareCopyWith<$Res> get encShare; +} + +/// @nodoc +class __$VotingSharePayloadCopyWithImpl<$Res> + implements _$VotingSharePayloadCopyWith<$Res> { + __$VotingSharePayloadCopyWithImpl(this._self, this._then); + + final _VotingSharePayload _self; + final $Res Function(_VotingSharePayload) _then; + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? sharesHash = null, + Object? proposalId = null, + Object? voteDecision = null, + Object? encShare = null, + Object? treePosition = null, + Object? allEncShares = null, + Object? shareComms = null, + Object? primaryBlind = null, + }) { + return _then(_VotingSharePayload( + sharesHash: null == sharesHash + ? _self.sharesHash + : sharesHash // ignore: cast_nullable_to_non_nullable + as Uint8List, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + voteDecision: null == voteDecision + ? _self.voteDecision + : voteDecision // ignore: cast_nullable_to_non_nullable + as int, + encShare: null == encShare + ? _self.encShare + : encShare // ignore: cast_nullable_to_non_nullable + as VotingEncryptedShare, + treePosition: null == treePosition + ? _self.treePosition + : treePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + allEncShares: null == allEncShares + ? _self._allEncShares + : allEncShares // ignore: cast_nullable_to_non_nullable + as List, + shareComms: null == shareComms + ? _self._shareComms + : shareComms // ignore: cast_nullable_to_non_nullable + as List, + primaryBlind: null == primaryBlind + ? _self.primaryBlind + : primaryBlind // ignore: cast_nullable_to_non_nullable + as Uint8List, + )); + } + + /// Create a copy of VotingSharePayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingEncryptedShareCopyWith<$Res> get encShare { + return $VotingEncryptedShareCopyWith<$Res>(_self.encShare, (value) { + return _then(_self.copyWith(encShare: value)); + }); + } +} + +/// @nodoc +mixin _$VotingSharePlan { + VotingShareTrackingSummary get summary; + BigInt? get nextTrackingDelaySecs; + bool get lastMoment; + List get submissions; + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSharePlanCopyWith get copyWith => + _$VotingSharePlanCopyWithImpl( + this as VotingSharePlan, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSharePlan && + (identical(other.summary, summary) || other.summary == summary) && + (identical(other.nextTrackingDelaySecs, nextTrackingDelaySecs) || + other.nextTrackingDelaySecs == nextTrackingDelaySecs) && + (identical(other.lastMoment, lastMoment) || + other.lastMoment == lastMoment) && + const DeepCollectionEquality() + .equals(other.submissions, submissions)); + } + + @override + int get hashCode => Object.hash(runtimeType, summary, nextTrackingDelaySecs, + lastMoment, const DeepCollectionEquality().hash(submissions)); + + @override + String toString() { + return 'VotingSharePlan(summary: $summary, nextTrackingDelaySecs: $nextTrackingDelaySecs, lastMoment: $lastMoment, submissions: $submissions)'; + } +} + +/// @nodoc +abstract mixin class $VotingSharePlanCopyWith<$Res> { + factory $VotingSharePlanCopyWith( + VotingSharePlan value, $Res Function(VotingSharePlan) _then) = + _$VotingSharePlanCopyWithImpl; + @useResult + $Res call( + {VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + bool lastMoment, + List submissions}); + + $VotingShareTrackingSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$VotingSharePlanCopyWithImpl<$Res> + implements $VotingSharePlanCopyWith<$Res> { + _$VotingSharePlanCopyWithImpl(this._self, this._then); + + final VotingSharePlan _self; + final $Res Function(VotingSharePlan) _then; + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = null, + Object? nextTrackingDelaySecs = freezed, + Object? lastMoment = null, + Object? submissions = null, + }) { + return _then(_self.copyWith( + summary: null == summary + ? _self.summary + : summary // ignore: cast_nullable_to_non_nullable + as VotingShareTrackingSummary, + nextTrackingDelaySecs: freezed == nextTrackingDelaySecs + ? _self.nextTrackingDelaySecs + : nextTrackingDelaySecs // ignore: cast_nullable_to_non_nullable + as BigInt?, + lastMoment: null == lastMoment + ? _self.lastMoment + : lastMoment // ignore: cast_nullable_to_non_nullable + as bool, + submissions: null == submissions + ? _self.submissions + : submissions // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingShareTrackingSummaryCopyWith<$Res> get summary { + return $VotingShareTrackingSummaryCopyWith<$Res>(_self.summary, (value) { + return _then(_self.copyWith(summary: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingSharePlan]. +extension VotingSharePlanPatterns on VotingSharePlan { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSharePlan value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePlan() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSharePlan value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlan(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSharePlan value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlan() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + bool lastMoment, + List submissions)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePlan() when $default != null: + return $default(_that.summary, _that.nextTrackingDelaySecs, + _that.lastMoment, _that.submissions); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + bool lastMoment, + List submissions) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlan(): + return $default(_that.summary, _that.nextTrackingDelaySecs, + _that.lastMoment, _that.submissions); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + bool lastMoment, + List submissions)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlan() when $default != null: + return $default(_that.summary, _that.nextTrackingDelaySecs, + _that.lastMoment, _that.submissions); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSharePlan implements VotingSharePlan { + const _VotingSharePlan( + {required this.summary, + this.nextTrackingDelaySecs, + required this.lastMoment, + required final List submissions}) + : _submissions = submissions; + + @override + final VotingShareTrackingSummary summary; + @override + final BigInt? nextTrackingDelaySecs; + @override + final bool lastMoment; + final List _submissions; + @override + List get submissions { + if (_submissions is EqualUnmodifiableListView) return _submissions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_submissions); + } + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSharePlanCopyWith<_VotingSharePlan> get copyWith => + __$VotingSharePlanCopyWithImpl<_VotingSharePlan>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSharePlan && + (identical(other.summary, summary) || other.summary == summary) && + (identical(other.nextTrackingDelaySecs, nextTrackingDelaySecs) || + other.nextTrackingDelaySecs == nextTrackingDelaySecs) && + (identical(other.lastMoment, lastMoment) || + other.lastMoment == lastMoment) && + const DeepCollectionEquality() + .equals(other._submissions, _submissions)); + } + + @override + int get hashCode => Object.hash(runtimeType, summary, nextTrackingDelaySecs, + lastMoment, const DeepCollectionEquality().hash(_submissions)); + + @override + String toString() { + return 'VotingSharePlan(summary: $summary, nextTrackingDelaySecs: $nextTrackingDelaySecs, lastMoment: $lastMoment, submissions: $submissions)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSharePlanCopyWith<$Res> + implements $VotingSharePlanCopyWith<$Res> { + factory _$VotingSharePlanCopyWith( + _VotingSharePlan value, $Res Function(_VotingSharePlan) _then) = + __$VotingSharePlanCopyWithImpl; + @override + @useResult + $Res call( + {VotingShareTrackingSummary summary, + BigInt? nextTrackingDelaySecs, + bool lastMoment, + List submissions}); + + @override + $VotingShareTrackingSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$VotingSharePlanCopyWithImpl<$Res> + implements _$VotingSharePlanCopyWith<$Res> { + __$VotingSharePlanCopyWithImpl(this._self, this._then); + + final _VotingSharePlan _self; + final $Res Function(_VotingSharePlan) _then; + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? summary = null, + Object? nextTrackingDelaySecs = freezed, + Object? lastMoment = null, + Object? submissions = null, + }) { + return _then(_VotingSharePlan( + summary: null == summary + ? _self.summary + : summary // ignore: cast_nullable_to_non_nullable + as VotingShareTrackingSummary, + nextTrackingDelaySecs: freezed == nextTrackingDelaySecs + ? _self.nextTrackingDelaySecs + : nextTrackingDelaySecs // ignore: cast_nullable_to_non_nullable + as BigInt?, + lastMoment: null == lastMoment + ? _self.lastMoment + : lastMoment // ignore: cast_nullable_to_non_nullable + as bool, + submissions: null == submissions + ? _self._submissions + : submissions // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingSharePlan + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingShareTrackingSummaryCopyWith<$Res> get summary { + return $VotingShareTrackingSummaryCopyWith<$Res>(_self.summary, (value) { + return _then(_self.copyWith(summary: value)); + }); + } +} + +/// @nodoc +mixin _$VotingSharePlanItem { + BigInt get submitAt; + int get targetCount; + List get targetServers; + + /// Create a copy of VotingSharePlanItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSharePlanItemCopyWith get copyWith => + _$VotingSharePlanItemCopyWithImpl( + this as VotingSharePlanItem, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSharePlanItem && + (identical(other.submitAt, submitAt) || + other.submitAt == submitAt) && + (identical(other.targetCount, targetCount) || + other.targetCount == targetCount) && + const DeepCollectionEquality() + .equals(other.targetServers, targetServers)); + } + + @override + int get hashCode => Object.hash(runtimeType, submitAt, targetCount, + const DeepCollectionEquality().hash(targetServers)); + + @override + String toString() { + return 'VotingSharePlanItem(submitAt: $submitAt, targetCount: $targetCount, targetServers: $targetServers)'; + } +} + +/// @nodoc +abstract mixin class $VotingSharePlanItemCopyWith<$Res> { + factory $VotingSharePlanItemCopyWith( + VotingSharePlanItem value, $Res Function(VotingSharePlanItem) _then) = + _$VotingSharePlanItemCopyWithImpl; + @useResult + $Res call({BigInt submitAt, int targetCount, List targetServers}); +} + +/// @nodoc +class _$VotingSharePlanItemCopyWithImpl<$Res> + implements $VotingSharePlanItemCopyWith<$Res> { + _$VotingSharePlanItemCopyWithImpl(this._self, this._then); + + final VotingSharePlanItem _self; + final $Res Function(VotingSharePlanItem) _then; + + /// Create a copy of VotingSharePlanItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? submitAt = null, + Object? targetCount = null, + Object? targetServers = null, + }) { + return _then(_self.copyWith( + submitAt: null == submitAt + ? _self.submitAt + : submitAt // ignore: cast_nullable_to_non_nullable + as BigInt, + targetCount: null == targetCount + ? _self.targetCount + : targetCount // ignore: cast_nullable_to_non_nullable + as int, + targetServers: null == targetServers + ? _self.targetServers + : targetServers // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingSharePlanItem]. +extension VotingSharePlanItemPatterns on VotingSharePlanItem { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSharePlanItem value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSharePlanItem value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSharePlanItem value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + BigInt submitAt, int targetCount, List targetServers)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem() when $default != null: + return $default(_that.submitAt, _that.targetCount, _that.targetServers); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + BigInt submitAt, int targetCount, List targetServers) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem(): + return $default(_that.submitAt, _that.targetCount, _that.targetServers); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + BigInt submitAt, int targetCount, List targetServers)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSharePlanItem() when $default != null: + return $default(_that.submitAt, _that.targetCount, _that.targetServers); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSharePlanItem implements VotingSharePlanItem { + const _VotingSharePlanItem( + {required this.submitAt, + required this.targetCount, + required final List targetServers}) + : _targetServers = targetServers; + + @override + final BigInt submitAt; + @override + final int targetCount; + final List _targetServers; + @override + List get targetServers { + if (_targetServers is EqualUnmodifiableListView) return _targetServers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_targetServers); + } + + /// Create a copy of VotingSharePlanItem + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSharePlanItemCopyWith<_VotingSharePlanItem> get copyWith => + __$VotingSharePlanItemCopyWithImpl<_VotingSharePlanItem>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSharePlanItem && + (identical(other.submitAt, submitAt) || + other.submitAt == submitAt) && + (identical(other.targetCount, targetCount) || + other.targetCount == targetCount) && + const DeepCollectionEquality() + .equals(other._targetServers, _targetServers)); + } + + @override + int get hashCode => Object.hash(runtimeType, submitAt, targetCount, + const DeepCollectionEquality().hash(_targetServers)); + + @override + String toString() { + return 'VotingSharePlanItem(submitAt: $submitAt, targetCount: $targetCount, targetServers: $targetServers)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSharePlanItemCopyWith<$Res> + implements $VotingSharePlanItemCopyWith<$Res> { + factory _$VotingSharePlanItemCopyWith(_VotingSharePlanItem value, + $Res Function(_VotingSharePlanItem) _then) = + __$VotingSharePlanItemCopyWithImpl; + @override + @useResult + $Res call({BigInt submitAt, int targetCount, List targetServers}); +} + +/// @nodoc +class __$VotingSharePlanItemCopyWithImpl<$Res> + implements _$VotingSharePlanItemCopyWith<$Res> { + __$VotingSharePlanItemCopyWithImpl(this._self, this._then); + + final _VotingSharePlanItem _self; + final $Res Function(_VotingSharePlanItem) _then; + + /// Create a copy of VotingSharePlanItem + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? submitAt = null, + Object? targetCount = null, + Object? targetServers = null, + }) { + return _then(_VotingSharePlanItem( + submitAt: null == submitAt + ? _self.submitAt + : submitAt // ignore: cast_nullable_to_non_nullable + as BigInt, + targetCount: null == targetCount + ? _self.targetCount + : targetCount // ignore: cast_nullable_to_non_nullable + as int, + targetServers: null == targetServers + ? _self._targetServers + : targetServers // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +mixin _$VotingShareTrackingSummary { + BigInt get total; + BigInt get confirmed; + BigInt get waiting; + BigInt get ready; + BigInt get overdue; + + /// Create a copy of VotingShareTrackingSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingShareTrackingSummaryCopyWith + get copyWith => + _$VotingShareTrackingSummaryCopyWithImpl( + this as VotingShareTrackingSummary, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingShareTrackingSummary && + (identical(other.total, total) || other.total == total) && + (identical(other.confirmed, confirmed) || + other.confirmed == confirmed) && + (identical(other.waiting, waiting) || other.waiting == waiting) && + (identical(other.ready, ready) || other.ready == ready) && + (identical(other.overdue, overdue) || other.overdue == overdue)); + } + + @override + int get hashCode => + Object.hash(runtimeType, total, confirmed, waiting, ready, overdue); + + @override + String toString() { + return 'VotingShareTrackingSummary(total: $total, confirmed: $confirmed, waiting: $waiting, ready: $ready, overdue: $overdue)'; + } +} + +/// @nodoc +abstract mixin class $VotingShareTrackingSummaryCopyWith<$Res> { + factory $VotingShareTrackingSummaryCopyWith(VotingShareTrackingSummary value, + $Res Function(VotingShareTrackingSummary) _then) = + _$VotingShareTrackingSummaryCopyWithImpl; + @useResult + $Res call( + {BigInt total, + BigInt confirmed, + BigInt waiting, + BigInt ready, + BigInt overdue}); +} + +/// @nodoc +class _$VotingShareTrackingSummaryCopyWithImpl<$Res> + implements $VotingShareTrackingSummaryCopyWith<$Res> { + _$VotingShareTrackingSummaryCopyWithImpl(this._self, this._then); + + final VotingShareTrackingSummary _self; + final $Res Function(VotingShareTrackingSummary) _then; + + /// Create a copy of VotingShareTrackingSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? total = null, + Object? confirmed = null, + Object? waiting = null, + Object? ready = null, + Object? overdue = null, + }) { + return _then(_self.copyWith( + total: null == total + ? _self.total + : total // ignore: cast_nullable_to_non_nullable + as BigInt, + confirmed: null == confirmed + ? _self.confirmed + : confirmed // ignore: cast_nullable_to_non_nullable + as BigInt, + waiting: null == waiting + ? _self.waiting + : waiting // ignore: cast_nullable_to_non_nullable + as BigInt, + ready: null == ready + ? _self.ready + : ready // ignore: cast_nullable_to_non_nullable + as BigInt, + overdue: null == overdue + ? _self.overdue + : overdue // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingShareTrackingSummary]. +extension VotingShareTrackingSummaryPatterns on VotingShareTrackingSummary { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingShareTrackingSummary value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingShareTrackingSummary value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingShareTrackingSummary value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(BigInt total, BigInt confirmed, BigInt waiting, + BigInt ready, BigInt overdue)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary() when $default != null: + return $default(_that.total, _that.confirmed, _that.waiting, + _that.ready, _that.overdue); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(BigInt total, BigInt confirmed, BigInt waiting, + BigInt ready, BigInt overdue) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary(): + return $default(_that.total, _that.confirmed, _that.waiting, + _that.ready, _that.overdue); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(BigInt total, BigInt confirmed, BigInt waiting, + BigInt ready, BigInt overdue)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareTrackingSummary() when $default != null: + return $default(_that.total, _that.confirmed, _that.waiting, + _that.ready, _that.overdue); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingShareTrackingSummary implements VotingShareTrackingSummary { + const _VotingShareTrackingSummary( + {required this.total, + required this.confirmed, + required this.waiting, + required this.ready, + required this.overdue}); + + @override + final BigInt total; + @override + final BigInt confirmed; + @override + final BigInt waiting; + @override + final BigInt ready; + @override + final BigInt overdue; + + /// Create a copy of VotingShareTrackingSummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingShareTrackingSummaryCopyWith<_VotingShareTrackingSummary> + get copyWith => __$VotingShareTrackingSummaryCopyWithImpl< + _VotingShareTrackingSummary>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingShareTrackingSummary && + (identical(other.total, total) || other.total == total) && + (identical(other.confirmed, confirmed) || + other.confirmed == confirmed) && + (identical(other.waiting, waiting) || other.waiting == waiting) && + (identical(other.ready, ready) || other.ready == ready) && + (identical(other.overdue, overdue) || other.overdue == overdue)); + } + + @override + int get hashCode => + Object.hash(runtimeType, total, confirmed, waiting, ready, overdue); + + @override + String toString() { + return 'VotingShareTrackingSummary(total: $total, confirmed: $confirmed, waiting: $waiting, ready: $ready, overdue: $overdue)'; + } +} + +/// @nodoc +abstract mixin class _$VotingShareTrackingSummaryCopyWith<$Res> + implements $VotingShareTrackingSummaryCopyWith<$Res> { + factory _$VotingShareTrackingSummaryCopyWith( + _VotingShareTrackingSummary value, + $Res Function(_VotingShareTrackingSummary) _then) = + __$VotingShareTrackingSummaryCopyWithImpl; + @override + @useResult + $Res call( + {BigInt total, + BigInt confirmed, + BigInt waiting, + BigInt ready, + BigInt overdue}); +} + +/// @nodoc +class __$VotingShareTrackingSummaryCopyWithImpl<$Res> + implements _$VotingShareTrackingSummaryCopyWith<$Res> { + __$VotingShareTrackingSummaryCopyWithImpl(this._self, this._then); + + final _VotingShareTrackingSummary _self; + final $Res Function(_VotingShareTrackingSummary) _then; + + /// Create a copy of VotingShareTrackingSummary + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? total = null, + Object? confirmed = null, + Object? waiting = null, + Object? ready = null, + Object? overdue = null, + }) { + return _then(_VotingShareTrackingSummary( + total: null == total + ? _self.total + : total // ignore: cast_nullable_to_non_nullable + as BigInt, + confirmed: null == confirmed + ? _self.confirmed + : confirmed // ignore: cast_nullable_to_non_nullable + as BigInt, + waiting: null == waiting + ? _self.waiting + : waiting // ignore: cast_nullable_to_non_nullable + as BigInt, + ready: null == ready + ? _self.ready + : ready // ignore: cast_nullable_to_non_nullable + as BigInt, + overdue: null == overdue + ? _self.overdue + : overdue // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// @nodoc +mixin _$VotingShareWorkflow { + int get bundleIndex; + int get proposalId; + int get shareIndex; + String get phase; + + /// Create a copy of VotingShareWorkflow + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingShareWorkflowCopyWith get copyWith => + _$VotingShareWorkflowCopyWithImpl( + this as VotingShareWorkflow, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingShareWorkflow && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + (identical(other.phase, phase) || other.phase == phase)); + } + + @override + int get hashCode => + Object.hash(runtimeType, bundleIndex, proposalId, shareIndex, phase); + + @override + String toString() { + return 'VotingShareWorkflow(bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, phase: $phase)'; + } +} + +/// @nodoc +abstract mixin class $VotingShareWorkflowCopyWith<$Res> { + factory $VotingShareWorkflowCopyWith( + VotingShareWorkflow value, $Res Function(VotingShareWorkflow) _then) = + _$VotingShareWorkflowCopyWithImpl; + @useResult + $Res call({int bundleIndex, int proposalId, int shareIndex, String phase}); +} + +/// @nodoc +class _$VotingShareWorkflowCopyWithImpl<$Res> + implements $VotingShareWorkflowCopyWith<$Res> { + _$VotingShareWorkflowCopyWithImpl(this._self, this._then); + + final VotingShareWorkflow _self; + final $Res Function(VotingShareWorkflow) _then; + + /// Create a copy of VotingShareWorkflow + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? phase = null, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingShareWorkflow]. +extension VotingShareWorkflowPatterns on VotingShareWorkflow { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingShareWorkflow value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingShareWorkflow value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingShareWorkflow value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int bundleIndex, int proposalId, int shareIndex, String phase)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow() when $default != null: + return $default( + _that.bundleIndex, _that.proposalId, _that.shareIndex, _that.phase); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int bundleIndex, int proposalId, int shareIndex, String phase) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow(): + return $default( + _that.bundleIndex, _that.proposalId, _that.shareIndex, _that.phase); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int bundleIndex, int proposalId, int shareIndex, String phase)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareWorkflow() when $default != null: + return $default( + _that.bundleIndex, _that.proposalId, _that.shareIndex, _that.phase); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingShareWorkflow implements VotingShareWorkflow { + const _VotingShareWorkflow( + {required this.bundleIndex, + required this.proposalId, + required this.shareIndex, + required this.phase}); + + @override + final int bundleIndex; + @override + final int proposalId; + @override + final int shareIndex; + @override + final String phase; + + /// Create a copy of VotingShareWorkflow + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingShareWorkflowCopyWith<_VotingShareWorkflow> get copyWith => + __$VotingShareWorkflowCopyWithImpl<_VotingShareWorkflow>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingShareWorkflow && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + (identical(other.phase, phase) || other.phase == phase)); + } + + @override + int get hashCode => + Object.hash(runtimeType, bundleIndex, proposalId, shareIndex, phase); + + @override + String toString() { + return 'VotingShareWorkflow(bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, phase: $phase)'; + } +} + +/// @nodoc +abstract mixin class _$VotingShareWorkflowCopyWith<$Res> + implements $VotingShareWorkflowCopyWith<$Res> { + factory _$VotingShareWorkflowCopyWith(_VotingShareWorkflow value, + $Res Function(_VotingShareWorkflow) _then) = + __$VotingShareWorkflowCopyWithImpl; + @override + @useResult + $Res call({int bundleIndex, int proposalId, int shareIndex, String phase}); +} + +/// @nodoc +class __$VotingShareWorkflowCopyWithImpl<$Res> + implements _$VotingShareWorkflowCopyWith<$Res> { + __$VotingShareWorkflowCopyWithImpl(this._self, this._then); + + final _VotingShareWorkflow _self; + final $Res Function(_VotingShareWorkflow) _then; + + /// Create a copy of VotingShareWorkflow + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? phase = null, + }) { + return _then(_VotingShareWorkflow( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingSignedVoteCommitment { + int get proposalId; + int get choice; + String get voteRoundId; + Uint8List get vanNullifier; + Uint8List get voteAuthorityNoteNew; + Uint8List get voteCommitment; + Uint8List get proof; + int get anchorHeight; + Uint8List get rVpk; + Uint8List get voteAuthSig; + String get commitmentBundleJson; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSignedVoteCommitmentCopyWith + get copyWith => + _$VotingSignedVoteCommitmentCopyWithImpl( + this as VotingSignedVoteCommitment, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSignedVoteCommitment && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.commitmentBundleJson, commitmentBundleJson) || + other.commitmentBundleJson == commitmentBundleJson)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + proposalId, + choice, + voteRoundId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + anchorHeight, + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + commitmentBundleJson); + + @override + String toString() { + return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + } +} + +/// @nodoc +abstract mixin class $VotingSignedVoteCommitmentCopyWith<$Res> { + factory $VotingSignedVoteCommitmentCopyWith(VotingSignedVoteCommitment value, + $Res Function(VotingSignedVoteCommitment) _then) = + _$VotingSignedVoteCommitmentCopyWithImpl; + @useResult + $Res call( + {int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson}); +} + +/// @nodoc +class _$VotingSignedVoteCommitmentCopyWithImpl<$Res> + implements $VotingSignedVoteCommitmentCopyWith<$Res> { + _$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); + + final VotingSignedVoteCommitment _self; + final $Res Function(VotingSignedVoteCommitment) _then; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proposalId = null, + Object? choice = null, + Object? voteRoundId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? anchorHeight = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? commitmentBundleJson = null, + }) { + return _then(_self.copyWith( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + commitmentBundleJson: null == commitmentBundleJson + ? _self.commitmentBundleJson + : commitmentBundleJson // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingSignedVoteCommitment]. +extension VotingSignedVoteCommitmentPatterns on VotingSignedVoteCommitment { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSignedVoteCommitment value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSignedVoteCommitment value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSignedVoteCommitment value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment(): + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSignedVoteCommitment() when $default != null: + return $default( + _that.proposalId, + _that.choice, + _that.voteRoundId, + _that.vanNullifier, + _that.voteAuthorityNoteNew, + _that.voteCommitment, + _that.proof, + _that.anchorHeight, + _that.rVpk, + _that.voteAuthSig, + _that.commitmentBundleJson); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSignedVoteCommitment implements VotingSignedVoteCommitment { + const _VotingSignedVoteCommitment( + {required this.proposalId, + required this.choice, + required this.voteRoundId, + required this.vanNullifier, + required this.voteAuthorityNoteNew, + required this.voteCommitment, + required this.proof, + required this.anchorHeight, + required this.rVpk, + required this.voteAuthSig, + required this.commitmentBundleJson}); + + @override + final int proposalId; + @override + final int choice; + @override + final String voteRoundId; + @override + final Uint8List vanNullifier; + @override + final Uint8List voteAuthorityNoteNew; + @override + final Uint8List voteCommitment; + @override + final Uint8List proof; + @override + final int anchorHeight; + @override + final Uint8List rVpk; + @override + final Uint8List voteAuthSig; + @override + final String commitmentBundleJson; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSignedVoteCommitmentCopyWith<_VotingSignedVoteCommitment> + get copyWith => __$VotingSignedVoteCommitmentCopyWithImpl< + _VotingSignedVoteCommitment>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSignedVoteCommitment && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.voteRoundId, voteRoundId) || + other.voteRoundId == voteRoundId) && + const DeepCollectionEquality() + .equals(other.vanNullifier, vanNullifier) && + const DeepCollectionEquality() + .equals(other.voteAuthorityNoteNew, voteAuthorityNoteNew) && + const DeepCollectionEquality() + .equals(other.voteCommitment, voteCommitment) && + const DeepCollectionEquality().equals(other.proof, proof) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight) && + const DeepCollectionEquality().equals(other.rVpk, rVpk) && + const DeepCollectionEquality() + .equals(other.voteAuthSig, voteAuthSig) && + (identical(other.commitmentBundleJson, commitmentBundleJson) || + other.commitmentBundleJson == commitmentBundleJson)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + proposalId, + choice, + voteRoundId, + const DeepCollectionEquality().hash(vanNullifier), + const DeepCollectionEquality().hash(voteAuthorityNoteNew), + const DeepCollectionEquality().hash(voteCommitment), + const DeepCollectionEquality().hash(proof), + anchorHeight, + const DeepCollectionEquality().hash(rVpk), + const DeepCollectionEquality().hash(voteAuthSig), + commitmentBundleJson); + + @override + String toString() { + return 'VotingSignedVoteCommitment(proposalId: $proposalId, choice: $choice, voteRoundId: $voteRoundId, vanNullifier: $vanNullifier, voteAuthorityNoteNew: $voteAuthorityNoteNew, voteCommitment: $voteCommitment, proof: $proof, anchorHeight: $anchorHeight, rVpk: $rVpk, voteAuthSig: $voteAuthSig, commitmentBundleJson: $commitmentBundleJson)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSignedVoteCommitmentCopyWith<$Res> + implements $VotingSignedVoteCommitmentCopyWith<$Res> { + factory _$VotingSignedVoteCommitmentCopyWith( + _VotingSignedVoteCommitment value, + $Res Function(_VotingSignedVoteCommitment) _then) = + __$VotingSignedVoteCommitmentCopyWithImpl; + @override + @useResult + $Res call( + {int proposalId, + int choice, + String voteRoundId, + Uint8List vanNullifier, + Uint8List voteAuthorityNoteNew, + Uint8List voteCommitment, + Uint8List proof, + int anchorHeight, + Uint8List rVpk, + Uint8List voteAuthSig, + String commitmentBundleJson}); +} + +/// @nodoc +class __$VotingSignedVoteCommitmentCopyWithImpl<$Res> + implements _$VotingSignedVoteCommitmentCopyWith<$Res> { + __$VotingSignedVoteCommitmentCopyWithImpl(this._self, this._then); + + final _VotingSignedVoteCommitment _self; + final $Res Function(_VotingSignedVoteCommitment) _then; + + /// Create a copy of VotingSignedVoteCommitment + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proposalId = null, + Object? choice = null, + Object? voteRoundId = null, + Object? vanNullifier = null, + Object? voteAuthorityNoteNew = null, + Object? voteCommitment = null, + Object? proof = null, + Object? anchorHeight = null, + Object? rVpk = null, + Object? voteAuthSig = null, + Object? commitmentBundleJson = null, + }) { + return _then(_VotingSignedVoteCommitment( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + voteRoundId: null == voteRoundId + ? _self.voteRoundId + : voteRoundId // ignore: cast_nullable_to_non_nullable + as String, + vanNullifier: null == vanNullifier + ? _self.vanNullifier + : vanNullifier // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthorityNoteNew: null == voteAuthorityNoteNew + ? _self.voteAuthorityNoteNew + : voteAuthorityNoteNew // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteCommitment: null == voteCommitment + ? _self.voteCommitment + : voteCommitment // ignore: cast_nullable_to_non_nullable + as Uint8List, + proof: null == proof + ? _self.proof + : proof // ignore: cast_nullable_to_non_nullable + as Uint8List, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + rVpk: null == rVpk + ? _self.rVpk + : rVpk // ignore: cast_nullable_to_non_nullable + as Uint8List, + voteAuthSig: null == voteAuthSig + ? _self.voteAuthSig + : voteAuthSig // ignore: cast_nullable_to_non_nullable + as Uint8List, + commitmentBundleJson: null == commitmentBundleJson + ? _self.commitmentBundleJson + : commitmentBundleJson // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +mixin _$VotingVanWitness { + List get authPath; + int get position; + int get anchorHeight; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVanWitnessCopyWith get copyWith => + _$VotingVanWitnessCopyWithImpl( + this as VotingVanWitness, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVanWitness && + const DeepCollectionEquality().equals(other.authPath, authPath) && + (identical(other.position, position) || + other.position == position) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(authPath), position, anchorHeight); + + @override + String toString() { + return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class $VotingVanWitnessCopyWith<$Res> { + factory $VotingVanWitnessCopyWith( + VotingVanWitness value, $Res Function(VotingVanWitness) _then) = + _$VotingVanWitnessCopyWithImpl; + @useResult + $Res call({List authPath, int position, int anchorHeight}); +} + +/// @nodoc +class _$VotingVanWitnessCopyWithImpl<$Res> + implements $VotingVanWitnessCopyWith<$Res> { + _$VotingVanWitnessCopyWithImpl(this._self, this._then); + + final VotingVanWitness _self; + final $Res Function(VotingVanWitness) _then; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? authPath = null, + Object? position = null, + Object? anchorHeight = null, + }) { + return _then(_self.copyWith( + authPath: null == authPath + ? _self.authPath + : authPath // ignore: cast_nullable_to_non_nullable + as List, + position: null == position + ? _self.position + : position // ignore: cast_nullable_to_non_nullable + as int, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVanWitness]. +extension VotingVanWitnessPatterns on VotingVanWitness { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVanWitness value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVanWitness value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVanWitness value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(List authPath, int position, int anchorHeight)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that.authPath, _that.position, _that.anchorHeight); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(List authPath, int position, int anchorHeight) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness(): + return $default(_that.authPath, _that.position, _that.anchorHeight); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(List authPath, int position, int anchorHeight)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVanWitness() when $default != null: + return $default(_that.authPath, _that.position, _that.anchorHeight); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVanWitness implements VotingVanWitness { + const _VotingVanWitness( + {required final List authPath, + required this.position, + required this.anchorHeight}) + : _authPath = authPath; + + final List _authPath; + @override + List get authPath { + if (_authPath is EqualUnmodifiableListView) return _authPath; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_authPath); + } + + @override + final int position; + @override + final int anchorHeight; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVanWitnessCopyWith<_VotingVanWitness> get copyWith => + __$VotingVanWitnessCopyWithImpl<_VotingVanWitness>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVanWitness && + const DeepCollectionEquality().equals(other._authPath, _authPath) && + (identical(other.position, position) || + other.position == position) && + (identical(other.anchorHeight, anchorHeight) || + other.anchorHeight == anchorHeight)); + } + + @override + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_authPath), position, anchorHeight); + + @override + String toString() { + return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + } +} + +/// @nodoc +abstract mixin class _$VotingVanWitnessCopyWith<$Res> + implements $VotingVanWitnessCopyWith<$Res> { + factory _$VotingVanWitnessCopyWith( + _VotingVanWitness value, $Res Function(_VotingVanWitness) _then) = + __$VotingVanWitnessCopyWithImpl; + @override + @useResult + $Res call({List authPath, int position, int anchorHeight}); +} + +/// @nodoc +class __$VotingVanWitnessCopyWithImpl<$Res> + implements _$VotingVanWitnessCopyWith<$Res> { + __$VotingVanWitnessCopyWithImpl(this._self, this._then); + + final _VotingVanWitness _self; + final $Res Function(_VotingVanWitness) _then; + + /// Create a copy of VotingVanWitness + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? authPath = null, + Object? position = null, + Object? anchorHeight = null, + }) { + return _then(_VotingVanWitness( + authPath: null == authPath + ? _self._authPath + : authPath // ignore: cast_nullable_to_non_nullable + as List, + position: null == position + ? _self.position + : position // ignore: cast_nullable_to_non_nullable + as int, + anchorHeight: null == anchorHeight + ? _self.anchorHeight + : anchorHeight // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +mixin _$VotingVoteCommitStage { + int get proposalId; + int get bundleIndex; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteCommitStageCopyWith get copyWith => + _$VotingVoteCommitStageCopyWithImpl( + this as VotingVoteCommitStage, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteCommitStage && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex)); + } + + @override + int get hashCode => Object.hash(runtimeType, proposalId, bundleIndex); + + @override + String toString() { + return 'VotingVoteCommitStage(proposalId: $proposalId, bundleIndex: $bundleIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteCommitStageCopyWith<$Res> { + factory $VotingVoteCommitStageCopyWith(VotingVoteCommitStage value, + $Res Function(VotingVoteCommitStage) _then) = + _$VotingVoteCommitStageCopyWithImpl; + @useResult + $Res call({int proposalId, int bundleIndex}); +} + +/// @nodoc +class _$VotingVoteCommitStageCopyWithImpl<$Res> + implements $VotingVoteCommitStageCopyWith<$Res> { + _$VotingVoteCommitStageCopyWithImpl(this._self, this._then); + + final VotingVoteCommitStage _self; + final $Res Function(VotingVoteCommitStage) _then; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? proposalId = null, + Object? bundleIndex = null, + }) { + return _then(_self.copyWith( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteCommitStage]. +extension VotingVoteCommitStagePatterns on VotingVoteCommitStage { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap({ + TResult Function(VotingVoteCommitStage_ProofStarting value)? proofStarting, + TResult Function(VotingVoteCommitStage_ProofProgress value)? proofProgress, + TResult Function(VotingVoteCommitStage_SharePayloadsBuilding value)? + sharePayloadsBuilding, + TResult Function(VotingVoteCommitStage_Signing value)? signing, + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting() when proofStarting != null: + return proofStarting(_that); + case VotingVoteCommitStage_ProofProgress() when proofProgress != null: + return proofProgress(_that); + case VotingVoteCommitStage_SharePayloadsBuilding() + when sharePayloadsBuilding != null: + return sharePayloadsBuilding(_that); + case VotingVoteCommitStage_Signing() when signing != null: + return signing(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map({ + required TResult Function(VotingVoteCommitStage_ProofStarting value) + proofStarting, + required TResult Function(VotingVoteCommitStage_ProofProgress value) + proofProgress, + required TResult Function(VotingVoteCommitStage_SharePayloadsBuilding value) + sharePayloadsBuilding, + required TResult Function(VotingVoteCommitStage_Signing value) signing, + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting(): + return proofStarting(_that); + case VotingVoteCommitStage_ProofProgress(): + return proofProgress(_that); + case VotingVoteCommitStage_SharePayloadsBuilding(): + return sharePayloadsBuilding(_that); + case VotingVoteCommitStage_Signing(): + return signing(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(VotingVoteCommitStage_ProofStarting value)? proofStarting, + TResult? Function(VotingVoteCommitStage_ProofProgress value)? proofProgress, + TResult? Function(VotingVoteCommitStage_SharePayloadsBuilding value)? + sharePayloadsBuilding, + TResult? Function(VotingVoteCommitStage_Signing value)? signing, + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting() when proofStarting != null: + return proofStarting(_that); + case VotingVoteCommitStage_ProofProgress() when proofProgress != null: + return proofProgress(_that); + case VotingVoteCommitStage_SharePayloadsBuilding() + when sharePayloadsBuilding != null: + return sharePayloadsBuilding(_that); + case VotingVoteCommitStage_Signing() when signing != null: + return signing(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int proposalId, int bundleIndex)? proofStarting, + TResult Function(int proposalId, int bundleIndex, double progress)? + proofProgress, + TResult Function(int proposalId, int bundleIndex)? sharePayloadsBuilding, + TResult Function(int proposalId, int bundleIndex)? signing, + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting() when proofStarting != null: + return proofStarting(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_ProofProgress() when proofProgress != null: + return proofProgress( + _that.proposalId, _that.bundleIndex, _that.progress); + case VotingVoteCommitStage_SharePayloadsBuilding() + when sharePayloadsBuilding != null: + return sharePayloadsBuilding(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_Signing() when signing != null: + return signing(_that.proposalId, _that.bundleIndex); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when({ + required TResult Function(int proposalId, int bundleIndex) proofStarting, + required TResult Function(int proposalId, int bundleIndex, double progress) + proofProgress, + required TResult Function(int proposalId, int bundleIndex) + sharePayloadsBuilding, + required TResult Function(int proposalId, int bundleIndex) signing, + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting(): + return proofStarting(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_ProofProgress(): + return proofProgress( + _that.proposalId, _that.bundleIndex, _that.progress); + case VotingVoteCommitStage_SharePayloadsBuilding(): + return sharePayloadsBuilding(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_Signing(): + return signing(_that.proposalId, _that.bundleIndex); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int proposalId, int bundleIndex)? proofStarting, + TResult? Function(int proposalId, int bundleIndex, double progress)? + proofProgress, + TResult? Function(int proposalId, int bundleIndex)? sharePayloadsBuilding, + TResult? Function(int proposalId, int bundleIndex)? signing, + }) { + final _that = this; + switch (_that) { + case VotingVoteCommitStage_ProofStarting() when proofStarting != null: + return proofStarting(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_ProofProgress() when proofProgress != null: + return proofProgress( + _that.proposalId, _that.bundleIndex, _that.progress); + case VotingVoteCommitStage_SharePayloadsBuilding() + when sharePayloadsBuilding != null: + return sharePayloadsBuilding(_that.proposalId, _that.bundleIndex); + case VotingVoteCommitStage_Signing() when signing != null: + return signing(_that.proposalId, _that.bundleIndex); + case _: + return null; + } + } +} + +/// @nodoc + +class VotingVoteCommitStage_ProofStarting extends VotingVoteCommitStage { + const VotingVoteCommitStage_ProofStarting( + {required this.proposalId, required this.bundleIndex}) + : super._(); @override - final int position; + final int proposalId; @override - final int anchorHeight; + final int bundleIndex; - /// Create a copy of VotingVanWitness + /// Create a copy of VotingVoteCommitStage /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingVanWitnessCopyWith<_VotingVanWitness> get copyWith => - __$VotingVanWitnessCopyWithImpl<_VotingVanWitness>(this, _$identity); + $VotingVoteCommitStage_ProofStartingCopyWith< + VotingVoteCommitStage_ProofStarting> + get copyWith => _$VotingVoteCommitStage_ProofStartingCopyWithImpl< + VotingVoteCommitStage_ProofStarting>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingVanWitness && - const DeepCollectionEquality().equals(other._authPath, _authPath) && - (identical(other.position, position) || - other.position == position) && - (identical(other.anchorHeight, anchorHeight) || - other.anchorHeight == anchorHeight)); + other is VotingVoteCommitStage_ProofStarting && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex)); } @override - int get hashCode => Object.hash(runtimeType, - const DeepCollectionEquality().hash(_authPath), position, anchorHeight); + int get hashCode => Object.hash(runtimeType, proposalId, bundleIndex); @override String toString() { - return 'VotingVanWitness(authPath: $authPath, position: $position, anchorHeight: $anchorHeight)'; + return 'VotingVoteCommitStage.proofStarting(proposalId: $proposalId, bundleIndex: $bundleIndex)'; } } /// @nodoc -abstract mixin class _$VotingVanWitnessCopyWith<$Res> - implements $VotingVanWitnessCopyWith<$Res> { - factory _$VotingVanWitnessCopyWith( - _VotingVanWitness value, $Res Function(_VotingVanWitness) _then) = - __$VotingVanWitnessCopyWithImpl; +abstract mixin class $VotingVoteCommitStage_ProofStartingCopyWith<$Res> + implements $VotingVoteCommitStageCopyWith<$Res> { + factory $VotingVoteCommitStage_ProofStartingCopyWith( + VotingVoteCommitStage_ProofStarting value, + $Res Function(VotingVoteCommitStage_ProofStarting) _then) = + _$VotingVoteCommitStage_ProofStartingCopyWithImpl; @override @useResult - $Res call({List authPath, int position, int anchorHeight}); + $Res call({int proposalId, int bundleIndex}); } /// @nodoc -class __$VotingVanWitnessCopyWithImpl<$Res> - implements _$VotingVanWitnessCopyWith<$Res> { - __$VotingVanWitnessCopyWithImpl(this._self, this._then); +class _$VotingVoteCommitStage_ProofStartingCopyWithImpl<$Res> + implements $VotingVoteCommitStage_ProofStartingCopyWith<$Res> { + _$VotingVoteCommitStage_ProofStartingCopyWithImpl(this._self, this._then); - final _VotingVanWitness _self; - final $Res Function(_VotingVanWitness) _then; + final VotingVoteCommitStage_ProofStarting _self; + final $Res Function(VotingVoteCommitStage_ProofStarting) _then; - /// Create a copy of VotingVanWitness + /// Create a copy of VotingVoteCommitStage /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? authPath = null, - Object? position = null, - Object? anchorHeight = null, + Object? proposalId = null, + Object? bundleIndex = null, }) { - return _then(_VotingVanWitness( - authPath: null == authPath - ? _self._authPath - : authPath // ignore: cast_nullable_to_non_nullable - as List, - position: null == position - ? _self.position - : position // ignore: cast_nullable_to_non_nullable + return _then(VotingVoteCommitStage_ProofStarting( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class VotingVoteCommitStage_ProofProgress extends VotingVoteCommitStage { + const VotingVoteCommitStage_ProofProgress( + {required this.proposalId, + required this.bundleIndex, + required this.progress}) + : super._(); + + @override + final int proposalId; + @override + final int bundleIndex; + final double progress; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteCommitStage_ProofProgressCopyWith< + VotingVoteCommitStage_ProofProgress> + get copyWith => _$VotingVoteCommitStage_ProofProgressCopyWithImpl< + VotingVoteCommitStage_ProofProgress>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteCommitStage_ProofProgress && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.progress, progress) || + other.progress == progress)); + } + + @override + int get hashCode => + Object.hash(runtimeType, proposalId, bundleIndex, progress); + + @override + String toString() { + return 'VotingVoteCommitStage.proofProgress(proposalId: $proposalId, bundleIndex: $bundleIndex, progress: $progress)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteCommitStage_ProofProgressCopyWith<$Res> + implements $VotingVoteCommitStageCopyWith<$Res> { + factory $VotingVoteCommitStage_ProofProgressCopyWith( + VotingVoteCommitStage_ProofProgress value, + $Res Function(VotingVoteCommitStage_ProofProgress) _then) = + _$VotingVoteCommitStage_ProofProgressCopyWithImpl; + @override + @useResult + $Res call({int proposalId, int bundleIndex, double progress}); +} + +/// @nodoc +class _$VotingVoteCommitStage_ProofProgressCopyWithImpl<$Res> + implements $VotingVoteCommitStage_ProofProgressCopyWith<$Res> { + _$VotingVoteCommitStage_ProofProgressCopyWithImpl(this._self, this._then); + + final VotingVoteCommitStage_ProofProgress _self; + final $Res Function(VotingVoteCommitStage_ProofProgress) _then; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proposalId = null, + Object? bundleIndex = null, + Object? progress = null, + }) { + return _then(VotingVoteCommitStage_ProofProgress( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + progress: null == progress + ? _self.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc + +class VotingVoteCommitStage_SharePayloadsBuilding + extends VotingVoteCommitStage { + const VotingVoteCommitStage_SharePayloadsBuilding( + {required this.proposalId, required this.bundleIndex}) + : super._(); + + @override + final int proposalId; + @override + final int bundleIndex; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteCommitStage_SharePayloadsBuildingCopyWith< + VotingVoteCommitStage_SharePayloadsBuilding> + get copyWith => _$VotingVoteCommitStage_SharePayloadsBuildingCopyWithImpl< + VotingVoteCommitStage_SharePayloadsBuilding>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteCommitStage_SharePayloadsBuilding && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex)); + } + + @override + int get hashCode => Object.hash(runtimeType, proposalId, bundleIndex); + + @override + String toString() { + return 'VotingVoteCommitStage.sharePayloadsBuilding(proposalId: $proposalId, bundleIndex: $bundleIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteCommitStage_SharePayloadsBuildingCopyWith<$Res> + implements $VotingVoteCommitStageCopyWith<$Res> { + factory $VotingVoteCommitStage_SharePayloadsBuildingCopyWith( + VotingVoteCommitStage_SharePayloadsBuilding value, + $Res Function(VotingVoteCommitStage_SharePayloadsBuilding) _then) = + _$VotingVoteCommitStage_SharePayloadsBuildingCopyWithImpl; + @override + @useResult + $Res call({int proposalId, int bundleIndex}); +} + +/// @nodoc +class _$VotingVoteCommitStage_SharePayloadsBuildingCopyWithImpl<$Res> + implements $VotingVoteCommitStage_SharePayloadsBuildingCopyWith<$Res> { + _$VotingVoteCommitStage_SharePayloadsBuildingCopyWithImpl( + this._self, this._then); + + final VotingVoteCommitStage_SharePayloadsBuilding _self; + final $Res Function(VotingVoteCommitStage_SharePayloadsBuilding) _then; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proposalId = null, + Object? bundleIndex = null, + }) { + return _then(VotingVoteCommitStage_SharePayloadsBuilding( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class VotingVoteCommitStage_Signing extends VotingVoteCommitStage { + const VotingVoteCommitStage_Signing( + {required this.proposalId, required this.bundleIndex}) + : super._(); + + @override + final int proposalId; + @override + final int bundleIndex; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteCommitStage_SigningCopyWith + get copyWith => _$VotingVoteCommitStage_SigningCopyWithImpl< + VotingVoteCommitStage_Signing>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteCommitStage_Signing && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex)); + } + + @override + int get hashCode => Object.hash(runtimeType, proposalId, bundleIndex); + + @override + String toString() { + return 'VotingVoteCommitStage.signing(proposalId: $proposalId, bundleIndex: $bundleIndex)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteCommitStage_SigningCopyWith<$Res> + implements $VotingVoteCommitStageCopyWith<$Res> { + factory $VotingVoteCommitStage_SigningCopyWith( + VotingVoteCommitStage_Signing value, + $Res Function(VotingVoteCommitStage_Signing) _then) = + _$VotingVoteCommitStage_SigningCopyWithImpl; + @override + @useResult + $Res call({int proposalId, int bundleIndex}); +} + +/// @nodoc +class _$VotingVoteCommitStage_SigningCopyWithImpl<$Res> + implements $VotingVoteCommitStage_SigningCopyWith<$Res> { + _$VotingVoteCommitStage_SigningCopyWithImpl(this._self, this._then); + + final VotingVoteCommitStage_Signing _self; + final $Res Function(VotingVoteCommitStage_Signing) _then; + + /// Create a copy of VotingVoteCommitStage + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? proposalId = null, + Object? bundleIndex = null, + }) { + return _then(VotingVoteCommitStage_Signing( + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable as int, - anchorHeight: null == anchorHeight - ? _self.anchorHeight - : anchorHeight // ignore: cast_nullable_to_non_nullable + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable as int, )); } @@ -4160,7 +12777,256 @@ mixin _$VotingVoteConfirmation { bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingVoteConfirmation && + other is VotingVoteConfirmation && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition)); + } + + @override + int get hashCode => + Object.hash(runtimeType, txHash, vanLeafPosition, vcTreePosition); + + @override + String toString() { + return 'VotingVoteConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition, vcTreePosition: $vcTreePosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteConfirmationCopyWith<$Res> { + factory $VotingVoteConfirmationCopyWith(VotingVoteConfirmation value, + $Res Function(VotingVoteConfirmation) _then) = + _$VotingVoteConfirmationCopyWithImpl; + @useResult + $Res call({String txHash, int vanLeafPosition, BigInt vcTreePosition}); +} + +/// @nodoc +class _$VotingVoteConfirmationCopyWithImpl<$Res> + implements $VotingVoteConfirmationCopyWith<$Res> { + _$VotingVoteConfirmationCopyWithImpl(this._self, this._then); + + final VotingVoteConfirmation _self; + final $Res Function(VotingVoteConfirmation) _then; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? txHash = null, + Object? vanLeafPosition = null, + Object? vcTreePosition = null, + }) { + return _then(_self.copyWith( + txHash: null == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String, + vanLeafPosition: null == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int, + vcTreePosition: null == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteConfirmation]. +extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingVoteConfirmation value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingVoteConfirmation value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingVoteConfirmation value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation(): + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String txHash, int vanLeafPosition, BigInt vcTreePosition)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingVoteConfirmation() when $default != null: + return $default( + _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingVoteConfirmation implements VotingVoteConfirmation { + const _VotingVoteConfirmation( + {required this.txHash, + required this.vanLeafPosition, + required this.vcTreePosition}); + + @override + final String txHash; + @override + final int vanLeafPosition; + @override + final BigInt vcTreePosition; + + /// Create a copy of VotingVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingVoteConfirmationCopyWith<_VotingVoteConfirmation> get copyWith => + __$VotingVoteConfirmationCopyWithImpl<_VotingVoteConfirmation>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingVoteConfirmation && (identical(other.txHash, txHash) || other.txHash == txHash) && (identical(other.vanLeafPosition, vanLeafPosition) || other.vanLeafPosition == vanLeafPosition) && @@ -4179,32 +13045,34 @@ mixin _$VotingVoteConfirmation { } /// @nodoc -abstract mixin class $VotingVoteConfirmationCopyWith<$Res> { - factory $VotingVoteConfirmationCopyWith(VotingVoteConfirmation value, - $Res Function(VotingVoteConfirmation) _then) = - _$VotingVoteConfirmationCopyWithImpl; +abstract mixin class _$VotingVoteConfirmationCopyWith<$Res> + implements $VotingVoteConfirmationCopyWith<$Res> { + factory _$VotingVoteConfirmationCopyWith(_VotingVoteConfirmation value, + $Res Function(_VotingVoteConfirmation) _then) = + __$VotingVoteConfirmationCopyWithImpl; + @override @useResult $Res call({String txHash, int vanLeafPosition, BigInt vcTreePosition}); } /// @nodoc -class _$VotingVoteConfirmationCopyWithImpl<$Res> - implements $VotingVoteConfirmationCopyWith<$Res> { - _$VotingVoteConfirmationCopyWithImpl(this._self, this._then); +class __$VotingVoteConfirmationCopyWithImpl<$Res> + implements _$VotingVoteConfirmationCopyWith<$Res> { + __$VotingVoteConfirmationCopyWithImpl(this._self, this._then); - final VotingVoteConfirmation _self; - final $Res Function(VotingVoteConfirmation) _then; + final _VotingVoteConfirmation _self; + final $Res Function(_VotingVoteConfirmation) _then; /// Create a copy of VotingVoteConfirmation /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') @override + @pragma('vm:prefer-inline') $Res call({ Object? txHash = null, Object? vanLeafPosition = null, Object? vcTreePosition = null, }) { - return _then(_self.copyWith( + return _then(_VotingVoteConfirmation( txHash: null == txHash ? _self.txHash : txHash // ignore: cast_nullable_to_non_nullable @@ -4221,8 +13089,94 @@ class _$VotingVoteConfirmationCopyWithImpl<$Res> } } -/// Adds pattern-matching-related methods to [VotingVoteConfirmation]. -extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { +/// @nodoc +mixin _$VotingVotePayloads { + VotingVoteSubmission get submission; + List get sharePayloads; + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVotePayloadsCopyWith get copyWith => + _$VotingVotePayloadsCopyWithImpl( + this as VotingVotePayloads, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVotePayloads && + (identical(other.submission, submission) || + other.submission == submission) && + const DeepCollectionEquality() + .equals(other.sharePayloads, sharePayloads)); + } + + @override + int get hashCode => Object.hash(runtimeType, submission, + const DeepCollectionEquality().hash(sharePayloads)); + + @override + String toString() { + return 'VotingVotePayloads(submission: $submission, sharePayloads: $sharePayloads)'; + } +} + +/// @nodoc +abstract mixin class $VotingVotePayloadsCopyWith<$Res> { + factory $VotingVotePayloadsCopyWith( + VotingVotePayloads value, $Res Function(VotingVotePayloads) _then) = + _$VotingVotePayloadsCopyWithImpl; + @useResult + $Res call( + {VotingVoteSubmission submission, + List sharePayloads}); + + $VotingVoteSubmissionCopyWith<$Res> get submission; +} + +/// @nodoc +class _$VotingVotePayloadsCopyWithImpl<$Res> + implements $VotingVotePayloadsCopyWith<$Res> { + _$VotingVotePayloadsCopyWithImpl(this._self, this._then); + + final VotingVotePayloads _self; + final $Res Function(VotingVotePayloads) _then; + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? submission = null, + Object? sharePayloads = null, + }) { + return _then(_self.copyWith( + submission: null == submission + ? _self.submission + : submission // ignore: cast_nullable_to_non_nullable + as VotingVoteSubmission, + sharePayloads: null == sharePayloads + ? _self.sharePayloads + : sharePayloads // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingVotePayloads + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingVoteSubmissionCopyWith<$Res> get submission { + return $VotingVoteSubmissionCopyWith<$Res>(_self.submission, (value) { + return _then(_self.copyWith(submission: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingVotePayloads]. +extension VotingVotePayloadsPatterns on VotingVotePayloads { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -4237,12 +13191,12 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingVoteConfirmation value)? $default, { + TResult Function(_VotingVotePayloads value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVoteConfirmation() when $default != null: + case _VotingVotePayloads() when $default != null: return $default(_that); case _: return orElse(); @@ -4264,11 +13218,11 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult map( - TResult Function(_VotingVoteConfirmation value) $default, + TResult Function(_VotingVotePayloads value) $default, ) { final _that = this; switch (_that) { - case _VotingVoteConfirmation(): + case _VotingVotePayloads(): return $default(_that); } } @@ -4287,11 +13241,11 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingVoteConfirmation value)? $default, + TResult? Function(_VotingVotePayloads value)? $default, ) { final _that = this; switch (_that) { - case _VotingVoteConfirmation() when $default != null: + case _VotingVotePayloads() when $default != null: return $default(_that); case _: return null; @@ -4312,15 +13266,15 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult maybeWhen( - TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition)? + TResult Function(VotingVoteSubmission submission, + List sharePayloads)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVoteConfirmation() when $default != null: - return $default( - _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _VotingVotePayloads() when $default != null: + return $default(_that.submission, _that.sharePayloads); case _: return orElse(); } @@ -4341,14 +13295,14 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult when( - TResult Function(String txHash, int vanLeafPosition, BigInt vcTreePosition) + TResult Function(VotingVoteSubmission submission, + List sharePayloads) $default, ) { final _that = this; switch (_that) { - case _VotingVoteConfirmation(): - return $default( - _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _VotingVotePayloads(): + return $default(_that.submission, _that.sharePayloads); } } @@ -4366,15 +13320,14 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { @optionalTypeArgs TResult? whenOrNull( - TResult? Function( - String txHash, int vanLeafPosition, BigInt vcTreePosition)? + TResult? Function(VotingVoteSubmission submission, + List sharePayloads)? $default, ) { final _that = this; switch (_that) { - case _VotingVoteConfirmation() when $default != null: - return $default( - _that.txHash, _that.vanLeafPosition, _that.vcTreePosition); + case _VotingVotePayloads() when $default != null: + return $default(_that.submission, _that.sharePayloads); case _: return null; } @@ -4383,122 +13336,44 @@ extension VotingVoteConfirmationPatterns on VotingVoteConfirmation { /// @nodoc -class _VotingVoteConfirmation implements VotingVoteConfirmation { - const _VotingVoteConfirmation( - {required this.txHash, - required this.vanLeafPosition, - required this.vcTreePosition}); - - @override - final String txHash; - @override - final int vanLeafPosition; - @override - final BigInt vcTreePosition; - - /// Create a copy of VotingVoteConfirmation - /// with the given fields replaced by the non-null parameter values. - @override - @JsonKey(includeFromJson: false, includeToJson: false) - @pragma('vm:prefer-inline') - _$VotingVoteConfirmationCopyWith<_VotingVoteConfirmation> get copyWith => - __$VotingVoteConfirmationCopyWithImpl<_VotingVoteConfirmation>( - this, _$identity); - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _VotingVoteConfirmation && - (identical(other.txHash, txHash) || other.txHash == txHash) && - (identical(other.vanLeafPosition, vanLeafPosition) || - other.vanLeafPosition == vanLeafPosition) && - (identical(other.vcTreePosition, vcTreePosition) || - other.vcTreePosition == vcTreePosition)); - } - - @override - int get hashCode => - Object.hash(runtimeType, txHash, vanLeafPosition, vcTreePosition); - - @override - String toString() { - return 'VotingVoteConfirmation(txHash: $txHash, vanLeafPosition: $vanLeafPosition, vcTreePosition: $vcTreePosition)'; - } -} +class _VotingVotePayloads implements VotingVotePayloads { + const _VotingVotePayloads( + {required this.submission, + required final List sharePayloads}) + : _sharePayloads = sharePayloads; -/// @nodoc -abstract mixin class _$VotingVoteConfirmationCopyWith<$Res> - implements $VotingVoteConfirmationCopyWith<$Res> { - factory _$VotingVoteConfirmationCopyWith(_VotingVoteConfirmation value, - $Res Function(_VotingVoteConfirmation) _then) = - __$VotingVoteConfirmationCopyWithImpl; @override - @useResult - $Res call({String txHash, int vanLeafPosition, BigInt vcTreePosition}); -} - -/// @nodoc -class __$VotingVoteConfirmationCopyWithImpl<$Res> - implements _$VotingVoteConfirmationCopyWith<$Res> { - __$VotingVoteConfirmationCopyWithImpl(this._self, this._then); - - final _VotingVoteConfirmation _self; - final $Res Function(_VotingVoteConfirmation) _then; - - /// Create a copy of VotingVoteConfirmation - /// with the given fields replaced by the non-null parameter values. + final VotingVoteSubmission submission; + final List _sharePayloads; @override - @pragma('vm:prefer-inline') - $Res call({ - Object? txHash = null, - Object? vanLeafPosition = null, - Object? vcTreePosition = null, - }) { - return _then(_VotingVoteConfirmation( - txHash: null == txHash - ? _self.txHash - : txHash // ignore: cast_nullable_to_non_nullable - as String, - vanLeafPosition: null == vanLeafPosition - ? _self.vanLeafPosition - : vanLeafPosition // ignore: cast_nullable_to_non_nullable - as int, - vcTreePosition: null == vcTreePosition - ? _self.vcTreePosition - : vcTreePosition // ignore: cast_nullable_to_non_nullable - as BigInt, - )); - } -} - -/// @nodoc -mixin _$VotingVotePayloads { - VotingVoteSubmission get submission; - List get sharePayloads; + List get sharePayloads { + if (_sharePayloads is EqualUnmodifiableListView) return _sharePayloads; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_sharePayloads); + } /// Create a copy of VotingVotePayloads /// with the given fields replaced by the non-null parameter values. + @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - $VotingVotePayloadsCopyWith get copyWith => - _$VotingVotePayloadsCopyWithImpl( - this as VotingVotePayloads, _$identity); + _$VotingVotePayloadsCopyWith<_VotingVotePayloads> get copyWith => + __$VotingVotePayloadsCopyWithImpl<_VotingVotePayloads>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is VotingVotePayloads && + other is _VotingVotePayloads && (identical(other.submission, submission) || other.submission == submission) && const DeepCollectionEquality() - .equals(other.sharePayloads, sharePayloads)); + .equals(other._sharePayloads, _sharePayloads)); } @override int get hashCode => Object.hash(runtimeType, submission, - const DeepCollectionEquality().hash(sharePayloads)); + const DeepCollectionEquality().hash(_sharePayloads)); @override String toString() { @@ -4507,41 +13382,44 @@ mixin _$VotingVotePayloads { } /// @nodoc -abstract mixin class $VotingVotePayloadsCopyWith<$Res> { - factory $VotingVotePayloadsCopyWith( - VotingVotePayloads value, $Res Function(VotingVotePayloads) _then) = - _$VotingVotePayloadsCopyWithImpl; +abstract mixin class _$VotingVotePayloadsCopyWith<$Res> + implements $VotingVotePayloadsCopyWith<$Res> { + factory _$VotingVotePayloadsCopyWith( + _VotingVotePayloads value, $Res Function(_VotingVotePayloads) _then) = + __$VotingVotePayloadsCopyWithImpl; + @override @useResult $Res call( {VotingVoteSubmission submission, List sharePayloads}); + @override $VotingVoteSubmissionCopyWith<$Res> get submission; } /// @nodoc -class _$VotingVotePayloadsCopyWithImpl<$Res> - implements $VotingVotePayloadsCopyWith<$Res> { - _$VotingVotePayloadsCopyWithImpl(this._self, this._then); +class __$VotingVotePayloadsCopyWithImpl<$Res> + implements _$VotingVotePayloadsCopyWith<$Res> { + __$VotingVotePayloadsCopyWithImpl(this._self, this._then); - final VotingVotePayloads _self; - final $Res Function(VotingVotePayloads) _then; + final _VotingVotePayloads _self; + final $Res Function(_VotingVotePayloads) _then; /// Create a copy of VotingVotePayloads /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') @override + @pragma('vm:prefer-inline') $Res call({ Object? submission = null, Object? sharePayloads = null, }) { - return _then(_self.copyWith( + return _then(_VotingVotePayloads( submission: null == submission ? _self.submission : submission // ignore: cast_nullable_to_non_nullable as VotingVoteSubmission, sharePayloads: null == sharePayloads - ? _self.sharePayloads + ? _self._sharePayloads : sharePayloads // ignore: cast_nullable_to_non_nullable as List, )); @@ -4558,8 +13436,133 @@ class _$VotingVotePayloadsCopyWithImpl<$Res> } } -/// Adds pattern-matching-related methods to [VotingVotePayloads]. -extension VotingVotePayloadsPatterns on VotingVotePayloads { +/// @nodoc +mixin _$VotingVoteRecovery { + int get bundleIndex; + int get proposalId; + int get choice; + String get phase; + String get workflowPhase; + String? get txHash; + BigInt? get vcTreePosition; + bool get hasCommitmentBundle; + + /// Create a copy of VotingVoteRecovery + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingVoteRecoveryCopyWith get copyWith => + _$VotingVoteRecoveryCopyWithImpl( + this as VotingVoteRecovery, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingVoteRecovery && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.workflowPhase, workflowPhase) || + other.workflowPhase == workflowPhase) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition) && + (identical(other.hasCommitmentBundle, hasCommitmentBundle) || + other.hasCommitmentBundle == hasCommitmentBundle)); + } + + @override + int get hashCode => Object.hash(runtimeType, bundleIndex, proposalId, choice, + phase, workflowPhase, txHash, vcTreePosition, hasCommitmentBundle); + + @override + String toString() { + return 'VotingVoteRecovery(bundleIndex: $bundleIndex, proposalId: $proposalId, choice: $choice, phase: $phase, workflowPhase: $workflowPhase, txHash: $txHash, vcTreePosition: $vcTreePosition, hasCommitmentBundle: $hasCommitmentBundle)'; + } +} + +/// @nodoc +abstract mixin class $VotingVoteRecoveryCopyWith<$Res> { + factory $VotingVoteRecoveryCopyWith( + VotingVoteRecovery value, $Res Function(VotingVoteRecovery) _then) = + _$VotingVoteRecoveryCopyWithImpl; + @useResult + $Res call( + {int bundleIndex, + int proposalId, + int choice, + String phase, + String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + bool hasCommitmentBundle}); +} + +/// @nodoc +class _$VotingVoteRecoveryCopyWithImpl<$Res> + implements $VotingVoteRecoveryCopyWith<$Res> { + _$VotingVoteRecoveryCopyWithImpl(this._self, this._then); + + final VotingVoteRecovery _self; + final $Res Function(VotingVoteRecovery) _then; + + /// Create a copy of VotingVoteRecovery + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? proposalId = null, + Object? choice = null, + Object? phase = null, + Object? workflowPhase = null, + Object? txHash = freezed, + Object? vcTreePosition = freezed, + Object? hasCommitmentBundle = null, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + workflowPhase: null == workflowPhase + ? _self.workflowPhase + : workflowPhase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + vcTreePosition: freezed == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt?, + hasCommitmentBundle: null == hasCommitmentBundle + ? _self.hasCommitmentBundle + : hasCommitmentBundle // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingVoteRecovery]. +extension VotingVoteRecoveryPatterns on VotingVoteRecovery { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -4574,12 +13577,12 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult maybeMap( - TResult Function(_VotingVotePayloads value)? $default, { + TResult Function(_VotingVoteRecovery value)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVotePayloads() when $default != null: + case _VotingVoteRecovery() when $default != null: return $default(_that); case _: return orElse(); @@ -4601,11 +13604,11 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult map( - TResult Function(_VotingVotePayloads value) $default, + TResult Function(_VotingVoteRecovery value) $default, ) { final _that = this; switch (_that) { - case _VotingVotePayloads(): + case _VotingVoteRecovery(): return $default(_that); } } @@ -4624,11 +13627,11 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult? mapOrNull( - TResult? Function(_VotingVotePayloads value)? $default, + TResult? Function(_VotingVoteRecovery value)? $default, ) { final _that = this; switch (_that) { - case _VotingVotePayloads() when $default != null: + case _VotingVoteRecovery() when $default != null: return $default(_that); case _: return null; @@ -4649,15 +13652,30 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult maybeWhen( - TResult Function(VotingVoteSubmission submission, - List sharePayloads)? + TResult Function( + int bundleIndex, + int proposalId, + int choice, + String phase, + String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + bool hasCommitmentBundle)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { - case _VotingVotePayloads() when $default != null: - return $default(_that.submission, _that.sharePayloads); + case _VotingVoteRecovery() when $default != null: + return $default( + _that.bundleIndex, + _that.proposalId, + _that.choice, + _that.phase, + _that.workflowPhase, + _that.txHash, + _that.vcTreePosition, + _that.hasCommitmentBundle); case _: return orElse(); } @@ -4678,14 +13696,29 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult when( - TResult Function(VotingVoteSubmission submission, - List sharePayloads) + TResult Function( + int bundleIndex, + int proposalId, + int choice, + String phase, + String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + bool hasCommitmentBundle) $default, ) { final _that = this; switch (_that) { - case _VotingVotePayloads(): - return $default(_that.submission, _that.sharePayloads); + case _VotingVoteRecovery(): + return $default( + _that.bundleIndex, + _that.proposalId, + _that.choice, + _that.phase, + _that.workflowPhase, + _that.txHash, + _that.vcTreePosition, + _that.hasCommitmentBundle); } } @@ -4703,14 +13736,29 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(VotingVoteSubmission submission, - List sharePayloads)? + TResult? Function( + int bundleIndex, + int proposalId, + int choice, + String phase, + String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + bool hasCommitmentBundle)? $default, ) { final _that = this; switch (_that) { - case _VotingVotePayloads() when $default != null: - return $default(_that.submission, _that.sharePayloads); + case _VotingVoteRecovery() when $default != null: + return $default( + _that.bundleIndex, + _that.proposalId, + _that.choice, + _that.phase, + _that.workflowPhase, + _that.txHash, + _that.vcTreePosition, + _that.hasCommitmentBundle); case _: return null; } @@ -4719,104 +13767,148 @@ extension VotingVotePayloadsPatterns on VotingVotePayloads { /// @nodoc -class _VotingVotePayloads implements VotingVotePayloads { - const _VotingVotePayloads( - {required this.submission, - required final List sharePayloads}) - : _sharePayloads = sharePayloads; +class _VotingVoteRecovery implements VotingVoteRecovery { + const _VotingVoteRecovery( + {required this.bundleIndex, + required this.proposalId, + required this.choice, + required this.phase, + required this.workflowPhase, + this.txHash, + this.vcTreePosition, + required this.hasCommitmentBundle}); @override - final VotingVoteSubmission submission; - final List _sharePayloads; + final int bundleIndex; @override - List get sharePayloads { - if (_sharePayloads is EqualUnmodifiableListView) return _sharePayloads; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_sharePayloads); - } + final int proposalId; + @override + final int choice; + @override + final String phase; + @override + final String workflowPhase; + @override + final String? txHash; + @override + final BigInt? vcTreePosition; + @override + final bool hasCommitmentBundle; - /// Create a copy of VotingVotePayloads + /// Create a copy of VotingVoteRecovery /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') - _$VotingVotePayloadsCopyWith<_VotingVotePayloads> get copyWith => - __$VotingVotePayloadsCopyWithImpl<_VotingVotePayloads>(this, _$identity); + _$VotingVoteRecoveryCopyWith<_VotingVoteRecovery> get copyWith => + __$VotingVoteRecoveryCopyWithImpl<_VotingVoteRecovery>(this, _$identity); @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _VotingVotePayloads && - (identical(other.submission, submission) || - other.submission == submission) && - const DeepCollectionEquality() - .equals(other._sharePayloads, _sharePayloads)); + other is _VotingVoteRecovery && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.choice, choice) || other.choice == choice) && + (identical(other.phase, phase) || other.phase == phase) && + (identical(other.workflowPhase, workflowPhase) || + other.workflowPhase == workflowPhase) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition) && + (identical(other.hasCommitmentBundle, hasCommitmentBundle) || + other.hasCommitmentBundle == hasCommitmentBundle)); } @override - int get hashCode => Object.hash(runtimeType, submission, - const DeepCollectionEquality().hash(_sharePayloads)); + int get hashCode => Object.hash(runtimeType, bundleIndex, proposalId, choice, + phase, workflowPhase, txHash, vcTreePosition, hasCommitmentBundle); @override String toString() { - return 'VotingVotePayloads(submission: $submission, sharePayloads: $sharePayloads)'; + return 'VotingVoteRecovery(bundleIndex: $bundleIndex, proposalId: $proposalId, choice: $choice, phase: $phase, workflowPhase: $workflowPhase, txHash: $txHash, vcTreePosition: $vcTreePosition, hasCommitmentBundle: $hasCommitmentBundle)'; } } /// @nodoc -abstract mixin class _$VotingVotePayloadsCopyWith<$Res> - implements $VotingVotePayloadsCopyWith<$Res> { - factory _$VotingVotePayloadsCopyWith( - _VotingVotePayloads value, $Res Function(_VotingVotePayloads) _then) = - __$VotingVotePayloadsCopyWithImpl; +abstract mixin class _$VotingVoteRecoveryCopyWith<$Res> + implements $VotingVoteRecoveryCopyWith<$Res> { + factory _$VotingVoteRecoveryCopyWith( + _VotingVoteRecovery value, $Res Function(_VotingVoteRecovery) _then) = + __$VotingVoteRecoveryCopyWithImpl; @override @useResult $Res call( - {VotingVoteSubmission submission, - List sharePayloads}); - - @override - $VotingVoteSubmissionCopyWith<$Res> get submission; + {int bundleIndex, + int proposalId, + int choice, + String phase, + String workflowPhase, + String? txHash, + BigInt? vcTreePosition, + bool hasCommitmentBundle}); } /// @nodoc -class __$VotingVotePayloadsCopyWithImpl<$Res> - implements _$VotingVotePayloadsCopyWith<$Res> { - __$VotingVotePayloadsCopyWithImpl(this._self, this._then); +class __$VotingVoteRecoveryCopyWithImpl<$Res> + implements _$VotingVoteRecoveryCopyWith<$Res> { + __$VotingVoteRecoveryCopyWithImpl(this._self, this._then); - final _VotingVotePayloads _self; - final $Res Function(_VotingVotePayloads) _then; + final _VotingVoteRecovery _self; + final $Res Function(_VotingVoteRecovery) _then; - /// Create a copy of VotingVotePayloads + /// Create a copy of VotingVoteRecovery /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({ - Object? submission = null, - Object? sharePayloads = null, + Object? bundleIndex = null, + Object? proposalId = null, + Object? choice = null, + Object? phase = null, + Object? workflowPhase = null, + Object? txHash = freezed, + Object? vcTreePosition = freezed, + Object? hasCommitmentBundle = null, }) { - return _then(_VotingVotePayloads( - submission: null == submission - ? _self.submission - : submission // ignore: cast_nullable_to_non_nullable - as VotingVoteSubmission, - sharePayloads: null == sharePayloads - ? _self._sharePayloads - : sharePayloads // ignore: cast_nullable_to_non_nullable - as List, + return _then(_VotingVoteRecovery( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + choice: null == choice + ? _self.choice + : choice // ignore: cast_nullable_to_non_nullable + as int, + phase: null == phase + ? _self.phase + : phase // ignore: cast_nullable_to_non_nullable + as String, + workflowPhase: null == workflowPhase + ? _self.workflowPhase + : workflowPhase // ignore: cast_nullable_to_non_nullable + as String, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + vcTreePosition: freezed == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt?, + hasCommitmentBundle: null == hasCommitmentBundle + ? _self.hasCommitmentBundle + : hasCommitmentBundle // ignore: cast_nullable_to_non_nullable + as bool, )); } - - /// Create a copy of VotingVotePayloads - /// with the given fields replaced by the non-null parameter values. - @override - @pragma('vm:prefer-inline') - $VotingVoteSubmissionCopyWith<$Res> get submission { - return $VotingVoteSubmissionCopyWith<$Res>(_self.submission, (value) { - return _then(_self.copyWith(submission: value)); - }); - } } /// @nodoc diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index adcfa3d17..d646a82c1 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 88494436; + int get rustContentHash => 1766202353; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -230,6 +230,14 @@ abstract class RustLibApi extends BaseApi { Future crateApiRaptorDecode({required List packet}); + Stream crateApiVotingDelegationBuildSubmission( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c}); + Future crateApiVotingDelegationConfirm( {required String roundId, required int bundleIndex, @@ -237,6 +245,12 @@ abstract class RustLibApi extends BaseApi { required String eventsJson, required Coin c}); + Future crateApiVotingDelegationMarkSubmitted( + {required String roundId, + required int bundleIndex, + required String txHash, + required Coin c}); + Future crateApiVotingDelegationPrepare( {required String roundParamsJson, required String roundName, @@ -246,6 +260,13 @@ abstract class RustLibApi extends BaseApi { required String lightwalletdUrl, required Coin c}); + Future crateApiVotingDelegationPrepareResume( + {required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c}); + Future crateApiVotingDelegationSetup( {required String roundId, required int bundleIndex, required Coin c}); @@ -257,6 +278,12 @@ abstract class RustLibApi extends BaseApi { required String pirServerUrl, required Coin c}); + Future crateApiVotingDelegationTxHash( + {required String roundId, required int bundleIndex, required Coin c}); + + Future crateApiVotingDelegationWireJson( + {required String roundId, required int bundleIndex, required Coin c}); + Future crateApiAccountDeleteAccount( {required int account, required Coin c}); @@ -642,6 +669,47 @@ abstract class RustLibApi extends BaseApi { bool crateApiOpenaliasValidateZcashAddress( {required String address, required Coin c}); + Future crateApiVotingVotechainListRounds( + {required String baseUrl, required Coin c}); + + Future crateApiVotingVotechainResubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}); + + Future crateApiVotingVotechainRoundStatus( + {required String baseUrl, required String roundId, required Coin c}); + + Future crateApiVotingVotechainRoundTally( + {required String baseUrl, required String roundId, required Coin c}); + + Future crateApiVotingVotechainShareStatus( + {required String serverUrl, + required String roundId, + required String shareId, + required Coin c}); + + Future crateApiVotingVotechainSubmitDelegation( + {required String baseUrl, + required String submissionJson, + required Coin c}); + + Future crateApiVotingVotechainSubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}); + + Future crateApiVotingVotechainSubmitVote( + {required String baseUrl, + required String submissionJson, + required Coin c}); + + Future crateApiVotingVotechainTxConfirmation( + {required String baseUrl, required String txHash, required Coin c}); + + Future> crateApiVotingVotingBallotIntents( + {required String roundId, required Coin c}); + Future crateApiVotingVotingCommit( {required String roundId, required int bundleIndex, @@ -649,6 +717,21 @@ abstract class RustLibApi extends BaseApi { required String voteNodeUrl, required Coin c}); + Stream crateApiVotingVotingCommitWithProgress( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}); + + Future crateApiVotingVotingConfigCached( + {required String source, required Coin c}); + + Future crateApiVotingVotingConfigClearCache({required Coin c}); + + Future crateApiVotingVotingConfigResolve( + {required String source, required Coin c}); + Future crateApiVotingVotingConfirm( {required String roundId, required int bundleIndex, @@ -657,16 +740,34 @@ abstract class RustLibApi extends BaseApi { required String eventsJson, required Coin c}); + Future crateApiVotingVotingDraftsLoad( + {required String roundId, required Coin c}); + + Future crateApiVotingVotingDraftsSave( + {required String roundId, required String draftsJson, required Coin c}); + Future crateApiVotingVotingHotkeyCreate({required Coin c}); Future crateApiVotingVotingHotkeyGet({required Coin c}); + Future crateApiVotingVotingMarkVoteSubmitted( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c}); + Future crateApiVotingVotingPayloads( {required String roundId, required int bundleIndex, required int proposalId, required Coin c}); + Future crateApiVotingVotingPlan( + {required String roundId, + required List proposalIds, + required Coin c}); + Future crateApiVotingVotingRecordExecution( {required String roundId, required int bundleIndex, @@ -676,12 +777,91 @@ abstract class RustLibApi extends BaseApi { required String shareDeliveriesJson, required Coin c}); + Future crateApiVotingVotingRecovery( + {required String roundId, required Coin c}); + + Future crateApiVotingVotingRecoveryClear( + {required String roundId, required Coin c}); + + Future crateApiVotingVotingRoundParamsJson( + {required String source, + required String roundId, + required BigInt snapshotHeight, + required List ncRoot, + required List nullifierImtRoot, + required Coin c}); + + Future> crateApiVotingVotingRounds({required Coin c}); + + Future crateApiVotingVotingSetBallotIntent( + {required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, + required Coin c}); + + Future crateApiVotingVotingShareAddServers( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List newUrls, + required Coin c}); + + Future crateApiVotingVotingShareConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c}); + + Future crateApiVotingVotingSharePlan( + {required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List serverUrls, + required bool singleShare, + required Coin c}); + + Future crateApiVotingVotingShareRecord( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List sentToUrls, + required BigInt submitAt, + required Coin c}); + + Future> + crateApiVotingVotingShareUnconfirmed( + {required String roundId, required Coin c}); + + Future crateApiVotingVotingShareWireJson( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, + required Coin c}); + + Future crateApiVotingVotingSyncTree( + {required String roundId, required String voteNodeUrl, required Coin c}); + Future crateApiVotingVotingVanWitness( {required String roundId, required int bundleIndex, required String voteNodeUrl, required Coin c}); + Future crateApiVotingVotingVoteWireJson( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}); + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DartVault; @@ -1816,6 +1996,66 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["packet"], ); + @override + Stream crateApiVotingDelegationBuildSubmission( + {required String roundId, + required int bundleIndex, + required List pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c}) { + final sink = RustStreamSink(); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_voting_delegation_progress_Sse( + sink, serializer); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_list_prim_u_8_loose(pcztBytes, serializer); + sse_encode_opt_box_autoadd_voting_pir_layout(pirLayout, serializer); + sse_encode_String(pirServerUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 37, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_delegation_build, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationBuildSubmissionConstMeta, + argValues: [ + sink, + roundId, + bundleIndex, + pcztBytes, + pirLayout, + pirServerUrl, + c + ], + apiImpl: this, + ), + ), + ); + return sink.stream; + } + + TaskConstMeta get kCrateApiVotingDelegationBuildSubmissionConstMeta => + const TaskConstMeta( + debugName: "delegation_build_submission", + argNames: [ + "sink", + "roundId", + "bundleIndex", + "pcztBytes", + "pirLayout", + "pirServerUrl", + "c" + ], + ); + @override Future crateApiVotingDelegationConfirm( {required String roundId, @@ -1833,7 +2073,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(eventsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 37, port: port_); + funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_confirmation, @@ -1852,6 +2092,40 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["roundId", "bundleIndex", "txHash", "eventsJson", "c"], ); + @override + Future crateApiVotingDelegationMarkSubmitted( + {required String roundId, + required int bundleIndex, + required String txHash, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(txHash, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 39, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationMarkSubmittedConstMeta, + argValues: [roundId, bundleIndex, txHash, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationMarkSubmittedConstMeta => + const TaskConstMeta( + debugName: "delegation_mark_submitted", + argNames: ["roundId", "bundleIndex", "txHash", "c"], + ); + @override Future crateApiVotingDelegationPrepare( {required String roundParamsJson, @@ -1873,7 +2147,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(lightwalletdUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 38, port: port_); + funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_prepared_info, @@ -1908,6 +2182,54 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ], ); + @override + Future crateApiVotingDelegationPrepareResume( + {required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_opt_box_autoadd_u_32(maxRealNotesPerBundle, serializer); + sse_encode_opt_String(lightwalletdUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 41, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_prepared_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingDelegationPrepareResumeConstMeta, + argValues: [ + roundId, + bundleIndex, + maxRealNotesPerBundle, + lightwalletdUrl, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingDelegationPrepareResumeConstMeta => + const TaskConstMeta( + debugName: "delegation_prepare_resume", + argNames: [ + "roundId", + "bundleIndex", + "maxRealNotesPerBundle", + "lightwalletdUrl", + "c" + ], + ); + @override Future crateApiVotingDelegationSetup( {required String roundId, required int bundleIndex, required Coin c}) { @@ -1919,7 +2241,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 39, port: port_); + funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_setup, @@ -1957,7 +2279,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(pirServerUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 40, port: port_); + funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_submission, @@ -1991,89 +2313,149 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiAccountDeleteAccount( - {required int account, required Coin c}) { + Future crateApiVotingDelegationTxHash( + {required String roundId, required int bundleIndex, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_u_32(account, serializer); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 41, port: port_); + funcId: 44, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_unit, + decodeSuccessData: sse_decode_opt_String, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiAccountDeleteAccountConstMeta, - argValues: [account, c], + constMeta: kCrateApiVotingDelegationTxHashConstMeta, + argValues: [roundId, bundleIndex, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => + TaskConstMeta get kCrateApiVotingDelegationTxHashConstMeta => const TaskConstMeta( - debugName: "delete_account", - argNames: ["account", "c"], + debugName: "delegation_tx_hash", + argNames: ["roundId", "bundleIndex", "c"], ); @override - Future crateApiAccountDeleteCategories( - {required List ids, required Coin c}) { + Future crateApiVotingDelegationWireJson( + {required String roundId, required int bundleIndex, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 42, port: port_); + funcId: 45, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_unit, + decodeSuccessData: sse_decode_opt_String, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiAccountDeleteCategoriesConstMeta, - argValues: [ids, c], + constMeta: kCrateApiVotingDelegationWireJsonConstMeta, + argValues: [roundId, bundleIndex, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => + TaskConstMeta get kCrateApiVotingDelegationWireJsonConstMeta => const TaskConstMeta( - debugName: "delete_categories", - argNames: ["ids", "c"], + debugName: "delegation_wire_json", + argNames: ["roundId", "bundleIndex", "c"], ); @override - Future crateApiContactsDeleteContacts( - {required List ids, required Coin c}) { + Future crateApiAccountDeleteAccount( + {required int account, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 43, port: port_); + funcId: 46, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiContactsDeleteContactsConstMeta, - argValues: [ids, c], + constMeta: kCrateApiAccountDeleteAccountConstMeta, + argValues: [account, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => + TaskConstMeta get kCrateApiAccountDeleteAccountConstMeta => const TaskConstMeta( - debugName: "delete_contacts", + debugName: "delete_account", + argNames: ["account", "c"], + ); + + @override + Future crateApiAccountDeleteCategories( + {required List ids, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 47, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountDeleteCategoriesConstMeta, + argValues: [ids, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAccountDeleteCategoriesConstMeta => + const TaskConstMeta( + debugName: "delete_categories", + argNames: ["ids", "c"], + ); + + @override + Future crateApiContactsDeleteContacts( + {required List ids, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_32_loose(ids, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 48, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiContactsDeleteContactsConstMeta, + argValues: [ids, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => + const TaskConstMeta( + debugName: "delete_contacts", argNames: ["ids", "c"], ); @@ -2087,7 +2469,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 44, port: port_); + funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2117,7 +2499,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_dkg_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 45, port: port_); + funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2148,7 +2530,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_signing_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 46, port: port_); + funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2175,7 +2557,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 47, port: port_); + funcId: 52, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2202,7 +2584,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_signing_event(a, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 48, port: port_); + funcId: 53, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2230,7 +2612,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(path, serializer); sse_encode_box_autoadd_raptor_q_params(params, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 49, port: port_); + funcId: 54, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_list_prim_u_8_strict, @@ -2255,7 +2637,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 50, port: port_); + funcId: 55, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2284,7 +2666,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(passphrase, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 51, port: port_); + funcId: 56, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2311,7 +2693,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 52, port: port_); + funcId: 57, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2339,7 +2721,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 53, port: port_); + funcId: 58, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2369,7 +2751,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(aggregate, serializer); sse_encode_u_8(poolFilter, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 54, port: port_); + funcId: 59, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2400,7 +2782,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 55, port: port_); + funcId: 60, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_u_32_f_64, @@ -2430,7 +2812,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 56, port: port_); + funcId: 61, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_string_f_64_bool, @@ -2458,7 +2840,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 57, port: port_); + funcId: 62, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2487,7 +2869,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 58, port: port_); + funcId: 63, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2516,7 +2898,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(currency, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 59, port: port_); + funcId: 64, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2545,7 +2927,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 60, port: port_); + funcId: 65, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact_match, @@ -2571,7 +2953,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 61, port: port_); + funcId: 66, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_frost_sign_params, @@ -2598,7 +2980,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 62, port: port_); + funcId: 67, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2625,7 +3007,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 63, port: port_); + funcId: 68, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2650,7 +3032,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2679,7 +3061,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); + funcId: 70, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2708,7 +3090,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); + funcId: 71, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2735,7 +3117,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); + funcId: 72, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, @@ -2764,7 +3146,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); + funcId: 73, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -2793,7 +3175,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 69, port: port_); + funcId: 74, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_seed, @@ -2823,7 +3205,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(pools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 70, port: port_); + funcId: 75, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2852,7 +3234,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 71, port: port_); + funcId: 76, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -2881,7 +3263,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); + funcId: 77, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -2908,7 +3290,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 73, port: port_); + funcId: 78, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2935,7 +3317,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 74, port: port_); + funcId: 79, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -2961,7 +3343,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 75, port: port_); + funcId: 80, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -2993,7 +3375,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 76, port: port_); + funcId: 81, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -3022,7 +3404,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); + funcId: 82, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -3049,7 +3431,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83)!; }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -3077,7 +3459,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 79, port: port_); + funcId: 84, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3104,7 +3486,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); + funcId: 85, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -3131,7 +3513,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); + funcId: 86, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -3159,7 +3541,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); + funcId: 87, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -3184,7 +3566,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(data, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 83)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 88)!; }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3211,7 +3593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); + funcId: 89, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3237,7 +3619,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); + funcId: 90, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3265,7 +3647,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); + funcId: 91, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -3292,7 +3674,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); + funcId: 92, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3319,7 +3701,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 88, port: port_); + funcId: 93, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3345,7 +3727,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 89, port: port_); + funcId: 94, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3375,7 +3757,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 90, port: port_); + funcId: 95, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3404,7 +3786,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); + funcId: 96, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3430,7 +3812,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 92, port: port_); + funcId: 97, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3455,7 +3837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 93, port: port_); + funcId: 98, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3481,7 +3863,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); + funcId: 99, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3507,7 +3889,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 95, port: port_); + funcId: 100, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3533,7 +3915,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 96, port: port_); + funcId: 101, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3557,7 +3939,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 97)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 102)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3590,7 +3973,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 98, port: port_); + funcId: 103, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3618,7 +4001,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( append, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 99, port: port_); + funcId: 104, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -3647,7 +4030,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 100, port: port_); + funcId: 105, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -3674,7 +4057,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 101, port: port_); + funcId: 106, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3701,7 +4084,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 102, port: port_); + funcId: 107, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3729,7 +4112,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 103)!; + funcId: 108)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3755,7 +4138,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 104)!; + funcId: 109)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3782,7 +4165,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105)!; + funcId: 110)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3809,7 +4192,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106)!; + funcId: 111)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3835,7 +4218,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(url, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107)!; + funcId: 112)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3862,7 +4245,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108)!; + funcId: 113)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3890,7 +4273,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109)!; + funcId: 114)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3917,7 +4300,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110, port: port_); + funcId: 115, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3956,7 +4339,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111, port: port_); + funcId: 116, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3998,7 +4381,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112, port: port_); + funcId: 117, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -4025,7 +4408,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113, port: port_); + funcId: 118, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -4052,7 +4435,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114, port: port_); + funcId: 119, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -4080,7 +4463,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + funcId: 120, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -4106,7 +4489,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + funcId: 121, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -4132,7 +4515,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + funcId: 122, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -4158,7 +4541,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + funcId: 123, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -4184,7 +4567,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + funcId: 124, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -4210,7 +4593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); + funcId: 125, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -4236,7 +4619,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); + funcId: 126, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -4263,7 +4646,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + funcId: 127, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -4292,7 +4675,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); + funcId: 128, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4321,7 +4704,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + funcId: 129, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4348,7 +4731,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + funcId: 130, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -4377,7 +4760,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + funcId: 131, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4403,7 +4786,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); + funcId: 132, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4431,7 +4814,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128, port: port_); + funcId: 133, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4458,7 +4841,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129)!; + funcId: 134)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, @@ -4489,7 +4872,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); + funcId: 135, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4520,7 +4903,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + funcId: 136, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4548,7 +4931,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + funcId: 137, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4577,7 +4960,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + funcId: 138, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4603,7 +4986,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134, port: port_); + funcId: 139, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -4629,7 +5012,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); + funcId: 140, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4658,7 +5041,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136)!; + funcId: 141)!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -4687,7 +5070,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + funcId: 142, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4716,7 +5099,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + funcId: 143, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4744,7 +5127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); + funcId: 144, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4774,7 +5157,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + funcId: 145, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4804,7 +5187,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141, port: port_); + funcId: 146, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4831,7 +5214,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + funcId: 147, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4858,7 +5241,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); + funcId: 148, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4886,7 +5269,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); + funcId: 149, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4914,7 +5297,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); + funcId: 150, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -4942,7 +5325,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146, port: port_); + funcId: 151, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -4972,7 +5355,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147, port: port_); + funcId: 152, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5001,7 +5384,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + funcId: 153, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5030,7 +5413,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + funcId: 154, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5059,7 +5442,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + funcId: 155, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5096,7 +5479,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); + funcId: 156, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5122,7 +5505,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152)!; + funcId: 157)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5149,7 +5532,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153)!; + funcId: 158)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5179,7 +5562,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + funcId: 159, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5209,7 +5592,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + funcId: 160, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5239,7 +5622,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + funcId: 161, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5269,7 +5652,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157, port: port_); + funcId: 162, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5296,7 +5679,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158, port: port_); + funcId: 163, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5324,7 +5707,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159, port: port_); + funcId: 164, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5356,7 +5739,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + funcId: 165, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5387,7 +5770,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + funcId: 166, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5413,7 +5796,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + funcId: 167, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5449,7 +5832,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + funcId: 168, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5491,7 +5874,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); + funcId: 169, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -5538,7 +5921,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165)!; + funcId: 170)!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5564,7 +5947,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); + funcId: 171, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5593,7 +5976,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167)!; + funcId: 172)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5619,7 +6002,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + funcId: 173, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -5645,7 +6028,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + funcId: 174, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -5671,7 +6054,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170, port: port_); + funcId: 175, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -5697,7 +6080,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); + funcId: 176, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -5723,7 +6106,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172, port: port_); + funcId: 177, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -5753,7 +6136,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173)!; + funcId: 178)!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5779,7 +6162,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 174, port: port_); + funcId: 179, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5806,7 +6189,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 175, port: port_); + funcId: 180, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5835,7 +6218,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 176, port: port_); + funcId: 181, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5871,7 +6254,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 177, port: port_); + funcId: 182, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5903,7 +6286,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 178, port: port_); + funcId: 183, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5930,7 +6313,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 179)!; + funcId: 184)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5959,7 +6342,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 180)!; + funcId: 185)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -5978,48 +6361,988 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["address", "c"], ); + @override + Future crateApiVotingVotechainListRounds( + {required String baseUrl, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 186, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainListRoundsConstMeta, + argValues: [baseUrl, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainListRoundsConstMeta => + const TaskConstMeta( + debugName: "votechain_list_rounds", + argNames: ["baseUrl", "c"], + ); + + @override + Future crateApiVotingVotechainResubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(serverUrl, serializer); + sse_encode_String(payloadJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 187, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainResubmitShareConstMeta, + argValues: [serverUrl, payloadJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainResubmitShareConstMeta => + const TaskConstMeta( + debugName: "votechain_resubmit_share", + argNames: ["serverUrl", "payloadJson", "c"], + ); + + @override + Future crateApiVotingVotechainRoundStatus( + {required String baseUrl, required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 188, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainRoundStatusConstMeta, + argValues: [baseUrl, roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainRoundStatusConstMeta => + const TaskConstMeta( + debugName: "votechain_round_status", + argNames: ["baseUrl", "roundId", "c"], + ); + + @override + Future crateApiVotingVotechainRoundTally( + {required String baseUrl, required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 189, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainRoundTallyConstMeta, + argValues: [baseUrl, roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainRoundTallyConstMeta => + const TaskConstMeta( + debugName: "votechain_round_tally", + argNames: ["baseUrl", "roundId", "c"], + ); + + @override + Future crateApiVotingVotechainShareStatus( + {required String serverUrl, + required String roundId, + required String shareId, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(serverUrl, serializer); + sse_encode_String(roundId, serializer); + sse_encode_String(shareId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 190, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainShareStatusConstMeta, + argValues: [serverUrl, roundId, shareId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainShareStatusConstMeta => + const TaskConstMeta( + debugName: "votechain_share_status", + argNames: ["serverUrl", "roundId", "shareId", "c"], + ); + + @override + Future crateApiVotingVotechainSubmitDelegation( + {required String baseUrl, + required String submissionJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_String(submissionJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 191, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainSubmitDelegationConstMeta, + argValues: [baseUrl, submissionJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainSubmitDelegationConstMeta => + const TaskConstMeta( + debugName: "votechain_submit_delegation", + argNames: ["baseUrl", "submissionJson", "c"], + ); + + @override + Future crateApiVotingVotechainSubmitShare( + {required String serverUrl, + required String payloadJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(serverUrl, serializer); + sse_encode_String(payloadJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 192, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainSubmitShareConstMeta, + argValues: [serverUrl, payloadJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainSubmitShareConstMeta => + const TaskConstMeta( + debugName: "votechain_submit_share", + argNames: ["serverUrl", "payloadJson", "c"], + ); + + @override + Future crateApiVotingVotechainSubmitVote( + {required String baseUrl, + required String submissionJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_String(submissionJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 193, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainSubmitVoteConstMeta, + argValues: [baseUrl, submissionJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainSubmitVoteConstMeta => + const TaskConstMeta( + debugName: "votechain_submit_vote", + argNames: ["baseUrl", "submissionJson", "c"], + ); + + @override + Future crateApiVotingVotechainTxConfirmation( + {required String baseUrl, required String txHash, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(baseUrl, serializer); + sse_encode_String(txHash, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 194, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_chain_response, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotechainTxConfirmationConstMeta, + argValues: [baseUrl, txHash, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotechainTxConfirmationConstMeta => + const TaskConstMeta( + debugName: "votechain_tx_confirmation", + argNames: ["baseUrl", "txHash", "c"], + ); + + @override + Future> crateApiVotingVotingBallotIntents( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 195, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_ballot_intent, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingBallotIntentsConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingBallotIntentsConstMeta => + const TaskConstMeta( + debugName: "voting_ballot_intents", + argNames: ["roundId", "c"], + ); + @override Future crateApiVotingVotingCommit( {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(draftsJson, serializer); + sse_encode_String(voteNodeUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 196, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_commitments, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingCommitConstMeta, + argValues: [roundId, bundleIndex, draftsJson, voteNodeUrl, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingCommitConstMeta => const TaskConstMeta( + debugName: "voting_commit", + argNames: ["roundId", "bundleIndex", "draftsJson", "voteNodeUrl", "c"], + ); + + @override + Stream crateApiVotingVotingCommitWithProgress( + {required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c}) { + final sink = RustStreamSink(); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_voting_vote_commit_stage_Sse( + sink, serializer); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_String(draftsJson, serializer); + sse_encode_String(voteNodeUrl, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 197, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_commitments, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingCommitWithProgressConstMeta, + argValues: [sink, roundId, bundleIndex, draftsJson, voteNodeUrl, c], + apiImpl: this, + ), + ), + ); + return sink.stream; + } + + TaskConstMeta get kCrateApiVotingVotingCommitWithProgressConstMeta => + const TaskConstMeta( + debugName: "voting_commit_with_progress", + argNames: [ + "sink", + "roundId", + "bundleIndex", + "draftsJson", + "voteNodeUrl", + "c" + ], + ); + + @override + Future crateApiVotingVotingConfigCached( + {required String source, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(source, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 198, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_voting_config, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingConfigCachedConstMeta, + argValues: [source, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingConfigCachedConstMeta => + const TaskConstMeta( + debugName: "voting_config_cached", + argNames: ["source", "c"], + ); + + @override + Future crateApiVotingVotingConfigClearCache({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 199, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingConfigClearCacheConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingConfigClearCacheConstMeta => + const TaskConstMeta( + debugName: "voting_config_clear_cache", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingConfigResolve( + {required String source, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(source, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 200, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_config, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingConfigResolveConstMeta, + argValues: [source, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingConfigResolveConstMeta => + const TaskConstMeta( + debugName: "voting_config_resolve", + argNames: ["source", "c"], + ); + + @override + Future crateApiVotingVotingConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_String(txHash, serializer); + sse_encode_String(eventsJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 201, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_confirmation, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingConfirmConstMeta, + argValues: [roundId, bundleIndex, proposalId, txHash, eventsJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingConfirmConstMeta => + const TaskConstMeta( + debugName: "voting_confirm", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "txHash", + "eventsJson", + "c" + ], + ); + + @override + Future crateApiVotingVotingDraftsLoad( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 202, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingDraftsLoadConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingDraftsLoadConstMeta => + const TaskConstMeta( + debugName: "voting_drafts_load", + argNames: ["roundId", "c"], + ); + + @override + Future crateApiVotingVotingDraftsSave( + {required String roundId, required String draftsJson, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_String(draftsJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 203, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingDraftsSaveConstMeta, + argValues: [roundId, draftsJson, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingDraftsSaveConstMeta => + const TaskConstMeta( + debugName: "voting_drafts_save", + argNames: ["roundId", "draftsJson", "c"], + ); + + @override + Future crateApiVotingVotingHotkeyCreate({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 204, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingHotkeyCreateConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingHotkeyCreateConstMeta => + const TaskConstMeta( + debugName: "voting_hotkey_create", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingHotkeyGet({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 205, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingHotkeyGetConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingHotkeyGetConstMeta => + const TaskConstMeta( + debugName: "voting_hotkey_get", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingMarkVoteSubmitted( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_String(txHash, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 206, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingMarkVoteSubmittedConstMeta, + argValues: [roundId, bundleIndex, proposalId, txHash, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingMarkVoteSubmittedConstMeta => + const TaskConstMeta( + debugName: "voting_mark_vote_submitted", + argNames: ["roundId", "bundleIndex", "proposalId", "txHash", "c"], + ); + + @override + Future crateApiVotingVotingPayloads( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 207, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_vote_payloads, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingPayloadsConstMeta, + argValues: [roundId, bundleIndex, proposalId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingPayloadsConstMeta => + const TaskConstMeta( + debugName: "voting_payloads", + argNames: ["roundId", "bundleIndex", "proposalId", "c"], + ); + + @override + Future crateApiVotingVotingPlan( + {required String roundId, + required List proposalIds, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_list_prim_u_32_loose(proposalIds, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 208, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_round_plan, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingPlanConstMeta, + argValues: [roundId, proposalIds, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingPlanConstMeta => const TaskConstMeta( + debugName: "voting_plan", + argNames: ["roundId", "proposalIds", "c"], + ); + + @override + Future crateApiVotingVotingRecordExecution( + {required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_String(voteTxHash, serializer); + sse_encode_u_64(vcTreePosition, serializer); + sse_encode_String(shareDeliveriesJson, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 209, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRecordExecutionConstMeta, + argValues: [ + roundId, + bundleIndex, + proposalId, + voteTxHash, + vcTreePosition, + shareDeliveriesJson, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRecordExecutionConstMeta => + const TaskConstMeta( + debugName: "voting_record_execution", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "voteTxHash", + "vcTreePosition", + "shareDeliveriesJson", + "c" + ], + ); + + @override + Future crateApiVotingVotingRecovery( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 210, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_round_recovery, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRecoveryConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRecoveryConstMeta => + const TaskConstMeta( + debugName: "voting_recovery", + argNames: ["roundId", "c"], + ); + + @override + Future crateApiVotingVotingRecoveryClear( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 211, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRecoveryClearConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRecoveryClearConstMeta => + const TaskConstMeta( + debugName: "voting_recovery_clear", + argNames: ["roundId", "c"], + ); + + @override + Future crateApiVotingVotingRoundParamsJson( + {required String source, + required String roundId, + required BigInt snapshotHeight, + required List ncRoot, + required List nullifierImtRoot, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(source, serializer); + sse_encode_String(roundId, serializer); + sse_encode_u_64(snapshotHeight, serializer); + sse_encode_list_prim_u_8_loose(ncRoot, serializer); + sse_encode_list_prim_u_8_loose(nullifierImtRoot, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 212, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRoundParamsJsonConstMeta, + argValues: [ + source, + roundId, + snapshotHeight, + ncRoot, + nullifierImtRoot, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRoundParamsJsonConstMeta => + const TaskConstMeta( + debugName: "voting_round_params_json", + argNames: [ + "source", + "roundId", + "snapshotHeight", + "ncRoot", + "nullifierImtRoot", + "c" + ], + ); + + @override + Future> crateApiVotingVotingRounds({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 213, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_round_info, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRoundsConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRoundsConstMeta => const TaskConstMeta( + debugName: "voting_rounds", + argNames: ["c"], + ); + + @override + Future crateApiVotingVotingSetBallotIntent( + {required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); - sse_encode_u_32(bundleIndex, serializer); - sse_encode_String(draftsJson, serializer); - sse_encode_String(voteNodeUrl, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_bool(skipped, serializer); + sse_encode_u_32(choice, serializer); + sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 181, port: port_); + funcId: 214, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_voting_vote_commitments, + decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingCommitConstMeta, - argValues: [roundId, bundleIndex, draftsJson, voteNodeUrl, c], + constMeta: kCrateApiVotingVotingSetBallotIntentConstMeta, + argValues: [roundId, proposalId, skipped, choice, numOptions, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingCommitConstMeta => const TaskConstMeta( - debugName: "voting_commit", - argNames: ["roundId", "bundleIndex", "draftsJson", "voteNodeUrl", "c"], + TaskConstMeta get kCrateApiVotingVotingSetBallotIntentConstMeta => + const TaskConstMeta( + debugName: "voting_set_ballot_intent", + argNames: [ + "roundId", + "proposalId", + "skipped", + "choice", + "numOptions", + "c" + ], ); @override - Future crateApiVotingVotingConfirm( + Future crateApiVotingVotingShareAddServers( {required String roundId, required int bundleIndex, required int proposalId, - required String txHash, - required String eventsJson, + required int shareIndex, + required List newUrls, required Coin c}) { return handler.executeNormal( NormalTask( @@ -6028,95 +7351,222 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); - sse_encode_String(txHash, serializer); - sse_encode_String(eventsJson, serializer); + sse_encode_u_32(shareIndex, serializer); + sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 182, port: port_); + funcId: 215, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_voting_vote_confirmation, + decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingConfirmConstMeta, - argValues: [roundId, bundleIndex, proposalId, txHash, eventsJson, c], + constMeta: kCrateApiVotingVotingShareAddServersConstMeta, + argValues: [roundId, bundleIndex, proposalId, shareIndex, newUrls, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingConfirmConstMeta => + TaskConstMeta get kCrateApiVotingVotingShareAddServersConstMeta => const TaskConstMeta( - debugName: "voting_confirm", + debugName: "voting_share_add_servers", argNames: [ "roundId", "bundleIndex", "proposalId", - "txHash", - "eventsJson", + "shareIndex", + "newUrls", "c" ], ); @override - Future crateApiVotingVotingHotkeyCreate({required Coin c}) { + Future crateApiVotingVotingShareConfirm( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 183, port: port_); + funcId: 216, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_String, + decodeSuccessData: sse_decode_unit, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingHotkeyCreateConstMeta, - argValues: [c], + constMeta: kCrateApiVotingVotingShareConfirmConstMeta, + argValues: [roundId, bundleIndex, proposalId, shareIndex, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingHotkeyCreateConstMeta => + TaskConstMeta get kCrateApiVotingVotingShareConfirmConstMeta => const TaskConstMeta( - debugName: "voting_hotkey_create", - argNames: ["c"], + debugName: "voting_share_confirm", + argNames: ["roundId", "bundleIndex", "proposalId", "shareIndex", "c"], ); @override - Future crateApiVotingVotingHotkeyGet({required Coin c}) { + Future crateApiVotingVotingSharePlan( + {required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List serverUrls, + required bool singleShare, + required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_64(now, serializer); + sse_encode_u_64(ceremonyStart, serializer); + sse_encode_opt_box_autoadd_u_64(voteEnd, serializer); + sse_encode_list_String(serverUrls, serializer); + sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 184, port: port_); + funcId: 217, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_String, + decodeSuccessData: sse_decode_voting_share_plan, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingHotkeyGetConstMeta, - argValues: [c], + constMeta: kCrateApiVotingVotingSharePlanConstMeta, + argValues: [ + roundId, + now, + ceremonyStart, + voteEnd, + serverUrls, + singleShare, + c + ], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingHotkeyGetConstMeta => + TaskConstMeta get kCrateApiVotingVotingSharePlanConstMeta => const TaskConstMeta( - debugName: "voting_hotkey_get", - argNames: ["c"], + debugName: "voting_share_plan", + argNames: [ + "roundId", + "now", + "ceremonyStart", + "voteEnd", + "serverUrls", + "singleShare", + "c" + ], ); @override - Future crateApiVotingVotingPayloads( + Future crateApiVotingVotingShareRecord( + {required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List sentToUrls, + required BigInt submitAt, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(shareIndex, serializer); + sse_encode_list_String(sentToUrls, serializer); + sse_encode_u_64(submitAt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 218, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingShareRecordConstMeta, + argValues: [ + roundId, + bundleIndex, + proposalId, + shareIndex, + sentToUrls, + submitAt, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingShareRecordConstMeta => + const TaskConstMeta( + debugName: "voting_share_record", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "shareIndex", + "sentToUrls", + "submitAt", + "c" + ], + ); + + @override + Future> + crateApiVotingVotingShareUnconfirmed( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 219, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_share_delegation_record, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingShareUnconfirmedConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingShareUnconfirmedConstMeta => + const TaskConstMeta( + debugName: "voting_share_unconfirmed", + argNames: ["roundId", "c"], + ); + + @override + Future crateApiVotingVotingShareWireJson( {required String roundId, required int bundleIndex, required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, required Coin c}) { return handler.executeNormal( NormalTask( @@ -6125,35 +7575,81 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(shareIndex, serializer); + sse_encode_opt_box_autoadd_u_64(vcTreePosition, serializer); + sse_encode_u_64(submitAt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 220, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingShareWireJsonConstMeta, + argValues: [ + roundId, + bundleIndex, + proposalId, + shareIndex, + vcTreePosition, + submitAt, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingShareWireJsonConstMeta => + const TaskConstMeta( + debugName: "voting_share_wire_json", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "shareIndex", + "vcTreePosition", + "submitAt", + "c" + ], + ); + + @override + Future crateApiVotingVotingSyncTree( + {required String roundId, required String voteNodeUrl, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 185, port: port_); + funcId: 221, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_voting_vote_payloads, + decodeSuccessData: sse_decode_u_32, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingPayloadsConstMeta, - argValues: [roundId, bundleIndex, proposalId, c], + constMeta: kCrateApiVotingVotingSyncTreeConstMeta, + argValues: [roundId, voteNodeUrl, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingPayloadsConstMeta => + TaskConstMeta get kCrateApiVotingVotingSyncTreeConstMeta => const TaskConstMeta( - debugName: "voting_payloads", - argNames: ["roundId", "bundleIndex", "proposalId", "c"], + debugName: "voting_sync_tree", + argNames: ["roundId", "voteNodeUrl", "c"], ); @override - Future crateApiVotingVotingRecordExecution( + Future crateApiVotingVotingVanWitness( {required String roundId, required int bundleIndex, - required int proposalId, - required String voteTxHash, - required BigInt vcTreePosition, - required String shareDeliveriesJson, + required String voteNodeUrl, required Coin c}) { return handler.executeNormal( NormalTask( @@ -6161,52 +7657,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); - sse_encode_u_32(proposalId, serializer); - sse_encode_String(voteTxHash, serializer); - sse_encode_u_64(vcTreePosition, serializer); - sse_encode_String(shareDeliveriesJson, serializer); + sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 186, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_unit, + decodeSuccessData: sse_decode_voting_van_witness, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingRecordExecutionConstMeta, - argValues: [ - roundId, - bundleIndex, - proposalId, - voteTxHash, - vcTreePosition, - shareDeliveriesJson, - c - ], + constMeta: kCrateApiVotingVotingVanWitnessConstMeta, + argValues: [roundId, bundleIndex, voteNodeUrl, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingRecordExecutionConstMeta => + TaskConstMeta get kCrateApiVotingVotingVanWitnessConstMeta => const TaskConstMeta( - debugName: "voting_record_execution", - argNames: [ - "roundId", - "bundleIndex", - "proposalId", - "voteTxHash", - "vcTreePosition", - "shareDeliveriesJson", - "c" - ], + debugName: "voting_van_witness", + argNames: ["roundId", "bundleIndex", "voteNodeUrl", "c"], ); @override - Future crateApiVotingVotingVanWitness( + Future crateApiVotingVotingVoteWireJson( {required String roundId, required int bundleIndex, - required String voteNodeUrl, + required int proposalId, required Coin c}) { return handler.executeNormal( NormalTask( @@ -6214,26 +7691,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); - sse_encode_String(voteNodeUrl, serializer); + sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 187, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_voting_van_witness, + decodeSuccessData: sse_decode_String, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiVotingVotingVanWitnessConstMeta, - argValues: [roundId, bundleIndex, voteNodeUrl, c], + constMeta: kCrateApiVotingVotingVoteWireJsonConstMeta, + argValues: [roundId, bundleIndex, proposalId, c], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiVotingVotingVanWitnessConstMeta => + TaskConstMeta get kCrateApiVotingVotingVoteWireJsonConstMeta => const TaskConstMeta( - debugName: "voting_van_witness", - argNames: ["roundId", "bundleIndex", "voteNodeUrl", "c"], + debugName: "voting_vote_wire_json", + argNames: ["roundId", "bundleIndex", "proposalId", "c"], ); Future Function(int, dynamic) @@ -6480,6 +7957,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { throw UnimplementedError(); } + @protected + RustStreamSink + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(); + } + + @protected + RustStreamSink + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(); + } + @protected String dco_decode_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -6663,6 +8154,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as int; } + @protected + VotingCompletedVoteDisplay + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_voting_completed_vote_display(raw); + } + + @protected + VotingConfig dco_decode_box_autoadd_voting_config(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_voting_config(raw); + } + @protected VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7049,6 +8553,45 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List).map(dco_decode_tx_spend).toList(); } + @protected + List dco_decode_list_voting_ballot_intent(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_ballot_intent).toList(); + } + + @protected + List dco_decode_list_voting_completed_vote_choice( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_completed_vote_choice) + .toList(); + } + + @protected + List dco_decode_list_voting_config_round(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_config_round).toList(); + } + + @protected + List dco_decode_list_voting_delegation_recovery( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_delegation_recovery) + .toList(); + } + + @protected + List dco_decode_list_voting_delegation_status( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_delegation_status) + .toList(); + } + @protected List dco_decode_list_voting_encrypted_share( dynamic raw) { @@ -7058,12 +8601,59 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { .toList(); } + @protected + List dco_decode_list_voting_next_step(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_next_step).toList(); + } + + @protected + List dco_decode_list_voting_round_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_round_info).toList(); + } + + @protected + List dco_decode_list_voting_service_endpoint( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_service_endpoint) + .toList(); + } + + @protected + List + dco_decode_list_voting_share_delegation_record(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_share_delegation_record) + .toList(); + } + @protected List dco_decode_list_voting_share_payload(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List).map(dco_decode_voting_share_payload).toList(); } + @protected + List dco_decode_list_voting_share_plan_item( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_share_plan_item) + .toList(); + } + + @protected + List dco_decode_list_voting_share_workflow(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List) + .map(dco_decode_voting_share_workflow) + .toList(); + } + @protected List dco_decode_list_voting_signed_vote_commitment(dynamic raw) { @@ -7073,6 +8663,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { .toList(); } + @protected + List dco_decode_list_voting_vote_recovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_voting_vote_recovery).toList(); + } + @protected List dco_decode_list_zsa_holding(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7368,6 +8964,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_u_8(raw); } + @protected + VotingCompletedVoteDisplay? + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null + ? null + : dco_decode_box_autoadd_voting_completed_vote_display(raw); + } + + @protected + VotingConfig? dco_decode_opt_box_autoadd_voting_config(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_voting_config(raw); + } + + @protected + VotingPirLayout? dco_decode_opt_box_autoadd_voting_pir_layout(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_voting_pir_layout(raw); + } + @protected List? dco_decode_opt_list_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7862,6 +9479,99 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return UsizeArray4(dco_decode_list_prim_usize_strict(raw)); } + @protected + VotingBallotIntent dco_decode_voting_ballot_intent(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return VotingBallotIntent( + proposalId: dco_decode_u_32(arr[0]), + skipped: dco_decode_bool(arr[1]), + choice: dco_decode_opt_box_autoadd_u_32(arr[2]), + ); + } + + @protected + VotingChainResponse dco_decode_voting_chain_response(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingChainResponse( + statusCode: dco_decode_u_16(arr[0]), + body: dco_decode_String(arr[1]), + ); + } + + @protected + VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingCompletedVoteChoice( + proposalId: dco_decode_u_32(arr[0]), + choice: dco_decode_opt_box_autoadd_u_32(arr[1]), + ); + } + + @protected + VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingCompletedVoteDisplay( + choices: dco_decode_list_voting_completed_vote_choice(arr[0]), + votedAt: dco_decode_opt_box_autoadd_u_64(arr[1]), + ); + } + + @protected + VotingConfig dco_decode_voting_config(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + return VotingConfig( + source: dco_decode_String(arr[0]), + sourceFingerprint: dco_decode_String(arr[1]), + trustedKeyFingerprint: dco_decode_String(arr[2]), + switchKind: dco_decode_String(arr[3]), + voteServers: dco_decode_list_voting_service_endpoint(arr[4]), + pirServers: dco_decode_list_voting_service_endpoint(arr[5]), + pirLayout: dco_decode_opt_box_autoadd_voting_pir_layout(arr[6]), + rounds: dco_decode_list_voting_config_round(arr[7]), + ); + } + + @protected + VotingConfigRound dco_decode_voting_config_round(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingConfigRound( + roundId: dco_decode_String(arr[0]), + eaPk: dco_decode_list_prim_u_8_strict(arr[1]), + ); + } + + @protected + VotingDelegationBuild dco_decode_voting_delegation_build(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingDelegationBuild( + submission: dco_decode_voting_delegation_submission(arr[0]), + wireJson: dco_decode_String(arr[1]), + ); + } + @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( dynamic raw) { @@ -7875,6 +9585,48 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingDelegationProgress dco_decode_voting_delegation_progress(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + switch (raw[0]) { + case 0: + return VotingDelegationProgress_SelectingNotes(); + case 1: + return VotingDelegationProgress_PcztBuilding(); + case 2: + return VotingDelegationProgress_PcztBuilt(); + case 3: + return VotingDelegationProgress_ProofStarting(); + case 4: + return VotingDelegationProgress_ProofProgress( + progress: dco_decode_f_64(raw[1]), + ); + case 5: + return VotingDelegationProgress_ProofComplete(); + case 6: + return VotingDelegationProgress_SigningPayload(); + case 7: + return VotingDelegationProgress_PayloadReady(); + default: + throw Exception("unreachable"); + } + } + + @protected + VotingDelegationRecovery dco_decode_voting_delegation_recovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + return VotingDelegationRecovery( + bundleIndex: dco_decode_u_32(arr[0]), + phase: dco_decode_String(arr[1]), + workflowPhase: dco_decode_String(arr[2]), + txHash: dco_decode_opt_String(arr[3]), + vanLeafPosition: dco_decode_opt_box_autoadd_u_32(arr[4]), + ); + } + @protected VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7891,6 +9643,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingDelegationStatus dco_decode_voting_delegation_status(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return VotingDelegationStatus( + bundleIndex: dco_decode_u_32(arr[0]), + phase: dco_decode_String(arr[1]), + txHash: dco_decode_opt_String(arr[2]), + ); + } + @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( dynamic raw) { @@ -7926,6 +9691,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingNextStep dco_decode_voting_next_step(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + return VotingNextStep( + kind: dco_decode_String(arr[0]), + bundleIndex: dco_decode_u_32(arr[1]), + proposalId: dco_decode_u_32(arr[2]), + choice: dco_decode_u_32(arr[3]), + shareIndex: dco_decode_u_32(arr[4]), + ); + } + @protected VotingPirLayout dco_decode_voting_pir_layout(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7955,6 +9735,98 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingRoundInfo dco_decode_voting_round_info(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 7) + throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + return VotingRoundInfo( + roundId: dco_decode_String(arr[0]), + network: dco_decode_String(arr[1]), + snapshotHeight: dco_decode_u_64(arr[2]), + hotkeyAddress: dco_decode_opt_String(arr[3]), + eligibleWeightZatoshi: dco_decode_opt_box_autoadd_u_64(arr[4]), + bundleCount: dco_decode_u_32(arr[5]), + createdAt: dco_decode_u_64(arr[6]), + ); + } + + @protected + VotingRoundPlan dco_decode_voting_round_plan(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 14) + throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); + return VotingRoundPlan( + roundId: dco_decode_String(arr[0]), + pendingRecovery: dco_decode_bool(arr[1]), + nextSteps: dco_decode_list_voting_next_step(arr[2]), + openProposals: dco_decode_list_prim_u_32_strict(arr[3]), + allDecided: dco_decode_bool(arr[4]), + delegationStatuses: dco_decode_list_voting_delegation_status(arr[5]), + blockingRecovery: dco_decode_bool(arr[6]), + blockingShareWork: dco_decode_bool(arr[7]), + hotkeyBound: dco_decode_bool(arr[8]), + completedVoteArtifact: dco_decode_bool(arr[9]), + completedForDisplay: dco_decode_bool(arr[10]), + completedVoteDisplay: + dco_decode_opt_box_autoadd_voting_completed_vote_display(arr[11]), + needsDraftSetup: dco_decode_bool(arr[12]), + primaryAction: dco_decode_String(arr[13]), + ); + } + + @protected + VotingRoundRecovery dco_decode_voting_round_recovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 7) + throw Exception('unexpected arr length: expect 7 but see ${arr.length}'); + return VotingRoundRecovery( + roundId: dco_decode_String(arr[0]), + bundleCount: dco_decode_u_32(arr[1]), + delegation: dco_decode_list_voting_delegation_recovery(arr[2]), + votes: dco_decode_list_voting_vote_recovery(arr[3]), + shares: dco_decode_list_voting_share_workflow(arr[4]), + shareDelegations: dco_decode_list_voting_share_delegation_record(arr[5]), + unconfirmedShareDelegations: + dco_decode_list_voting_share_delegation_record(arr[6]), + ); + } + + @protected + VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingServiceEndpoint( + url: dco_decode_String(arr[0]), + label: dco_decode_String(arr[1]), + ); + } + + @protected + VotingShareDelegationRecord dco_decode_voting_share_delegation_record( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 9) + throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + return VotingShareDelegationRecord( + roundId: dco_decode_String(arr[0]), + bundleIndex: dco_decode_u_32(arr[1]), + proposalId: dco_decode_u_32(arr[2]), + shareIndex: dco_decode_u_32(arr[3]), + sentToUrls: dco_decode_list_String(arr[4]), + nullifier: dco_decode_list_prim_u_8_strict(arr[5]), + confirmed: dco_decode_bool(arr[6]), + submitAt: dco_decode_u_64(arr[7]), + createdAt: dco_decode_u_64(arr[8]), + ); + } + @protected VotingSharePayload dco_decode_voting_share_payload(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -7973,6 +9845,63 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingSharePlan dco_decode_voting_share_plan(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return VotingSharePlan( + summary: dco_decode_voting_share_tracking_summary(arr[0]), + nextTrackingDelaySecs: dco_decode_opt_box_autoadd_u_64(arr[1]), + lastMoment: dco_decode_bool(arr[2]), + submissions: dco_decode_list_voting_share_plan_item(arr[3]), + ); + } + + @protected + VotingSharePlanItem dco_decode_voting_share_plan_item(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); + return VotingSharePlanItem( + submitAt: dco_decode_u_64(arr[0]), + targetCount: dco_decode_u_32(arr[1]), + targetServers: dco_decode_list_String(arr[2]), + ); + } + + @protected + VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 5) + throw Exception('unexpected arr length: expect 5 but see ${arr.length}'); + return VotingShareTrackingSummary( + total: dco_decode_u_64(arr[0]), + confirmed: dco_decode_u_64(arr[1]), + waiting: dco_decode_u_64(arr[2]), + ready: dco_decode_u_64(arr[3]), + overdue: dco_decode_u_64(arr[4]), + ); + } + + @protected + VotingShareWorkflow dco_decode_voting_share_workflow(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return VotingShareWorkflow( + bundleIndex: dco_decode_u_32(arr[0]), + proposalId: dco_decode_u_32(arr[1]), + shareIndex: dco_decode_u_32(arr[2]), + phase: dco_decode_String(arr[3]), + ); + } + @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( dynamic raw) { @@ -8008,6 +9937,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingVoteCommitStage dco_decode_voting_vote_commit_stage(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + switch (raw[0]) { + case 0: + return VotingVoteCommitStage_ProofStarting( + proposalId: dco_decode_u_32(raw[1]), + bundleIndex: dco_decode_u_32(raw[2]), + ); + case 1: + return VotingVoteCommitStage_ProofProgress( + proposalId: dco_decode_u_32(raw[1]), + bundleIndex: dco_decode_u_32(raw[2]), + progress: dco_decode_f_64(raw[3]), + ); + case 2: + return VotingVoteCommitStage_SharePayloadsBuilding( + proposalId: dco_decode_u_32(raw[1]), + bundleIndex: dco_decode_u_32(raw[2]), + ); + case 3: + return VotingVoteCommitStage_Signing( + proposalId: dco_decode_u_32(raw[1]), + bundleIndex: dco_decode_u_32(raw[2]), + ); + default: + throw Exception("unreachable"); + } + } + @protected VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -8045,6 +10004,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingVoteRecovery dco_decode_voting_vote_recovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 8) + throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); + return VotingVoteRecovery( + bundleIndex: dco_decode_u_32(arr[0]), + proposalId: dco_decode_u_32(arr[1]), + choice: dco_decode_u_32(arr[2]), + phase: dco_decode_String(arr[3]), + workflowPhase: dco_decode_String(arr[4]), + txHash: dco_decode_opt_String(arr[5]), + vcTreePosition: dco_decode_opt_box_autoadd_u_64(arr[6]), + hasCommitmentBundle: dco_decode_bool(arr[7]), + ); + } + @protected VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -8269,6 +10246,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { throw UnimplementedError('Unreachable ()'); } + @protected + RustStreamSink + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + throw UnimplementedError('Unreachable ()'); + } + + @protected + RustStreamSink + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + throw UnimplementedError('Unreachable ()'); + } + @protected String sse_decode_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -8480,6 +10473,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_u_8(deserializer)); } + @protected + VotingCompletedVoteDisplay + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_voting_completed_vote_display(deserializer)); + } + + @protected + VotingConfig sse_decode_box_autoadd_voting_config( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_voting_config(deserializer)); + } + @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( SseDeserializer deserializer) { @@ -9015,39 +11023,183 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - List sse_decode_list_tx_spend(SseDeserializer deserializer) { + List sse_decode_list_tx_spend(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_tx_spend(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_ballot_intent( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_ballot_intent(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_completed_vote_choice( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_completed_vote_choice(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_config_round( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_config_round(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_delegation_recovery( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_delegation_recovery(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_delegation_status( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_delegation_status(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_encrypted_share( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_encrypted_share(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_next_step( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_next_step(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_round_info( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_round_info(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_service_endpoint( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_service_endpoint(deserializer)); + } + return ans_; + } + + @protected + List + sse_decode_list_voting_share_delegation_record( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_share_delegation_record(deserializer)); + } + return ans_; + } + + @protected + List sse_decode_list_voting_share_payload( + SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); - var ans_ = []; + var ans_ = []; for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_tx_spend(deserializer)); + ans_.add(sse_decode_voting_share_payload(deserializer)); } return ans_; } @protected - List sse_decode_list_voting_encrypted_share( + List sse_decode_list_voting_share_plan_item( SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); - var ans_ = []; + var ans_ = []; for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_voting_encrypted_share(deserializer)); + ans_.add(sse_decode_voting_share_plan_item(deserializer)); } return ans_; } @protected - List sse_decode_list_voting_share_payload( + List sse_decode_list_voting_share_workflow( SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); - var ans_ = []; + var ans_ = []; for (var idx_ = 0; idx_ < len_; ++idx_) { - ans_.add(sse_decode_voting_share_payload(deserializer)); + ans_.add(sse_decode_voting_share_workflow(deserializer)); } return ans_; } @@ -9066,6 +11218,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_voting_vote_recovery( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_vote_recovery(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -9422,6 +11587,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + VotingCompletedVoteDisplay? + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_voting_completed_vote_display( + deserializer)); + } else { + return null; + } + } + + @protected + VotingConfig? sse_decode_opt_box_autoadd_voting_config( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_voting_config(deserializer)); + } else { + return null; + } + } + + @protected + VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_voting_pir_layout(deserializer)); + } else { + return null; + } + } + @protected List? sse_decode_opt_list_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -9944,6 +12147,89 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return UsizeArray4(inner); } + @protected + VotingBallotIntent sse_decode_voting_ballot_intent( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_proposalId = sse_decode_u_32(deserializer); + var var_skipped = sse_decode_bool(deserializer); + var var_choice = sse_decode_opt_box_autoadd_u_32(deserializer); + return VotingBallotIntent( + proposalId: var_proposalId, skipped: var_skipped, choice: var_choice); + } + + @protected + VotingChainResponse sse_decode_voting_chain_response( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_statusCode = sse_decode_u_16(deserializer); + var var_body = sse_decode_String(deserializer); + return VotingChainResponse(statusCode: var_statusCode, body: var_body); + } + + @protected + VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_proposalId = sse_decode_u_32(deserializer); + var var_choice = sse_decode_opt_box_autoadd_u_32(deserializer); + return VotingCompletedVoteChoice( + proposalId: var_proposalId, choice: var_choice); + } + + @protected + VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_choices = + sse_decode_list_voting_completed_vote_choice(deserializer); + var var_votedAt = sse_decode_opt_box_autoadd_u_64(deserializer); + return VotingCompletedVoteDisplay( + choices: var_choices, votedAt: var_votedAt); + } + + @protected + VotingConfig sse_decode_voting_config(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_source = sse_decode_String(deserializer); + var var_sourceFingerprint = sse_decode_String(deserializer); + var var_trustedKeyFingerprint = sse_decode_String(deserializer); + var var_switchKind = sse_decode_String(deserializer); + var var_voteServers = sse_decode_list_voting_service_endpoint(deserializer); + var var_pirServers = sse_decode_list_voting_service_endpoint(deserializer); + var var_pirLayout = + sse_decode_opt_box_autoadd_voting_pir_layout(deserializer); + var var_rounds = sse_decode_list_voting_config_round(deserializer); + return VotingConfig( + source: var_source, + sourceFingerprint: var_sourceFingerprint, + trustedKeyFingerprint: var_trustedKeyFingerprint, + switchKind: var_switchKind, + voteServers: var_voteServers, + pirServers: var_pirServers, + pirLayout: var_pirLayout, + rounds: var_rounds); + } + + @protected + VotingConfigRound sse_decode_voting_config_round( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_eaPk = sse_decode_list_prim_u_8_strict(deserializer); + return VotingConfigRound(roundId: var_roundId, eaPk: var_eaPk); + } + + @protected + VotingDelegationBuild sse_decode_voting_delegation_build( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_submission = sse_decode_voting_delegation_submission(deserializer); + var var_wireJson = sse_decode_String(deserializer); + return VotingDelegationBuild( + submission: var_submission, wireJson: var_wireJson); + } + @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( SseDeserializer deserializer) { @@ -9954,6 +12240,52 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { txHash: var_txHash, vanLeafPosition: var_vanLeafPosition); } + @protected + VotingDelegationProgress sse_decode_voting_delegation_progress( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var tag_ = sse_decode_i_32(deserializer); + switch (tag_) { + case 0: + return VotingDelegationProgress_SelectingNotes(); + case 1: + return VotingDelegationProgress_PcztBuilding(); + case 2: + return VotingDelegationProgress_PcztBuilt(); + case 3: + return VotingDelegationProgress_ProofStarting(); + case 4: + var var_progress = sse_decode_f_64(deserializer); + return VotingDelegationProgress_ProofProgress(progress: var_progress); + case 5: + return VotingDelegationProgress_ProofComplete(); + case 6: + return VotingDelegationProgress_SigningPayload(); + case 7: + return VotingDelegationProgress_PayloadReady(); + default: + throw UnimplementedError(''); + } + } + + @protected + VotingDelegationRecovery sse_decode_voting_delegation_recovery( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_phase = sse_decode_String(deserializer); + var var_workflowPhase = sse_decode_String(deserializer); + var var_txHash = sse_decode_opt_String(deserializer); + var var_vanLeafPosition = sse_decode_opt_box_autoadd_u_32(deserializer); + return VotingDelegationRecovery( + bundleIndex: var_bundleIndex, + phase: var_phase, + workflowPhase: var_workflowPhase, + txHash: var_txHash, + vanLeafPosition: var_vanLeafPosition); + } + @protected VotingDelegationSetup sse_decode_voting_delegation_setup( SseDeserializer deserializer) { @@ -9973,6 +12305,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { tx1Effects: var_tx1Effects); } + @protected + VotingDelegationStatus sse_decode_voting_delegation_status( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_phase = sse_decode_String(deserializer); + var var_txHash = sse_decode_opt_String(deserializer); + return VotingDelegationStatus( + bundleIndex: var_bundleIndex, phase: var_phase, txHash: var_txHash); + } + @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( SseDeserializer deserializer) { @@ -10013,6 +12356,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { c1: var_c1, c2: var_c2, shareIndex: var_shareIndex); } + @protected + VotingNextStep sse_decode_voting_next_step(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_kind = sse_decode_String(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_choice = sse_decode_u_32(deserializer); + var var_shareIndex = sse_decode_u_32(deserializer); + return VotingNextStep( + kind: var_kind, + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + choice: var_choice, + shareIndex: var_shareIndex); + } + @protected VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -10044,6 +12403,121 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { roundName: var_roundName); } + @protected + VotingRoundInfo sse_decode_voting_round_info(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_network = sse_decode_String(deserializer); + var var_snapshotHeight = sse_decode_u_64(deserializer); + var var_hotkeyAddress = sse_decode_opt_String(deserializer); + var var_eligibleWeightZatoshi = + sse_decode_opt_box_autoadd_u_64(deserializer); + var var_bundleCount = sse_decode_u_32(deserializer); + var var_createdAt = sse_decode_u_64(deserializer); + return VotingRoundInfo( + roundId: var_roundId, + network: var_network, + snapshotHeight: var_snapshotHeight, + hotkeyAddress: var_hotkeyAddress, + eligibleWeightZatoshi: var_eligibleWeightZatoshi, + bundleCount: var_bundleCount, + createdAt: var_createdAt); + } + + @protected + VotingRoundPlan sse_decode_voting_round_plan(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_pendingRecovery = sse_decode_bool(deserializer); + var var_nextSteps = sse_decode_list_voting_next_step(deserializer); + var var_openProposals = sse_decode_list_prim_u_32_strict(deserializer); + var var_allDecided = sse_decode_bool(deserializer); + var var_delegationStatuses = + sse_decode_list_voting_delegation_status(deserializer); + var var_blockingRecovery = sse_decode_bool(deserializer); + var var_blockingShareWork = sse_decode_bool(deserializer); + var var_hotkeyBound = sse_decode_bool(deserializer); + var var_completedVoteArtifact = sse_decode_bool(deserializer); + var var_completedForDisplay = sse_decode_bool(deserializer); + var var_completedVoteDisplay = + sse_decode_opt_box_autoadd_voting_completed_vote_display(deserializer); + var var_needsDraftSetup = sse_decode_bool(deserializer); + var var_primaryAction = sse_decode_String(deserializer); + return VotingRoundPlan( + roundId: var_roundId, + pendingRecovery: var_pendingRecovery, + nextSteps: var_nextSteps, + openProposals: var_openProposals, + allDecided: var_allDecided, + delegationStatuses: var_delegationStatuses, + blockingRecovery: var_blockingRecovery, + blockingShareWork: var_blockingShareWork, + hotkeyBound: var_hotkeyBound, + completedVoteArtifact: var_completedVoteArtifact, + completedForDisplay: var_completedForDisplay, + completedVoteDisplay: var_completedVoteDisplay, + needsDraftSetup: var_needsDraftSetup, + primaryAction: var_primaryAction); + } + + @protected + VotingRoundRecovery sse_decode_voting_round_recovery( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_bundleCount = sse_decode_u_32(deserializer); + var var_delegation = + sse_decode_list_voting_delegation_recovery(deserializer); + var var_votes = sse_decode_list_voting_vote_recovery(deserializer); + var var_shares = sse_decode_list_voting_share_workflow(deserializer); + var var_shareDelegations = + sse_decode_list_voting_share_delegation_record(deserializer); + var var_unconfirmedShareDelegations = + sse_decode_list_voting_share_delegation_record(deserializer); + return VotingRoundRecovery( + roundId: var_roundId, + bundleCount: var_bundleCount, + delegation: var_delegation, + votes: var_votes, + shares: var_shares, + shareDelegations: var_shareDelegations, + unconfirmedShareDelegations: var_unconfirmedShareDelegations); + } + + @protected + VotingServiceEndpoint sse_decode_voting_service_endpoint( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_url = sse_decode_String(deserializer); + var var_label = sse_decode_String(deserializer); + return VotingServiceEndpoint(url: var_url, label: var_label); + } + + @protected + VotingShareDelegationRecord sse_decode_voting_share_delegation_record( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_shareIndex = sse_decode_u_32(deserializer); + var var_sentToUrls = sse_decode_list_String(deserializer); + var var_nullifier = sse_decode_list_prim_u_8_strict(deserializer); + var var_confirmed = sse_decode_bool(deserializer); + var var_submitAt = sse_decode_u_64(deserializer); + var var_createdAt = sse_decode_u_64(deserializer); + return VotingShareDelegationRecord( + roundId: var_roundId, + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + sentToUrls: var_sentToUrls, + nullifier: var_nullifier, + confirmed: var_confirmed, + submitAt: var_submitAt, + createdAt: var_createdAt); + } + @protected VotingSharePayload sse_decode_voting_share_payload( SseDeserializer deserializer) { @@ -10067,6 +12541,66 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { primaryBlind: var_primaryBlind); } + @protected + VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_summary = sse_decode_voting_share_tracking_summary(deserializer); + var var_nextTrackingDelaySecs = + sse_decode_opt_box_autoadd_u_64(deserializer); + var var_lastMoment = sse_decode_bool(deserializer); + var var_submissions = sse_decode_list_voting_share_plan_item(deserializer); + return VotingSharePlan( + summary: var_summary, + nextTrackingDelaySecs: var_nextTrackingDelaySecs, + lastMoment: var_lastMoment, + submissions: var_submissions); + } + + @protected + VotingSharePlanItem sse_decode_voting_share_plan_item( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_submitAt = sse_decode_u_64(deserializer); + var var_targetCount = sse_decode_u_32(deserializer); + var var_targetServers = sse_decode_list_String(deserializer); + return VotingSharePlanItem( + submitAt: var_submitAt, + targetCount: var_targetCount, + targetServers: var_targetServers); + } + + @protected + VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_total = sse_decode_u_64(deserializer); + var var_confirmed = sse_decode_u_64(deserializer); + var var_waiting = sse_decode_u_64(deserializer); + var var_ready = sse_decode_u_64(deserializer); + var var_overdue = sse_decode_u_64(deserializer); + return VotingShareTrackingSummary( + total: var_total, + confirmed: var_confirmed, + waiting: var_waiting, + ready: var_ready, + overdue: var_overdue); + } + + @protected + VotingShareWorkflow sse_decode_voting_share_workflow( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_shareIndex = sse_decode_u_32(deserializer); + var var_phase = sse_decode_String(deserializer); + return VotingShareWorkflow( + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + phase: var_phase); + } + @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( SseDeserializer deserializer) { @@ -10109,6 +12643,41 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { anchorHeight: var_anchorHeight); } + @protected + VotingVoteCommitStage sse_decode_voting_vote_commit_stage( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var tag_ = sse_decode_i_32(deserializer); + switch (tag_) { + case 0: + var var_proposalId = sse_decode_u_32(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + return VotingVoteCommitStage_ProofStarting( + proposalId: var_proposalId, bundleIndex: var_bundleIndex); + case 1: + var var_proposalId = sse_decode_u_32(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_progress = sse_decode_f_64(deserializer); + return VotingVoteCommitStage_ProofProgress( + proposalId: var_proposalId, + bundleIndex: var_bundleIndex, + progress: var_progress); + case 2: + var var_proposalId = sse_decode_u_32(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + return VotingVoteCommitStage_SharePayloadsBuilding( + proposalId: var_proposalId, bundleIndex: var_bundleIndex); + case 3: + var var_proposalId = sse_decode_u_32(deserializer); + var var_bundleIndex = sse_decode_u_32(deserializer); + return VotingVoteCommitStage_Signing( + proposalId: var_proposalId, bundleIndex: var_bundleIndex); + default: + throw UnimplementedError(''); + } + } + @protected VotingVoteCommitments sse_decode_voting_vote_commitments( SseDeserializer deserializer) { @@ -10143,6 +12712,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { submission: var_submission, sharePayloads: var_sharePayloads); } + @protected + VotingVoteRecovery sse_decode_voting_vote_recovery( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_choice = sse_decode_u_32(deserializer); + var var_phase = sse_decode_String(deserializer); + var var_workflowPhase = sse_decode_String(deserializer); + var var_txHash = sse_decode_opt_String(deserializer); + var var_vcTreePosition = sse_decode_opt_box_autoadd_u_64(deserializer); + var var_hasCommitmentBundle = sse_decode_bool(deserializer); + return VotingVoteRecovery( + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + choice: var_choice, + phase: var_phase, + workflowPhase: var_workflowPhase, + txHash: var_txHash, + vcTreePosition: var_vcTreePosition, + hasCommitmentBundle: var_hasCommitmentBundle); + } + @protected VotingVoteSubmission sse_decode_voting_vote_submission( SseDeserializer deserializer) { @@ -10418,13 +13010,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_signing_event_Sse( + RustStreamSink self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String( + self.setupAndSerialize( + codec: SseCodec( + decodeSuccessData: sse_decode_signing_event, + decodeErrorData: sse_decode_AnyhowException, + ), + ), + serializer, + ); + } + + @protected + void sse_encode_StreamSink_signing_status_Sse( + RustStreamSink self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String( + self.setupAndSerialize( + codec: SseCodec( + decodeSuccessData: sse_decode_signing_status, + decodeErrorData: sse_decode_AnyhowException, + ), + ), + serializer, + ); + } + + @protected + void sse_encode_StreamSink_sync_progress_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( codec: SseCodec( - decodeSuccessData: sse_decode_signing_event, + decodeSuccessData: sse_decode_sync_progress, decodeErrorData: sse_decode_AnyhowException, ), ), @@ -10433,13 +13055,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_voting_delegation_progress_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( codec: SseCodec( - decodeSuccessData: sse_decode_signing_status, + decodeSuccessData: sse_decode_voting_delegation_progress, decodeErrorData: sse_decode_AnyhowException, ), ), @@ -10448,13 +13070,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_voting_vote_commit_stage_Sse( + RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( codec: SseCodec( - decodeSuccessData: sse_decode_sync_progress, + decodeSuccessData: sse_decode_voting_vote_commit_stage, decodeErrorData: sse_decode_AnyhowException, ), ), @@ -10640,6 +13262,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(self, serializer); } + @protected + void sse_encode_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_completed_vote_display(self, serializer); + } + + @protected + void sse_encode_box_autoadd_voting_config( + VotingConfig self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_config(self, serializer); + } + @protected void sse_encode_box_autoadd_voting_pir_layout( VotingPirLayout self, SseSerializer serializer) { @@ -11091,6 +13727,56 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_ballot_intent( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_ballot_intent(item, serializer); + } + } + + @protected + void sse_encode_list_voting_completed_vote_choice( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_completed_vote_choice(item, serializer); + } + } + + @protected + void sse_encode_list_voting_config_round( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_config_round(item, serializer); + } + } + + @protected + void sse_encode_list_voting_delegation_recovery( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_delegation_recovery(item, serializer); + } + } + + @protected + void sse_encode_list_voting_delegation_status( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_delegation_status(item, serializer); + } + } + @protected void sse_encode_list_voting_encrypted_share( List self, SseSerializer serializer) { @@ -11101,6 +13787,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_next_step( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_next_step(item, serializer); + } + } + + @protected + void sse_encode_list_voting_round_info( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_round_info(item, serializer); + } + } + + @protected + void sse_encode_list_voting_service_endpoint( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_service_endpoint(item, serializer); + } + } + + @protected + void sse_encode_list_voting_share_delegation_record( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_share_delegation_record(item, serializer); + } + } + @protected void sse_encode_list_voting_share_payload( List self, SseSerializer serializer) { @@ -11111,6 +13837,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_share_plan_item( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_share_plan_item(item, serializer); + } + } + + @protected + void sse_encode_list_voting_share_workflow( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_share_workflow(item, serializer); + } + } + @protected void sse_encode_list_voting_signed_vote_commitment( List self, SseSerializer serializer) { @@ -11121,6 +13867,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_vote_recovery( + List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_vote_recovery(item, serializer); + } + } + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer) { @@ -11396,6 +14152,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_voting_completed_vote_display(self, serializer); + } + } + + @protected + void sse_encode_opt_box_autoadd_voting_config( + VotingConfig? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_voting_config(self, serializer); + } + } + + @protected + void sse_encode_opt_box_autoadd_voting_pir_layout( + VotingPirLayout? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_voting_pir_layout(self, serializer); + } + } + @protected void sse_encode_opt_list_String( List? self, SseSerializer serializer) { @@ -11778,6 +14567,68 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_usize_strict(self.inner, serializer); } + @protected + void sse_encode_voting_ballot_intent( + VotingBallotIntent self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.proposalId, serializer); + sse_encode_bool(self.skipped, serializer); + sse_encode_opt_box_autoadd_u_32(self.choice, serializer); + } + + @protected + void sse_encode_voting_chain_response( + VotingChainResponse self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_16(self.statusCode, serializer); + sse_encode_String(self.body, serializer); + } + + @protected + void sse_encode_voting_completed_vote_choice( + VotingCompletedVoteChoice self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.proposalId, serializer); + sse_encode_opt_box_autoadd_u_32(self.choice, serializer); + } + + @protected + void sse_encode_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_voting_completed_vote_choice(self.choices, serializer); + sse_encode_opt_box_autoadd_u_64(self.votedAt, serializer); + } + + @protected + void sse_encode_voting_config(VotingConfig self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.source, serializer); + sse_encode_String(self.sourceFingerprint, serializer); + sse_encode_String(self.trustedKeyFingerprint, serializer); + sse_encode_String(self.switchKind, serializer); + sse_encode_list_voting_service_endpoint(self.voteServers, serializer); + sse_encode_list_voting_service_endpoint(self.pirServers, serializer); + sse_encode_opt_box_autoadd_voting_pir_layout(self.pirLayout, serializer); + sse_encode_list_voting_config_round(self.rounds, serializer); + } + + @protected + void sse_encode_voting_config_round( + VotingConfigRound self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_list_prim_u_8_strict(self.eaPk, serializer); + } + + @protected + void sse_encode_voting_delegation_build( + VotingDelegationBuild self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_delegation_submission(self.submission, serializer); + sse_encode_String(self.wireJson, serializer); + } + @protected void sse_encode_voting_delegation_confirmation( VotingDelegationConfirmation self, SseSerializer serializer) { @@ -11786,6 +14637,42 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(self.vanLeafPosition, serializer); } + @protected + void sse_encode_voting_delegation_progress( + VotingDelegationProgress self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + switch (self) { + case VotingDelegationProgress_SelectingNotes(): + sse_encode_i_32(0, serializer); + case VotingDelegationProgress_PcztBuilding(): + sse_encode_i_32(1, serializer); + case VotingDelegationProgress_PcztBuilt(): + sse_encode_i_32(2, serializer); + case VotingDelegationProgress_ProofStarting(): + sse_encode_i_32(3, serializer); + case VotingDelegationProgress_ProofProgress(progress: final progress): + sse_encode_i_32(4, serializer); + sse_encode_f_64(progress, serializer); + case VotingDelegationProgress_ProofComplete(): + sse_encode_i_32(5, serializer); + case VotingDelegationProgress_SigningPayload(): + sse_encode_i_32(6, serializer); + case VotingDelegationProgress_PayloadReady(): + sse_encode_i_32(7, serializer); + } + } + + @protected + void sse_encode_voting_delegation_recovery( + VotingDelegationRecovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_String(self.phase, serializer); + sse_encode_String(self.workflowPhase, serializer); + sse_encode_opt_String(self.txHash, serializer); + sse_encode_opt_box_autoadd_u_32(self.vanLeafPosition, serializer); + } + @protected void sse_encode_voting_delegation_setup( VotingDelegationSetup self, SseSerializer serializer) { @@ -11798,6 +14685,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_strict(self.tx1Effects, serializer); } + @protected + void sse_encode_voting_delegation_status( + VotingDelegationStatus self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_String(self.phase, serializer); + sse_encode_opt_String(self.txHash, serializer); + } + @protected void sse_encode_voting_delegation_submission( VotingDelegationSubmission self, SseSerializer serializer) { @@ -11824,6 +14720,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(self.shareIndex, serializer); } + @protected + void sse_encode_voting_next_step( + VotingNextStep self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.kind, serializer); + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.choice, serializer); + sse_encode_u_32(self.shareIndex, serializer); + } + @protected void sse_encode_voting_pir_layout( VotingPirLayout self, SseSerializer serializer) { @@ -11845,6 +14752,79 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.roundName, serializer); } + @protected + void sse_encode_voting_round_info( + VotingRoundInfo self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_String(self.network, serializer); + sse_encode_u_64(self.snapshotHeight, serializer); + sse_encode_opt_String(self.hotkeyAddress, serializer); + sse_encode_opt_box_autoadd_u_64(self.eligibleWeightZatoshi, serializer); + sse_encode_u_32(self.bundleCount, serializer); + sse_encode_u_64(self.createdAt, serializer); + } + + @protected + void sse_encode_voting_round_plan( + VotingRoundPlan self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_bool(self.pendingRecovery, serializer); + sse_encode_list_voting_next_step(self.nextSteps, serializer); + sse_encode_list_prim_u_32_strict(self.openProposals, serializer); + sse_encode_bool(self.allDecided, serializer); + sse_encode_list_voting_delegation_status( + self.delegationStatuses, serializer); + sse_encode_bool(self.blockingRecovery, serializer); + sse_encode_bool(self.blockingShareWork, serializer); + sse_encode_bool(self.hotkeyBound, serializer); + sse_encode_bool(self.completedVoteArtifact, serializer); + sse_encode_bool(self.completedForDisplay, serializer); + sse_encode_opt_box_autoadd_voting_completed_vote_display( + self.completedVoteDisplay, serializer); + sse_encode_bool(self.needsDraftSetup, serializer); + sse_encode_String(self.primaryAction, serializer); + } + + @protected + void sse_encode_voting_round_recovery( + VotingRoundRecovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_u_32(self.bundleCount, serializer); + sse_encode_list_voting_delegation_recovery(self.delegation, serializer); + sse_encode_list_voting_vote_recovery(self.votes, serializer); + sse_encode_list_voting_share_workflow(self.shares, serializer); + sse_encode_list_voting_share_delegation_record( + self.shareDelegations, serializer); + sse_encode_list_voting_share_delegation_record( + self.unconfirmedShareDelegations, serializer); + } + + @protected + void sse_encode_voting_service_endpoint( + VotingServiceEndpoint self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.url, serializer); + sse_encode_String(self.label, serializer); + } + + @protected + void sse_encode_voting_share_delegation_record( + VotingShareDelegationRecord self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.shareIndex, serializer); + sse_encode_list_String(self.sentToUrls, serializer); + sse_encode_list_prim_u_8_strict(self.nullifier, serializer); + sse_encode_bool(self.confirmed, serializer); + sse_encode_u_64(self.submitAt, serializer); + sse_encode_u_64(self.createdAt, serializer); + } + @protected void sse_encode_voting_share_payload( VotingSharePayload self, SseSerializer serializer) { @@ -11859,6 +14839,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_strict(self.primaryBlind, serializer); } + @protected + void sse_encode_voting_share_plan( + VotingSharePlan self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_voting_share_tracking_summary(self.summary, serializer); + sse_encode_opt_box_autoadd_u_64(self.nextTrackingDelaySecs, serializer); + sse_encode_bool(self.lastMoment, serializer); + sse_encode_list_voting_share_plan_item(self.submissions, serializer); + } + + @protected + void sse_encode_voting_share_plan_item( + VotingSharePlanItem self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_64(self.submitAt, serializer); + sse_encode_u_32(self.targetCount, serializer); + sse_encode_list_String(self.targetServers, serializer); + } + + @protected + void sse_encode_voting_share_tracking_summary( + VotingShareTrackingSummary self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_64(self.total, serializer); + sse_encode_u_64(self.confirmed, serializer); + sse_encode_u_64(self.waiting, serializer); + sse_encode_u_64(self.ready, serializer); + sse_encode_u_64(self.overdue, serializer); + } + + @protected + void sse_encode_voting_share_workflow( + VotingShareWorkflow self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.shareIndex, serializer); + sse_encode_String(self.phase, serializer); + } + @protected void sse_encode_voting_signed_vote_commitment( VotingSignedVoteCommitment self, SseSerializer serializer) { @@ -11885,6 +14905,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(self.anchorHeight, serializer); } + @protected + void sse_encode_voting_vote_commit_stage( + VotingVoteCommitStage self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + switch (self) { + case VotingVoteCommitStage_ProofStarting( + proposalId: final proposalId, + bundleIndex: final bundleIndex + ): + sse_encode_i_32(0, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(bundleIndex, serializer); + case VotingVoteCommitStage_ProofProgress( + proposalId: final proposalId, + bundleIndex: final bundleIndex, + progress: final progress + ): + sse_encode_i_32(1, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_f_64(progress, serializer); + case VotingVoteCommitStage_SharePayloadsBuilding( + proposalId: final proposalId, + bundleIndex: final bundleIndex + ): + sse_encode_i_32(2, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(bundleIndex, serializer); + case VotingVoteCommitStage_Signing( + proposalId: final proposalId, + bundleIndex: final bundleIndex + ): + sse_encode_i_32(3, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_32(bundleIndex, serializer); + } + } + @protected void sse_encode_voting_vote_commitments( VotingVoteCommitments self, SseSerializer serializer) { @@ -11910,6 +14968,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_voting_share_payload(self.sharePayloads, serializer); } + @protected + void sse_encode_voting_vote_recovery( + VotingVoteRecovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.choice, serializer); + sse_encode_String(self.phase, serializer); + sse_encode_String(self.workflowPhase, serializer); + sse_encode_opt_String(self.txHash, serializer); + sse_encode_opt_box_autoadd_u_64(self.vcTreePosition, serializer); + sse_encode_bool(self.hasCommitmentBundle, serializer); + } + @protected void sse_encode_voting_vote_submission( VotingVoteSubmission self, SseSerializer serializer) { diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 21d121681..1a4f93cc6 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -160,6 +160,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_sync_progress_Sse( dynamic raw); + @protected + RustStreamSink + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); + + @protected + RustStreamSink + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); + @protected String dco_decode_String(dynamic raw); @@ -229,6 +237,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int dco_decode_box_autoadd_u_8(dynamic raw); + @protected + VotingCompletedVoteDisplay + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); + + @protected + VotingConfig dco_decode_box_autoadd_voting_config(dynamic raw); + @protected VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw); @@ -377,17 +392,58 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_tx_spend(dynamic raw); + @protected + List dco_decode_list_voting_ballot_intent(dynamic raw); + + @protected + List dco_decode_list_voting_completed_vote_choice( + dynamic raw); + + @protected + List dco_decode_list_voting_config_round(dynamic raw); + + @protected + List dco_decode_list_voting_delegation_recovery( + dynamic raw); + + @protected + List dco_decode_list_voting_delegation_status( + dynamic raw); + @protected List dco_decode_list_voting_encrypted_share( dynamic raw); + @protected + List dco_decode_list_voting_next_step(dynamic raw); + + @protected + List dco_decode_list_voting_round_info(dynamic raw); + + @protected + List dco_decode_list_voting_service_endpoint( + dynamic raw); + + @protected + List + dco_decode_list_voting_share_delegation_record(dynamic raw); + @protected List dco_decode_list_voting_share_payload(dynamic raw); + @protected + List dco_decode_list_voting_share_plan_item(dynamic raw); + + @protected + List dco_decode_list_voting_share_workflow(dynamic raw); + @protected List dco_decode_list_voting_signed_vote_commitment(dynamic raw); + @protected + List dco_decode_list_voting_vote_recovery(dynamic raw); + @protected List dco_decode_list_zsa_holding(dynamic raw); @@ -463,6 +519,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? dco_decode_opt_box_autoadd_u_8(dynamic raw); + @protected + VotingCompletedVoteDisplay? + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); + + @protected + VotingConfig? dco_decode_opt_box_autoadd_voting_config(dynamic raw); + + @protected + VotingPirLayout? dco_decode_opt_box_autoadd_voting_pir_layout(dynamic raw); + @protected List? dco_decode_opt_list_String(dynamic raw); @@ -574,13 +640,45 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 dco_decode_usize_array_4(dynamic raw); + @protected + VotingBallotIntent dco_decode_voting_ballot_intent(dynamic raw); + + @protected + VotingChainResponse dco_decode_voting_chain_response(dynamic raw); + + @protected + VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( + dynamic raw); + + @protected + VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( + dynamic raw); + + @protected + VotingConfig dco_decode_voting_config(dynamic raw); + + @protected + VotingConfigRound dco_decode_voting_config_round(dynamic raw); + + @protected + VotingDelegationBuild dco_decode_voting_delegation_build(dynamic raw); + @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( dynamic raw); + @protected + VotingDelegationProgress dco_decode_voting_delegation_progress(dynamic raw); + + @protected + VotingDelegationRecovery dco_decode_voting_delegation_recovery(dynamic raw); + @protected VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw); + @protected + VotingDelegationStatus dco_decode_voting_delegation_status(dynamic raw); + @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( dynamic raw); @@ -588,15 +686,47 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); + @protected + VotingNextStep dco_decode_voting_next_step(dynamic raw); + @protected VotingPirLayout dco_decode_voting_pir_layout(dynamic raw); @protected VotingPreparedInfo dco_decode_voting_prepared_info(dynamic raw); + @protected + VotingRoundInfo dco_decode_voting_round_info(dynamic raw); + + @protected + VotingRoundPlan dco_decode_voting_round_plan(dynamic raw); + + @protected + VotingRoundRecovery dco_decode_voting_round_recovery(dynamic raw); + + @protected + VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw); + + @protected + VotingShareDelegationRecord dco_decode_voting_share_delegation_record( + dynamic raw); + @protected VotingSharePayload dco_decode_voting_share_payload(dynamic raw); + @protected + VotingSharePlan dco_decode_voting_share_plan(dynamic raw); + + @protected + VotingSharePlanItem dco_decode_voting_share_plan_item(dynamic raw); + + @protected + VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( + dynamic raw); + + @protected + VotingShareWorkflow dco_decode_voting_share_workflow(dynamic raw); + @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( dynamic raw); @@ -604,6 +734,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); + @protected + VotingVoteCommitStage dco_decode_voting_vote_commit_stage(dynamic raw); + @protected VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw); @@ -613,6 +746,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVotePayloads dco_decode_voting_vote_payloads(dynamic raw); + @protected + VotingVoteRecovery dco_decode_voting_vote_recovery(dynamic raw); + @protected VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw); @@ -722,6 +858,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink sse_decode_StreamSink_sync_progress_Sse( SseDeserializer deserializer); + @protected + RustStreamSink + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer); + + @protected + RustStreamSink + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer); + @protected String sse_decode_String(SseDeserializer deserializer); @@ -795,6 +941,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int sse_decode_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingCompletedVoteDisplay + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig sse_decode_box_autoadd_voting_config( + SseDeserializer deserializer); + @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( SseDeserializer deserializer); @@ -951,19 +1106,68 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_tx_spend(SseDeserializer deserializer); + @protected + List sse_decode_list_voting_ballot_intent( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_completed_vote_choice( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_config_round( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_delegation_recovery( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_delegation_status( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_encrypted_share( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_next_step( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_round_info( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_service_endpoint( + SseDeserializer deserializer); + + @protected + List + sse_decode_list_voting_share_delegation_record( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_share_payload( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_share_plan_item( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_share_workflow( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_signed_vote_commitment( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_vote_recovery( + SseDeserializer deserializer); + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1041,6 +1245,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? sse_decode_opt_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingCompletedVoteDisplay? + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig? sse_decode_opt_box_autoadd_voting_config( + SseDeserializer deserializer); + + @protected + VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( + SseDeserializer deserializer); + @protected List? sse_decode_opt_list_String(SseDeserializer deserializer); @@ -1155,14 +1372,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 sse_decode_usize_array_4(SseDeserializer deserializer); + @protected + VotingBallotIntent sse_decode_voting_ballot_intent( + SseDeserializer deserializer); + + @protected + VotingChainResponse sse_decode_voting_chain_response( + SseDeserializer deserializer); + + @protected + VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( + SseDeserializer deserializer); + + @protected + VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig sse_decode_voting_config(SseDeserializer deserializer); + + @protected + VotingConfigRound sse_decode_voting_config_round( + SseDeserializer deserializer); + + @protected + VotingDelegationBuild sse_decode_voting_delegation_build( + SseDeserializer deserializer); + @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( SseDeserializer deserializer); + @protected + VotingDelegationProgress sse_decode_voting_delegation_progress( + SseDeserializer deserializer); + + @protected + VotingDelegationRecovery sse_decode_voting_delegation_recovery( + SseDeserializer deserializer); + @protected VotingDelegationSetup sse_decode_voting_delegation_setup( SseDeserializer deserializer); + @protected + VotingDelegationStatus sse_decode_voting_delegation_status( + SseDeserializer deserializer); + @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( SseDeserializer deserializer); @@ -1171,6 +1427,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingEncryptedShare sse_decode_voting_encrypted_share( SseDeserializer deserializer); + @protected + VotingNextStep sse_decode_voting_next_step(SseDeserializer deserializer); + @protected VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer); @@ -1178,10 +1437,43 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingPreparedInfo sse_decode_voting_prepared_info( SseDeserializer deserializer); + @protected + VotingRoundInfo sse_decode_voting_round_info(SseDeserializer deserializer); + + @protected + VotingRoundPlan sse_decode_voting_round_plan(SseDeserializer deserializer); + + @protected + VotingRoundRecovery sse_decode_voting_round_recovery( + SseDeserializer deserializer); + + @protected + VotingServiceEndpoint sse_decode_voting_service_endpoint( + SseDeserializer deserializer); + + @protected + VotingShareDelegationRecord sse_decode_voting_share_delegation_record( + SseDeserializer deserializer); + @protected VotingSharePayload sse_decode_voting_share_payload( SseDeserializer deserializer); + @protected + VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer); + + @protected + VotingSharePlanItem sse_decode_voting_share_plan_item( + SseDeserializer deserializer); + + @protected + VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( + SseDeserializer deserializer); + + @protected + VotingShareWorkflow sse_decode_voting_share_workflow( + SseDeserializer deserializer); + @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( SseDeserializer deserializer); @@ -1189,6 +1481,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); + @protected + VotingVoteCommitStage sse_decode_voting_vote_commit_stage( + SseDeserializer deserializer); + @protected VotingVoteCommitments sse_decode_voting_vote_commitments( SseDeserializer deserializer); @@ -1201,6 +1497,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingVotePayloads sse_decode_voting_vote_payloads( SseDeserializer deserializer); + @protected + VotingVoteRecovery sse_decode_voting_vote_recovery( + SseDeserializer deserializer); + @protected VotingVoteSubmission sse_decode_voting_vote_submission( SseDeserializer deserializer); @@ -1317,6 +1617,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_StreamSink_sync_progress_Sse( RustStreamSink self, SseSerializer serializer); + @protected + void sse_encode_StreamSink_voting_delegation_progress_Sse( + RustStreamSink self, SseSerializer serializer); + + @protected + void sse_encode_StreamSink_voting_vote_commit_stage_Sse( + RustStreamSink self, SseSerializer serializer); + @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1395,6 +1703,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_u_8(int self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer); + + @protected + void sse_encode_box_autoadd_voting_config( + VotingConfig self, SseSerializer serializer); + @protected void sse_encode_box_autoadd_voting_pir_layout( VotingPirLayout self, SseSerializer serializer); @@ -1564,18 +1880,66 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_ballot_intent( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_completed_vote_choice( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_config_round( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_delegation_recovery( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_delegation_status( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_encrypted_share( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_next_step( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_round_info( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_service_endpoint( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_delegation_record( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_share_payload( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_share_plan_item( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_workflow( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_signed_vote_commitment( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_vote_recovery( + List self, SseSerializer serializer); + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer); @@ -1657,6 +2021,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_u_8(int? self, SseSerializer serializer); + @protected + void sse_encode_opt_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay? self, SseSerializer serializer); + + @protected + void sse_encode_opt_box_autoadd_voting_config( + VotingConfig? self, SseSerializer serializer); + + @protected + void sse_encode_opt_box_autoadd_voting_pir_layout( + VotingPirLayout? self, SseSerializer serializer); + @protected void sse_encode_opt_list_String(List? self, SseSerializer serializer); @@ -1777,14 +2153,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_usize_array_4(UsizeArray4 self, SseSerializer serializer); + @protected + void sse_encode_voting_ballot_intent( + VotingBallotIntent self, SseSerializer serializer); + + @protected + void sse_encode_voting_chain_response( + VotingChainResponse self, SseSerializer serializer); + + @protected + void sse_encode_voting_completed_vote_choice( + VotingCompletedVoteChoice self, SseSerializer serializer); + + @protected + void sse_encode_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer); + + @protected + void sse_encode_voting_config(VotingConfig self, SseSerializer serializer); + + @protected + void sse_encode_voting_config_round( + VotingConfigRound self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_build( + VotingDelegationBuild self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_confirmation( VotingDelegationConfirmation self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_progress( + VotingDelegationProgress self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_recovery( + VotingDelegationRecovery self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_setup( VotingDelegationSetup self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_status( + VotingDelegationStatus self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_submission( VotingDelegationSubmission self, SseSerializer serializer); @@ -1793,6 +2208,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_encrypted_share( VotingEncryptedShare self, SseSerializer serializer); + @protected + void sse_encode_voting_next_step( + VotingNextStep self, SseSerializer serializer); + @protected void sse_encode_voting_pir_layout( VotingPirLayout self, SseSerializer serializer); @@ -1801,10 +2220,46 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_prepared_info( VotingPreparedInfo self, SseSerializer serializer); + @protected + void sse_encode_voting_round_info( + VotingRoundInfo self, SseSerializer serializer); + + @protected + void sse_encode_voting_round_plan( + VotingRoundPlan self, SseSerializer serializer); + + @protected + void sse_encode_voting_round_recovery( + VotingRoundRecovery self, SseSerializer serializer); + + @protected + void sse_encode_voting_service_endpoint( + VotingServiceEndpoint self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_delegation_record( + VotingShareDelegationRecord self, SseSerializer serializer); + @protected void sse_encode_voting_share_payload( VotingSharePayload self, SseSerializer serializer); + @protected + void sse_encode_voting_share_plan( + VotingSharePlan self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_plan_item( + VotingSharePlanItem self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_tracking_summary( + VotingShareTrackingSummary self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_workflow( + VotingShareWorkflow self, SseSerializer serializer); + @protected void sse_encode_voting_signed_vote_commitment( VotingSignedVoteCommitment self, SseSerializer serializer); @@ -1813,6 +2268,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_van_witness( VotingVanWitness self, SseSerializer serializer); + @protected + void sse_encode_voting_vote_commit_stage( + VotingVoteCommitStage self, SseSerializer serializer); + @protected void sse_encode_voting_vote_commitments( VotingVoteCommitments self, SseSerializer serializer); @@ -1825,6 +2284,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_vote_payloads( VotingVotePayloads self, SseSerializer serializer); + @protected + void sse_encode_voting_vote_recovery( + VotingVoteRecovery self, SseSerializer serializer); + @protected void sse_encode_voting_vote_submission( VotingVoteSubmission self, SseSerializer serializer); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 316297029..04b4a467a 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -162,6 +162,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_sync_progress_Sse( dynamic raw); + @protected + RustStreamSink + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); + + @protected + RustStreamSink + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); + @protected String dco_decode_String(dynamic raw); @@ -231,6 +239,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int dco_decode_box_autoadd_u_8(dynamic raw); + @protected + VotingCompletedVoteDisplay + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); + + @protected + VotingConfig dco_decode_box_autoadd_voting_config(dynamic raw); + @protected VotingPirLayout dco_decode_box_autoadd_voting_pir_layout(dynamic raw); @@ -379,17 +394,58 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List dco_decode_list_tx_spend(dynamic raw); + @protected + List dco_decode_list_voting_ballot_intent(dynamic raw); + + @protected + List dco_decode_list_voting_completed_vote_choice( + dynamic raw); + + @protected + List dco_decode_list_voting_config_round(dynamic raw); + + @protected + List dco_decode_list_voting_delegation_recovery( + dynamic raw); + + @protected + List dco_decode_list_voting_delegation_status( + dynamic raw); + @protected List dco_decode_list_voting_encrypted_share( dynamic raw); + @protected + List dco_decode_list_voting_next_step(dynamic raw); + + @protected + List dco_decode_list_voting_round_info(dynamic raw); + + @protected + List dco_decode_list_voting_service_endpoint( + dynamic raw); + + @protected + List + dco_decode_list_voting_share_delegation_record(dynamic raw); + @protected List dco_decode_list_voting_share_payload(dynamic raw); + @protected + List dco_decode_list_voting_share_plan_item(dynamic raw); + + @protected + List dco_decode_list_voting_share_workflow(dynamic raw); + @protected List dco_decode_list_voting_signed_vote_commitment(dynamic raw); + @protected + List dco_decode_list_voting_vote_recovery(dynamic raw); + @protected List dco_decode_list_zsa_holding(dynamic raw); @@ -465,6 +521,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? dco_decode_opt_box_autoadd_u_8(dynamic raw); + @protected + VotingCompletedVoteDisplay? + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); + + @protected + VotingConfig? dco_decode_opt_box_autoadd_voting_config(dynamic raw); + + @protected + VotingPirLayout? dco_decode_opt_box_autoadd_voting_pir_layout(dynamic raw); + @protected List? dco_decode_opt_list_String(dynamic raw); @@ -576,13 +642,45 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 dco_decode_usize_array_4(dynamic raw); + @protected + VotingBallotIntent dco_decode_voting_ballot_intent(dynamic raw); + + @protected + VotingChainResponse dco_decode_voting_chain_response(dynamic raw); + + @protected + VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( + dynamic raw); + + @protected + VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( + dynamic raw); + + @protected + VotingConfig dco_decode_voting_config(dynamic raw); + + @protected + VotingConfigRound dco_decode_voting_config_round(dynamic raw); + + @protected + VotingDelegationBuild dco_decode_voting_delegation_build(dynamic raw); + @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( dynamic raw); + @protected + VotingDelegationProgress dco_decode_voting_delegation_progress(dynamic raw); + + @protected + VotingDelegationRecovery dco_decode_voting_delegation_recovery(dynamic raw); + @protected VotingDelegationSetup dco_decode_voting_delegation_setup(dynamic raw); + @protected + VotingDelegationStatus dco_decode_voting_delegation_status(dynamic raw); + @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( dynamic raw); @@ -590,15 +688,47 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); + @protected + VotingNextStep dco_decode_voting_next_step(dynamic raw); + @protected VotingPirLayout dco_decode_voting_pir_layout(dynamic raw); @protected VotingPreparedInfo dco_decode_voting_prepared_info(dynamic raw); + @protected + VotingRoundInfo dco_decode_voting_round_info(dynamic raw); + + @protected + VotingRoundPlan dco_decode_voting_round_plan(dynamic raw); + + @protected + VotingRoundRecovery dco_decode_voting_round_recovery(dynamic raw); + + @protected + VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw); + + @protected + VotingShareDelegationRecord dco_decode_voting_share_delegation_record( + dynamic raw); + @protected VotingSharePayload dco_decode_voting_share_payload(dynamic raw); + @protected + VotingSharePlan dco_decode_voting_share_plan(dynamic raw); + + @protected + VotingSharePlanItem dco_decode_voting_share_plan_item(dynamic raw); + + @protected + VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( + dynamic raw); + + @protected + VotingShareWorkflow dco_decode_voting_share_workflow(dynamic raw); + @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( dynamic raw); @@ -606,6 +736,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); + @protected + VotingVoteCommitStage dco_decode_voting_vote_commit_stage(dynamic raw); + @protected VotingVoteCommitments dco_decode_voting_vote_commitments(dynamic raw); @@ -615,6 +748,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVotePayloads dco_decode_voting_vote_payloads(dynamic raw); + @protected + VotingVoteRecovery dco_decode_voting_vote_recovery(dynamic raw); + @protected VotingVoteSubmission dco_decode_voting_vote_submission(dynamic raw); @@ -724,6 +860,16 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink sse_decode_StreamSink_sync_progress_Sse( SseDeserializer deserializer); + @protected + RustStreamSink + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer); + + @protected + RustStreamSink + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer); + @protected String sse_decode_String(SseDeserializer deserializer); @@ -797,6 +943,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int sse_decode_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingCompletedVoteDisplay + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig sse_decode_box_autoadd_voting_config( + SseDeserializer deserializer); + @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( SseDeserializer deserializer); @@ -953,19 +1108,68 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected List sse_decode_list_tx_spend(SseDeserializer deserializer); + @protected + List sse_decode_list_voting_ballot_intent( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_completed_vote_choice( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_config_round( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_delegation_recovery( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_delegation_status( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_encrypted_share( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_next_step( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_round_info( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_service_endpoint( + SseDeserializer deserializer); + + @protected + List + sse_decode_list_voting_share_delegation_record( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_share_payload( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_share_plan_item( + SseDeserializer deserializer); + + @protected + List sse_decode_list_voting_share_workflow( + SseDeserializer deserializer); + @protected List sse_decode_list_voting_signed_vote_commitment( SseDeserializer deserializer); + @protected + List sse_decode_list_voting_vote_recovery( + SseDeserializer deserializer); + @protected List sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1043,6 +1247,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? sse_decode_opt_box_autoadd_u_8(SseDeserializer deserializer); + @protected + VotingCompletedVoteDisplay? + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig? sse_decode_opt_box_autoadd_voting_config( + SseDeserializer deserializer); + + @protected + VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( + SseDeserializer deserializer); + @protected List? sse_decode_opt_list_String(SseDeserializer deserializer); @@ -1157,14 +1374,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected UsizeArray4 sse_decode_usize_array_4(SseDeserializer deserializer); + @protected + VotingBallotIntent sse_decode_voting_ballot_intent( + SseDeserializer deserializer); + + @protected + VotingChainResponse sse_decode_voting_chain_response( + SseDeserializer deserializer); + + @protected + VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( + SseDeserializer deserializer); + + @protected + VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( + SseDeserializer deserializer); + + @protected + VotingConfig sse_decode_voting_config(SseDeserializer deserializer); + + @protected + VotingConfigRound sse_decode_voting_config_round( + SseDeserializer deserializer); + + @protected + VotingDelegationBuild sse_decode_voting_delegation_build( + SseDeserializer deserializer); + @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( SseDeserializer deserializer); + @protected + VotingDelegationProgress sse_decode_voting_delegation_progress( + SseDeserializer deserializer); + + @protected + VotingDelegationRecovery sse_decode_voting_delegation_recovery( + SseDeserializer deserializer); + @protected VotingDelegationSetup sse_decode_voting_delegation_setup( SseDeserializer deserializer); + @protected + VotingDelegationStatus sse_decode_voting_delegation_status( + SseDeserializer deserializer); + @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( SseDeserializer deserializer); @@ -1173,6 +1429,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingEncryptedShare sse_decode_voting_encrypted_share( SseDeserializer deserializer); + @protected + VotingNextStep sse_decode_voting_next_step(SseDeserializer deserializer); + @protected VotingPirLayout sse_decode_voting_pir_layout(SseDeserializer deserializer); @@ -1180,10 +1439,43 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingPreparedInfo sse_decode_voting_prepared_info( SseDeserializer deserializer); + @protected + VotingRoundInfo sse_decode_voting_round_info(SseDeserializer deserializer); + + @protected + VotingRoundPlan sse_decode_voting_round_plan(SseDeserializer deserializer); + + @protected + VotingRoundRecovery sse_decode_voting_round_recovery( + SseDeserializer deserializer); + + @protected + VotingServiceEndpoint sse_decode_voting_service_endpoint( + SseDeserializer deserializer); + + @protected + VotingShareDelegationRecord sse_decode_voting_share_delegation_record( + SseDeserializer deserializer); + @protected VotingSharePayload sse_decode_voting_share_payload( SseDeserializer deserializer); + @protected + VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer); + + @protected + VotingSharePlanItem sse_decode_voting_share_plan_item( + SseDeserializer deserializer); + + @protected + VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( + SseDeserializer deserializer); + + @protected + VotingShareWorkflow sse_decode_voting_share_workflow( + SseDeserializer deserializer); + @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( SseDeserializer deserializer); @@ -1191,6 +1483,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); + @protected + VotingVoteCommitStage sse_decode_voting_vote_commit_stage( + SseDeserializer deserializer); + @protected VotingVoteCommitments sse_decode_voting_vote_commitments( SseDeserializer deserializer); @@ -1203,6 +1499,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { VotingVotePayloads sse_decode_voting_vote_payloads( SseDeserializer deserializer); + @protected + VotingVoteRecovery sse_decode_voting_vote_recovery( + SseDeserializer deserializer); + @protected VotingVoteSubmission sse_decode_voting_vote_submission( SseDeserializer deserializer); @@ -1319,6 +1619,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_StreamSink_sync_progress_Sse( RustStreamSink self, SseSerializer serializer); + @protected + void sse_encode_StreamSink_voting_delegation_progress_Sse( + RustStreamSink self, SseSerializer serializer); + + @protected + void sse_encode_StreamSink_voting_vote_commit_stage_Sse( + RustStreamSink self, SseSerializer serializer); + @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1397,6 +1705,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_u_8(int self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer); + + @protected + void sse_encode_box_autoadd_voting_config( + VotingConfig self, SseSerializer serializer); + @protected void sse_encode_box_autoadd_voting_pir_layout( VotingPirLayout self, SseSerializer serializer); @@ -1566,18 +1882,66 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_list_tx_spend(List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_ballot_intent( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_completed_vote_choice( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_config_round( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_delegation_recovery( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_delegation_status( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_encrypted_share( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_next_step( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_round_info( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_service_endpoint( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_delegation_record( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_share_payload( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_share_plan_item( + List self, SseSerializer serializer); + + @protected + void sse_encode_list_voting_share_workflow( + List self, SseSerializer serializer); + @protected void sse_encode_list_voting_signed_vote_commitment( List self, SseSerializer serializer); + @protected + void sse_encode_list_voting_vote_recovery( + List self, SseSerializer serializer); + @protected void sse_encode_list_zsa_holding( List self, SseSerializer serializer); @@ -1659,6 +2023,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_u_8(int? self, SseSerializer serializer); + @protected + void sse_encode_opt_box_autoadd_voting_completed_vote_display( + VotingCompletedVoteDisplay? self, SseSerializer serializer); + + @protected + void sse_encode_opt_box_autoadd_voting_config( + VotingConfig? self, SseSerializer serializer); + + @protected + void sse_encode_opt_box_autoadd_voting_pir_layout( + VotingPirLayout? self, SseSerializer serializer); + @protected void sse_encode_opt_list_String(List? self, SseSerializer serializer); @@ -1779,14 +2155,53 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_usize_array_4(UsizeArray4 self, SseSerializer serializer); + @protected + void sse_encode_voting_ballot_intent( + VotingBallotIntent self, SseSerializer serializer); + + @protected + void sse_encode_voting_chain_response( + VotingChainResponse self, SseSerializer serializer); + + @protected + void sse_encode_voting_completed_vote_choice( + VotingCompletedVoteChoice self, SseSerializer serializer); + + @protected + void sse_encode_voting_completed_vote_display( + VotingCompletedVoteDisplay self, SseSerializer serializer); + + @protected + void sse_encode_voting_config(VotingConfig self, SseSerializer serializer); + + @protected + void sse_encode_voting_config_round( + VotingConfigRound self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_build( + VotingDelegationBuild self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_confirmation( VotingDelegationConfirmation self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_progress( + VotingDelegationProgress self, SseSerializer serializer); + + @protected + void sse_encode_voting_delegation_recovery( + VotingDelegationRecovery self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_setup( VotingDelegationSetup self, SseSerializer serializer); + @protected + void sse_encode_voting_delegation_status( + VotingDelegationStatus self, SseSerializer serializer); + @protected void sse_encode_voting_delegation_submission( VotingDelegationSubmission self, SseSerializer serializer); @@ -1795,6 +2210,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_encrypted_share( VotingEncryptedShare self, SseSerializer serializer); + @protected + void sse_encode_voting_next_step( + VotingNextStep self, SseSerializer serializer); + @protected void sse_encode_voting_pir_layout( VotingPirLayout self, SseSerializer serializer); @@ -1803,10 +2222,46 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_prepared_info( VotingPreparedInfo self, SseSerializer serializer); + @protected + void sse_encode_voting_round_info( + VotingRoundInfo self, SseSerializer serializer); + + @protected + void sse_encode_voting_round_plan( + VotingRoundPlan self, SseSerializer serializer); + + @protected + void sse_encode_voting_round_recovery( + VotingRoundRecovery self, SseSerializer serializer); + + @protected + void sse_encode_voting_service_endpoint( + VotingServiceEndpoint self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_delegation_record( + VotingShareDelegationRecord self, SseSerializer serializer); + @protected void sse_encode_voting_share_payload( VotingSharePayload self, SseSerializer serializer); + @protected + void sse_encode_voting_share_plan( + VotingSharePlan self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_plan_item( + VotingSharePlanItem self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_tracking_summary( + VotingShareTrackingSummary self, SseSerializer serializer); + + @protected + void sse_encode_voting_share_workflow( + VotingShareWorkflow self, SseSerializer serializer); + @protected void sse_encode_voting_signed_vote_commitment( VotingSignedVoteCommitment self, SseSerializer serializer); @@ -1815,6 +2270,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_van_witness( VotingVanWitness self, SseSerializer serializer); + @protected + void sse_encode_voting_vote_commit_stage( + VotingVoteCommitStage self, SseSerializer serializer); + @protected void sse_encode_voting_vote_commitments( VotingVoteCommitments self, SseSerializer serializer); @@ -1827,6 +2286,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_voting_vote_payloads( VotingVotePayloads self, SseSerializer serializer); + @protected + void sse_encode_voting_vote_recovery( + VotingVoteRecovery self, SseSerializer serializer); + @protected void sse_encode_voting_vote_submission( VotingVoteSubmission self, SseSerializer serializer); diff --git a/lib/store.dart b/lib/store.dart index bcd0c700e..c0b60e168 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:math'; import 'package:collection/collection.dart'; import 'package:convert/convert.dart'; @@ -23,6 +24,7 @@ import 'package:zkool/src/rust/api/network.dart'; import 'package:zkool/src/rust/api/plugin.dart' as plugin_api; import 'package:zkool/src/rust/api/sweep.dart'; import 'package:zkool/src/rust/api/sync.dart'; +import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/src/rust/api/zsa.dart'; import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; @@ -368,6 +370,10 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { final isLightNode = (hasDb ? await getProp(key: "is_light_node", c: c) : null) ?? "true"; final lwd = (hasDb ? await getProp(key: "lwd", c: c) : null) ?? "https://zec.rocks"; final syncInterval = (hasDb ? await getProp(key: "sync_interval", c: c) : null) ?? "30"; + final votingConfigUrl = + (hasDb ? await getProp(key: "voting_config_url", c: c) : null) ?? ""; + final voteNodeUrl = + (hasDb ? await getProp(key: "vote_node_url", c: c) : null) ?? ""; final actionsPerSync = (hasDb ? await getProp(key: "actions_per_sync", c: c) : null) ?? "10000"; final blockExplorer = (hasDb ? await getProp(key: "block_explorer", c: c) : null) ?? "https://cipherscan.app/tx/{txid}"; final qrEnabled = (hasDb ? await getProp(key: "qr_enabled", c: c) : null) ?? "false"; @@ -413,6 +419,8 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { expertMode: expertMode, paletteName: paletteName, darkMode: darkMode, + votingConfigUrl: votingConfigUrl, + voteNodeUrl: voteNodeUrl, transactionTableMode: txTableMode, currency: currency, ); @@ -441,6 +449,20 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { transactionTableMode: tableMode, )); } + + Future setVotingConfigUrl(String url) async { + await putProp(key: "voting_config_url", value: url, c: coinContext.coin); + state = state.whenData((s) => s.copyWith( + votingConfigUrl: url, + )); + } + + Future setVoteNodeUrl(String url) async { + await putProp(key: "vote_node_url", value: url, c: coinContext.coin); + state = state.whenData((s) => s.copyWith( + voteNodeUrl: url, + )); + } } @Riverpod(keepAlive: true) @@ -515,6 +537,8 @@ sealed class AppSettings with _$AppSettings { required bool darkMode, required bool transactionTableMode, required String currency, + required String votingConfigUrl, + required String voteNodeUrl, }) = _AppSettings; } @@ -1194,6 +1218,11 @@ class VaultNotifier extends _$VaultNotifier { Future signOut() async { logger.i("VaultNotifier.signOut"); + if (ref.read(votingSubmissionGuardProvider)) { + throw Exception( + "A voting submission is in progress. Wait for it to finish before signing out.", + ); + } final vault = await future; await vault.signOut(); } @@ -1227,3 +1256,665 @@ Future> pluginMemoSections( final ironwoodActiveProvider = FutureProvider((ref) async { return await isIronwoodActive(c: coinContext.coin); }); + +// ── Voting providers ─────────────────────────────────────────────────────── + +/// Aggregated recovery-first view of one voting round: the fork-derived +/// resume plan, the full recovery snapshot, and the persisted ballot intents. +/// Every voting screen loads this before acting; nothing about a voting +/// session lives in Dart state. +@freezed +sealed class VotingSessionState with _$VotingSessionState { + factory VotingSessionState({ + required VotingRoundPlan? plan, + required VotingRoundRecovery? recovery, + required List intents, + }) = _VotingSessionState; +} + +/// Per-round voting session. `build()` is the recovery-first triple load; +/// `refresh()` re-runs it after an action mutates the voting DB. +@Riverpod(keepAlive: true) +class VotingSession extends _$VotingSession { + String _roundId = ""; + + @override + Future build(String roundId) { + _roundId = roundId; + return _load(); + } + + Future _load() async { + final c = coinContext.coin; + final plan = await votingPlan( + roundId: _roundId, + proposalIds: const [], + c: c, + ); + final recovery = await votingRecovery(roundId: _roundId, c: c); + final intents = await votingBallotIntents(roundId: _roundId, c: c); + return VotingSessionState(plan: plan, recovery: recovery, intents: intents); + } + + Future refresh() async { + state = const AsyncValue.loading(); + state = await AsyncValue.guard(_load); + } +} + +/// Rounds persisted in the voting DB for the current wallet. +@riverpod +Future> votingRoundList(Ref ref) async { + final c = coinContext.coin; + return await votingRounds(c: c); +} + +/// Resolved and authenticated voting config for the configured source URL. +/// Resolves fresh on build; on failure falls back to the last cached config. +@Riverpod(keepAlive: true) +class VotingConfigNotifier extends _$VotingConfigNotifier { + @override + Future build() async { + final settings = await ref.watch(appSettingsProvider.future); + final source = settings.votingConfigUrl; + if (source.isEmpty) return null; + return _resolve(source); + } + + Future _resolve(String source) async { + final c = coinContext.coin; + try { + return await votingConfigResolve(source: source, c: c); + } on Exception { + return await votingConfigCached(source: source, c: c); + } + } + + Future resolve() async { + final settings = await ref.read(appSettingsProvider.future); + final source = settings.votingConfigUrl; + state = const AsyncValue.loading(); + final result = source.isEmpty ? null : await _resolve(source); + state = AsyncValue.data(result); + return result; + } +} + +/// Blocks destructive wallet actions (account deletion, vault sign-out, +/// wallet removal) while a voting submission job is in flight. +@Riverpod(keepAlive: true) +class VotingSubmissionGuard extends _$VotingSubmissionGuard { + @override + bool build() => false; + + void setActive(bool active) { + state = active; + } +} + +/// State of the voting submission job for one round. +@freezed +sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { + factory VotingSubmissionJobState({ + required String stage, // idle|preparing|proving|submitting|confirming|done|error + required double progress, + String? error, + }) = _VotingSubmissionJobState; +} + +/// Delegation execution job for one round. Runs the serialized chain: +/// prepare (or resume) → setup → build submission (progress stream) → +/// broadcast → mark submitted → poll confirmation → confirm. Vote casting +/// lands in a later phase. Restart-safe: the resume plan decides which steps +/// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. +@Riverpod(keepAlive: true) +class VotingSubmissionJob extends _$VotingSubmissionJob { + Timer? _shareTimer; + + @override + VotingSubmissionJobState build(String roundId) { + ref.onDispose(() => _shareTimer?.cancel()); + return VotingSubmissionJobState(stage: "idle", progress: 0); + } + + Future start({ + required String chainUrl, + required String pirServerUrl, + VotingPirLayout? pirLayout, + String? roundParamsJson, + String? roundName, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + String voteNodeUrl = "", + int ceremonyStart = 0, + int? voteEnd, + List shareServerUrls = const [], + bool singleShare = false, + }) async { + if (state.stage != "idle" && + state.stage != "error" && + state.stage != "done") { + return; // already running + } + state = state.copyWith(stage: "running", progress: 0, error: null); + ref.read(votingSubmissionGuardProvider.notifier).setActive(true); + try { + await _runDelegation( + chainUrl: chainUrl, + pirServerUrl: pirServerUrl, + pirLayout: pirLayout, + roundParamsJson: roundParamsJson, + roundName: roundName, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + ); + final session = await ref.read(votingSessionProvider(roundId).future); + await _runVotes( + chainUrl: chainUrl, + voteNodeUrl: voteNodeUrl, + plan: session.plan, + recovery: session.recovery, + ); + await _submitShares( + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + state = state.copyWith(stage: "done", progress: 1); + ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + } on Exception catch (e) { + state = state.copyWith(stage: "error", error: e.toString()); + ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + } + } + + void reset() { + state = VotingSubmissionJobState(stage: "idle", progress: 0); + } + + Future _runDelegation({ + required String chainUrl, + required String pirServerUrl, + VotingPirLayout? pirLayout, + String? roundParamsJson, + String? roundName, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + }) async { + final c = coinContext.coin; + final session = await ref.read(votingSessionProvider(roundId).future); + final plan = session.plan; + final steps = plan?.nextSteps ?? const []; + final delegateStep = steps.where((s) => s.kind == "delegate").firstOrNull; + final pollStep = + steps.where((s) => s.kind == "poll_delegation").firstOrNull; + if (delegateStep == null && pollStep == null) { + return; // no delegation work for this round + } + final bundleIndex = (delegateStep ?? pollStep!).bundleIndex; + + String? txHash; + if (delegateStep != null) { + state = state.copyWith(stage: "preparing"); + if (roundParamsJson != null && roundName != null) { + await delegationPrepare( + roundParamsJson: roundParamsJson, + roundName: roundName, + sessionJson: null, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl ?? "", + c: c, + ); + } else { + await delegationPrepareResume( + roundId: roundId, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c, + ); + } + + final setup = await delegationSetup( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ); + + state = state.copyWith(stage: "proving"); + final stream = delegationBuildSubmission( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: setup.pcztBytes, + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c, + ); + await for (final event in stream) { + switch (event) { + case VotingDelegationProgress_ProofProgress(:final progress): + state = state.copyWith(progress: progress); + default: + break; + } + } + + // The FRB boundary drops the build result when a StreamSink is present, + // so the wire body comes from the prop persisted by the build. + final wireJson = await delegationWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ); + if (wireJson == null || wireJson.isEmpty) { + throw AnyhowException( + "No wire JSON produced for round $roundId bundle $bundleIndex", + ); + } + + state = state.copyWith(stage: "submitting"); + final res = await votechainSubmitDelegation( + baseUrl: chainUrl, + submissionJson: wireJson, + c: c, + ); + if (res.statusCode == 422) { + throw AnyhowException( + "Delegation rejected by the vote chain: ${res.body}", + ); + } + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final result = jsonDecode(res.body) as Map; + txHash = result['tx_hash'] as String? ?? ""; + final code = result['code'] as int? ?? -1; + if (code != 0 || txHash.isEmpty) { + throw AnyhowException( + "Vote chain rejected the delegation: ${result['log'] ?? res.body}", + ); + } + + await delegationMarkSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: txHash, + c: c, + ); + } else { + // poll-only path: the tx hash is already recorded + final status = plan! + .delegationStatuses + .where((s) => s.bundleIndex == bundleIndex) + .firstOrNull; + txHash = status?.txHash; + if (txHash == null || txHash.isEmpty) { + throw AnyhowException( + "Round $roundId bundle $bundleIndex is pending but has no recorded tx hash", + ); + } + } + + state = state.copyWith(stage: "confirming"); + final eventsJson = + await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash!); + await delegationConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: txHash, + eventsJson: eventsJson, + c: c, + ); + await ref.read(votingSessionProvider(roundId).notifier).refresh(); + } + + Future _pollTxConfirmation({ + required String chainUrl, + required String txHash, + }) async { + final c = coinContext.coin; + for (var attempt = 0; attempt < 45; attempt++) { + final res = await votechainTxConfirmation( + baseUrl: chainUrl, + txHash: txHash, + c: c, + ); + if (res.statusCode == 200) { + final body = jsonDecode(res.body) as Map; + final events = body['events']; + return jsonEncode(events ?? const []); + } + await Future.delayed(const Duration(seconds: 2)); + } + throw AnyhowException( + "Timed out waiting for tx $txHash to confirm", + ); + } + + /// Casts and confirms the remaining votes for a round, recovery-first: + /// `cast_vote` steps commit (streamed), `submit_vote` steps broadcast and + /// confirm, `poll_vote` steps only poll a previously recorded tx. + Future _runVotes({ + required String chainUrl, + required String voteNodeUrl, + required VotingRoundPlan? plan, + required VotingRoundRecovery? recovery, + }) async { + if (plan == null) return; + final c = coinContext.coin; + final voteSteps = plan.nextSteps + .where((s) => + s.kind == "cast_vote" || + s.kind == "submit_vote" || + s.kind == "poll_vote") + .toList(); + if (voteSteps.isEmpty) return; + + final draftsJson = await votingDraftsLoad(roundId: roundId, c: c); + final byBundle = groupBy(voteSteps, (s) => s.bundleIndex); + + for (final entry in byBundle.entries) { + final bundleIndex = entry.key; + final steps = entry.value; + + final castSteps = + steps.where((s) => s.kind == "cast_vote").toList(); + if (castSteps.isNotEmpty) { + if (draftsJson == null || draftsJson.isEmpty) { + throw AnyhowException( + "No draft ballot saved for round $roundId; " + "open the ballot and review first", + ); + } + state = state.copyWith(stage: "voting"); + final stream = votingCommitWithProgress( + roundId: roundId, + bundleIndex: bundleIndex, + draftsJson: draftsJson, + voteNodeUrl: voteNodeUrl, + c: c, + ); + await for (final event in stream) { + switch (event) { + case VotingVoteCommitStage_ProofProgress(:final progress): + state = state.copyWith(progress: progress); + default: + break; + } + } + } + + for (final step in steps.where((s) => s.kind == "submit_vote")) { + state = state.copyWith(stage: "voting"); + final wireJson = await votingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: step.proposalId, + c: c, + ); + final res = await votechainSubmitVote( + baseUrl: chainUrl, + submissionJson: wireJson, + c: c, + ); + if (res.statusCode == 422) { + throw AnyhowException( + "Vote rejected by the vote chain: ${res.body}", + ); + } + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final result = jsonDecode(res.body) as Map; + final txHash = result['tx_hash'] as String? ?? ""; + final code = result['code'] as int? ?? -1; + if (code != 0 || txHash.isEmpty) { + throw AnyhowException( + "Vote chain rejected the vote: ${result['log'] ?? res.body}", + ); + } + + await votingMarkVoteSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: step.proposalId, + txHash: txHash, + c: c, + ); + state = state.copyWith(stage: "confirming"); + final eventsJson = + await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); + await votingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: step.proposalId, + txHash: txHash, + eventsJson: eventsJson, + c: c, + ); + } + + for (final step in steps.where((s) => s.kind == "poll_vote")) { + final vote = recovery?.votes + .where((v) => + v.bundleIndex == step.bundleIndex && + v.proposalId == step.proposalId) + .firstOrNull; + final txHash = vote?.txHash; + if (txHash == null || txHash.isEmpty) { + throw AnyhowException( + "Vote for proposal ${step.proposalId} is pending but has no " + "recorded tx hash", + ); + } + state = state.copyWith(stage: "confirming"); + final eventsJson = + await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); + await votingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: step.proposalId, + txHash: txHash, + eventsJson: eventsJson, + c: c, + ); + } + } + } + + /// Plans and submits helper shares for unconfirmed share rows. With no + /// active vote window or no helper servers configured this is a no-op + /// (the real inputs arrive with the dynamic config in a later phase). + Future _submitShares({ + required int ceremonyStart, + required int? voteEnd, + required List shareServerUrls, + required bool singleShare, + }) async { + final c = coinContext.coin; + state = state.copyWith(stage: "shares"); + final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final sharePlan = await votingSharePlan( + roundId: roundId, + now: BigInt.from(now), + ceremonyStart: BigInt.from(ceremonyStart), + voteEnd: voteEnd == null ? null : BigInt.from(voteEnd), + serverUrls: shareServerUrls, + singleShare: singleShare, + c: c, + ); + final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); + final count = min(sharePlan.submissions.length, unconfirmed.length); + for (var i = 0; i < count; i++) { + final item = sharePlan.submissions[i]; + final share = unconfirmed[i]; + final wireJson = await votingShareWireJson( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + vcTreePosition: null, + submitAt: item.submitAt, + c: c, + ); + final body = + jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); + for (final server in item.targetServers) { + final res = await votechainSubmitShare( + serverUrl: server, + payloadJson: body, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Share submit to $server failed " + "(HTTP ${res.statusCode}): ${res.body}", + ); + } + } + await votingShareRecord( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + sentToUrls: item.targetServers, + submitAt: item.submitAt, + c: c, + ); + } + + // Background tracking until every share confirms (or the vote window ends). + if (voteEnd != null && sharePlan.nextTrackingDelaySecs != null) { + _scheduleShareTracking( + delaySeconds: sharePlan.nextTrackingDelaySecs!.toInt(), + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + } + } + + void _scheduleShareTracking({ + required int delaySeconds, + required int ceremonyStart, + required int? voteEnd, + required List shareServerUrls, + required bool singleShare, + }) { + _shareTimer?.cancel(); + _shareTimer = Timer(Duration(seconds: delaySeconds), () async { + if (state.stage == "done" || state.stage == "error") { + try { + await _trackShares( + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + } on Exception catch (_) { + // The next tick retries; share tracking is best-effort. + } + } + }); + } + + /// One share-tracking tick: poll helper status for sent shares, resubmit + /// when the plan reports overdue shares, then re-arm if work remains. + Future _trackShares({ + required int ceremonyStart, + required int? voteEnd, + required List shareServerUrls, + required bool singleShare, + }) async { + final c = coinContext.coin; + final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final plan = await votingSharePlan( + roundId: roundId, + now: BigInt.from(now), + ceremonyStart: BigInt.from(ceremonyStart), + voteEnd: voteEnd == null ? null : BigInt.from(voteEnd), + serverUrls: shareServerUrls, + singleShare: singleShare, + c: c, + ); + final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); + if (unconfirmed.isEmpty) return; + + for (final share in unconfirmed) { + if (share.sentToUrls.isEmpty) continue; + final shareId = hex.encode(share.nullifier); + final res = await votechainShareStatus( + serverUrl: share.sentToUrls.first, + roundId: roundId, + shareId: shareId, + c: c, + ); + if (res.statusCode == 200) { + await votingShareConfirm( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + c: c, + ); + } + } + + if (plan.summary.overdue > BigInt.zero) { + final count = min(plan.submissions.length, unconfirmed.length); + for (var i = 0; i < count; i++) { + final item = plan.submissions[i]; + final share = unconfirmed[i]; + final wireJson = await votingShareWireJson( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + vcTreePosition: null, + submitAt: item.submitAt, + c: c, + ); + final body = + jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); + for (final server in item.targetServers) { + final res = await votechainResubmitShare( + serverUrl: server, + payloadJson: body, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Share resubmit to $server failed " + "(HTTP ${res.statusCode}): ${res.body}", + ); + } + } + await votingShareAddServers( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + newUrls: item.targetServers, + c: c, + ); + } + } + + if (voteEnd != null && plan.nextTrackingDelaySecs != null) { + _scheduleShareTracking( + delaySeconds: plan.nextTrackingDelaySecs!.toInt(), + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + } + } +} diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index ad7e227e2..2ecb9bcaf 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -1347,6 +1347,8 @@ mixin _$AppSettings { bool get darkMode; bool get transactionTableMode; String get currency; + String get votingConfigUrl; + String get voteNodeUrl; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -1395,7 +1397,11 @@ mixin _$AppSettings { (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && (identical(other.currency, currency) || - other.currency == currency)); + other.currency == currency) && + (identical(other.votingConfigUrl, votingConfigUrl) || + other.votingConfigUrl == votingConfigUrl) && + (identical(other.voteNodeUrl, voteNodeUrl) || + other.voteNodeUrl == voteNodeUrl)); } @override @@ -1422,12 +1428,14 @@ mixin _$AppSettings { paletteName, darkMode, transactionTableMode, - currency + currency, + votingConfigUrl, + voteNodeUrl ]); @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; } } @@ -1459,7 +1467,9 @@ abstract mixin class $AppSettingsCopyWith<$Res> { String paletteName, bool darkMode, bool transactionTableMode, - String currency}); + String currency, + String votingConfigUrl, + String voteNodeUrl}); $QRSettingsCopyWith<$Res> get qrSettings; } @@ -1498,6 +1508,8 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { Object? darkMode = null, Object? transactionTableMode = null, Object? currency = null, + Object? votingConfigUrl = null, + Object? voteNodeUrl = null, }) { return _then(_self.copyWith( dbName: null == dbName @@ -1588,6 +1600,14 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { ? _self.currency : currency // ignore: cast_nullable_to_non_nullable as String, + votingConfigUrl: null == votingConfigUrl + ? _self.votingConfigUrl + : votingConfigUrl // ignore: cast_nullable_to_non_nullable + as String, + voteNodeUrl: null == voteNodeUrl + ? _self.voteNodeUrl + : voteNodeUrl // ignore: cast_nullable_to_non_nullable + as String, )); } @@ -1715,7 +1735,9 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, - String currency)? + String currency, + String votingConfigUrl, + String voteNodeUrl)? $default, { required TResult orElse(), }) { @@ -1744,7 +1766,9 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, - _that.currency); + _that.currency, + _that.votingConfigUrl, + _that.voteNodeUrl); case _: return orElse(); } @@ -1787,7 +1811,9 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, - String currency) + String currency, + String votingConfigUrl, + String voteNodeUrl) $default, ) { final _that = this; @@ -1815,7 +1841,9 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, - _that.currency); + _that.currency, + _that.votingConfigUrl, + _that.voteNodeUrl); } } @@ -1855,7 +1883,9 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, - String currency)? + String currency, + String votingConfigUrl, + String voteNodeUrl)? $default, ) { final _that = this; @@ -1883,7 +1913,9 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, - _that.currency); + _that.currency, + _that.votingConfigUrl, + _that.voteNodeUrl); case _: return null; } @@ -1915,7 +1947,9 @@ class _AppSettings implements AppSettings { required this.paletteName, required this.darkMode, required this.transactionTableMode, - required this.currency}); + required this.currency, + required this.votingConfigUrl, + required this.voteNodeUrl}); @override final String dbName; @@ -1962,6 +1996,10 @@ class _AppSettings implements AppSettings { final bool transactionTableMode; @override final String currency; + @override + final String votingConfigUrl; + @override + final String voteNodeUrl; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -2011,7 +2049,11 @@ class _AppSettings implements AppSettings { (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && (identical(other.currency, currency) || - other.currency == currency)); + other.currency == currency) && + (identical(other.votingConfigUrl, votingConfigUrl) || + other.votingConfigUrl == votingConfigUrl) && + (identical(other.voteNodeUrl, voteNodeUrl) || + other.voteNodeUrl == voteNodeUrl)); } @override @@ -2038,12 +2080,14 @@ class _AppSettings implements AppSettings { paletteName, darkMode, transactionTableMode, - currency + currency, + votingConfigUrl, + voteNodeUrl ]); @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; } } @@ -2077,7 +2121,9 @@ abstract mixin class _$AppSettingsCopyWith<$Res> String paletteName, bool darkMode, bool transactionTableMode, - String currency}); + String currency, + String votingConfigUrl, + String voteNodeUrl}); @override $QRSettingsCopyWith<$Res> get qrSettings; @@ -2117,6 +2163,8 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { Object? darkMode = null, Object? transactionTableMode = null, Object? currency = null, + Object? votingConfigUrl = null, + Object? voteNodeUrl = null, }) { return _then(_AppSettings( dbName: null == dbName @@ -2207,6 +2255,14 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { ? _self.currency : currency // ignore: cast_nullable_to_non_nullable as String, + votingConfigUrl: null == votingConfigUrl + ? _self.votingConfigUrl + : votingConfigUrl // ignore: cast_nullable_to_non_nullable + as String, + voteNodeUrl: null == voteNodeUrl + ? _self.voteNodeUrl + : voteNodeUrl // ignore: cast_nullable_to_non_nullable + as String, )); } @@ -4589,4 +4645,724 @@ class __$QRSettingsCopyWithImpl<$Res> implements _$QRSettingsCopyWith<$Res> { } } +/// @nodoc +mixin _$VotingSessionState { + VotingRoundPlan? get plan; + VotingRoundRecovery? get recovery; + List get intents; + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSessionStateCopyWith get copyWith => + _$VotingSessionStateCopyWithImpl( + this as VotingSessionState, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSessionState && + (identical(other.plan, plan) || other.plan == plan) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && + const DeepCollectionEquality().equals(other.intents, intents)); + } + + @override + int get hashCode => Object.hash(runtimeType, plan, recovery, + const DeepCollectionEquality().hash(intents)); + + @override + String toString() { + return 'VotingSessionState(plan: $plan, recovery: $recovery, intents: $intents)'; + } +} + +/// @nodoc +abstract mixin class $VotingSessionStateCopyWith<$Res> { + factory $VotingSessionStateCopyWith( + VotingSessionState value, $Res Function(VotingSessionState) _then) = + _$VotingSessionStateCopyWithImpl; + @useResult + $Res call( + {VotingRoundPlan? plan, + VotingRoundRecovery? recovery, + List intents}); + + $VotingRoundPlanCopyWith<$Res>? get plan; + $VotingRoundRecoveryCopyWith<$Res>? get recovery; +} + +/// @nodoc +class _$VotingSessionStateCopyWithImpl<$Res> + implements $VotingSessionStateCopyWith<$Res> { + _$VotingSessionStateCopyWithImpl(this._self, this._then); + + final VotingSessionState _self; + final $Res Function(VotingSessionState) _then; + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? plan = freezed, + Object? recovery = freezed, + Object? intents = null, + }) { + return _then(_self.copyWith( + plan: freezed == plan + ? _self.plan + : plan // ignore: cast_nullable_to_non_nullable + as VotingRoundPlan?, + recovery: freezed == recovery + ? _self.recovery + : recovery // ignore: cast_nullable_to_non_nullable + as VotingRoundRecovery?, + intents: null == intents + ? _self.intents + : intents // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundPlanCopyWith<$Res>? get plan { + if (_self.plan == null) { + return null; + } + + return $VotingRoundPlanCopyWith<$Res>(_self.plan!, (value) { + return _then(_self.copyWith(plan: value)); + }); + } + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundRecoveryCopyWith<$Res>? get recovery { + if (_self.recovery == null) { + return null; + } + + return $VotingRoundRecoveryCopyWith<$Res>(_self.recovery!, (value) { + return _then(_self.copyWith(recovery: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingSessionState]. +extension VotingSessionStatePatterns on VotingSessionState { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSessionState value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSessionState() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSessionState value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSessionState(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSessionState value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSessionState() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(VotingRoundPlan? plan, VotingRoundRecovery? recovery, + List intents)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSessionState() when $default != null: + return $default(_that.plan, _that.recovery, _that.intents); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(VotingRoundPlan? plan, VotingRoundRecovery? recovery, + List intents) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSessionState(): + return $default(_that.plan, _that.recovery, _that.intents); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(VotingRoundPlan? plan, VotingRoundRecovery? recovery, + List intents)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingSessionState() when $default != null: + return $default(_that.plan, _that.recovery, _that.intents); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSessionState implements VotingSessionState { + _VotingSessionState( + {required this.plan, + required this.recovery, + required final List intents}) + : _intents = intents; + + @override + final VotingRoundPlan? plan; + @override + final VotingRoundRecovery? recovery; + final List _intents; + @override + List get intents { + if (_intents is EqualUnmodifiableListView) return _intents; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_intents); + } + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSessionStateCopyWith<_VotingSessionState> get copyWith => + __$VotingSessionStateCopyWithImpl<_VotingSessionState>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSessionState && + (identical(other.plan, plan) || other.plan == plan) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && + const DeepCollectionEquality().equals(other._intents, _intents)); + } + + @override + int get hashCode => Object.hash(runtimeType, plan, recovery, + const DeepCollectionEquality().hash(_intents)); + + @override + String toString() { + return 'VotingSessionState(plan: $plan, recovery: $recovery, intents: $intents)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSessionStateCopyWith<$Res> + implements $VotingSessionStateCopyWith<$Res> { + factory _$VotingSessionStateCopyWith( + _VotingSessionState value, $Res Function(_VotingSessionState) _then) = + __$VotingSessionStateCopyWithImpl; + @override + @useResult + $Res call( + {VotingRoundPlan? plan, + VotingRoundRecovery? recovery, + List intents}); + + @override + $VotingRoundPlanCopyWith<$Res>? get plan; + @override + $VotingRoundRecoveryCopyWith<$Res>? get recovery; +} + +/// @nodoc +class __$VotingSessionStateCopyWithImpl<$Res> + implements _$VotingSessionStateCopyWith<$Res> { + __$VotingSessionStateCopyWithImpl(this._self, this._then); + + final _VotingSessionState _self; + final $Res Function(_VotingSessionState) _then; + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? plan = freezed, + Object? recovery = freezed, + Object? intents = null, + }) { + return _then(_VotingSessionState( + plan: freezed == plan + ? _self.plan + : plan // ignore: cast_nullable_to_non_nullable + as VotingRoundPlan?, + recovery: freezed == recovery + ? _self.recovery + : recovery // ignore: cast_nullable_to_non_nullable + as VotingRoundRecovery?, + intents: null == intents + ? _self._intents + : intents // ignore: cast_nullable_to_non_nullable + as List, + )); + } + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundPlanCopyWith<$Res>? get plan { + if (_self.plan == null) { + return null; + } + + return $VotingRoundPlanCopyWith<$Res>(_self.plan!, (value) { + return _then(_self.copyWith(plan: value)); + }); + } + + /// Create a copy of VotingSessionState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundRecoveryCopyWith<$Res>? get recovery { + if (_self.recovery == null) { + return null; + } + + return $VotingRoundRecoveryCopyWith<$Res>(_self.recovery!, (value) { + return _then(_self.copyWith(recovery: value)); + }); + } +} + +/// @nodoc +mixin _$VotingSubmissionJobState { + String get stage; // idle|preparing|proving|submitting|confirming|done|error + double get progress; + String? get error; + + /// Create a copy of VotingSubmissionJobState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingSubmissionJobStateCopyWith get copyWith => + _$VotingSubmissionJobStateCopyWithImpl( + this as VotingSubmissionJobState, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingSubmissionJobState && + (identical(other.stage, stage) || other.stage == stage) && + (identical(other.progress, progress) || + other.progress == progress) && + (identical(other.error, error) || other.error == error)); + } + + @override + int get hashCode => Object.hash(runtimeType, stage, progress, error); + + @override + String toString() { + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error)'; + } +} + +/// @nodoc +abstract mixin class $VotingSubmissionJobStateCopyWith<$Res> { + factory $VotingSubmissionJobStateCopyWith(VotingSubmissionJobState value, + $Res Function(VotingSubmissionJobState) _then) = + _$VotingSubmissionJobStateCopyWithImpl; + @useResult + $Res call({String stage, double progress, String? error}); +} + +/// @nodoc +class _$VotingSubmissionJobStateCopyWithImpl<$Res> + implements $VotingSubmissionJobStateCopyWith<$Res> { + _$VotingSubmissionJobStateCopyWithImpl(this._self, this._then); + + final VotingSubmissionJobState _self; + final $Res Function(VotingSubmissionJobState) _then; + + /// Create a copy of VotingSubmissionJobState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? stage = null, + Object? progress = null, + Object? error = freezed, + }) { + return _then(_self.copyWith( + stage: null == stage + ? _self.stage + : stage // ignore: cast_nullable_to_non_nullable + as String, + progress: null == progress + ? _self.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + error: freezed == error + ? _self.error + : error // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingSubmissionJobState]. +extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_VotingSubmissionJobState value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_VotingSubmissionJobState value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_VotingSubmissionJobState value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String stage, double progress, String? error)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState() when $default != null: + return $default(_that.stage, _that.progress, _that.error); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String stage, double progress, String? error) $default, + ) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState(): + return $default(_that.stage, _that.progress, _that.error); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String stage, double progress, String? error)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingSubmissionJobState() when $default != null: + return $default(_that.stage, _that.progress, _that.error); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingSubmissionJobState implements VotingSubmissionJobState { + _VotingSubmissionJobState( + {required this.stage, required this.progress, this.error}); + + @override + final String stage; +// idle|preparing|proving|submitting|confirming|done|error + @override + final double progress; + @override + final String? error; + + /// Create a copy of VotingSubmissionJobState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingSubmissionJobStateCopyWith<_VotingSubmissionJobState> get copyWith => + __$VotingSubmissionJobStateCopyWithImpl<_VotingSubmissionJobState>( + this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingSubmissionJobState && + (identical(other.stage, stage) || other.stage == stage) && + (identical(other.progress, progress) || + other.progress == progress) && + (identical(other.error, error) || other.error == error)); + } + + @override + int get hashCode => Object.hash(runtimeType, stage, progress, error); + + @override + String toString() { + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error)'; + } +} + +/// @nodoc +abstract mixin class _$VotingSubmissionJobStateCopyWith<$Res> + implements $VotingSubmissionJobStateCopyWith<$Res> { + factory _$VotingSubmissionJobStateCopyWith(_VotingSubmissionJobState value, + $Res Function(_VotingSubmissionJobState) _then) = + __$VotingSubmissionJobStateCopyWithImpl; + @override + @useResult + $Res call({String stage, double progress, String? error}); +} + +/// @nodoc +class __$VotingSubmissionJobStateCopyWithImpl<$Res> + implements _$VotingSubmissionJobStateCopyWith<$Res> { + __$VotingSubmissionJobStateCopyWithImpl(this._self, this._then); + + final _VotingSubmissionJobState _self; + final $Res Function(_VotingSubmissionJobState) _then; + + /// Create a copy of VotingSubmissionJobState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? stage = null, + Object? progress = null, + Object? error = freezed, + }) { + return _then(_VotingSubmissionJobState( + stage: null == stage + ? _self.stage + : stage // ignore: cast_nullable_to_non_nullable + as String, + progress: null == progress + ? _self.progress + : progress // ignore: cast_nullable_to_non_nullable + as double, + error: freezed == error + ? _self.error + : error // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + // dart format on diff --git a/lib/store.g.dart b/lib/store.g.dart index ca1dc410f..b56267cda 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -619,7 +619,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'c8611b3252b3a7ff4c27392a1b5345019eb405aa'; + r'7772fb1c14262ec8f76f7d44c600d06358ec5ebb'; abstract class _$AppSettingsNotifier extends $AsyncNotifier { FutureOr build(); @@ -1262,7 +1262,7 @@ final class VaultNotifierProvider VaultNotifier create() => VaultNotifier(); } -String _$vaultNotifierHash() => r'422ba342430a4319552b41d8dbe378de7dba470a'; +String _$vaultNotifierHash() => r'f1317577395220210fdffc5a59cd90bb6ad683da'; abstract class _$VaultNotifier extends $AsyncNotifier { FutureOr build(); @@ -1415,3 +1415,394 @@ final class PluginMemoSectionsFamily extends $Family @override String toString() => r'pluginMemoSectionsProvider'; } + +/// Per-round voting session. `build()` is the recovery-first triple load; +/// `refresh()` re-runs it after an action mutates the voting DB. + +@ProviderFor(VotingSession) +const votingSessionProvider = VotingSessionFamily._(); + +/// Per-round voting session. `build()` is the recovery-first triple load; +/// `refresh()` re-runs it after an action mutates the voting DB. +final class VotingSessionProvider + extends $AsyncNotifierProvider { + /// Per-round voting session. `build()` is the recovery-first triple load; + /// `refresh()` re-runs it after an action mutates the voting DB. + const VotingSessionProvider._( + {required VotingSessionFamily super.from, required String super.argument}) + : super( + retry: null, + name: r'votingSessionProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingSessionHash(); + + @override + String toString() { + return r'votingSessionProvider' + '' + '($argument)'; + } + + @$internal + @override + VotingSession create() => VotingSession(); + + @override + bool operator ==(Object other) { + return other is VotingSessionProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$votingSessionHash() => r'74d90be6f0517caae693468712cabce9319f0584'; + +/// Per-round voting session. `build()` is the recovery-first triple load; +/// `refresh()` re-runs it after an action mutates the voting DB. + +final class VotingSessionFamily extends $Family + with + $ClassFamilyOverride, + VotingSessionState, FutureOr, String> { + const VotingSessionFamily._() + : super( + retry: null, + name: r'votingSessionProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: false, + ); + + /// Per-round voting session. `build()` is the recovery-first triple load; + /// `refresh()` re-runs it after an action mutates the voting DB. + + VotingSessionProvider call( + String roundId, + ) => + VotingSessionProvider._(argument: roundId, from: this); + + @override + String toString() => r'votingSessionProvider'; +} + +/// Per-round voting session. `build()` is the recovery-first triple load; +/// `refresh()` re-runs it after an action mutates the voting DB. + +abstract class _$VotingSession extends $AsyncNotifier { + late final _$args = ref.$arg as String; + String get roundId => _$args; + + FutureOr build( + String roundId, + ); + @$mustCallSuper + @override + void runBuild() { + final created = build( + _$args, + ); + final ref = + this.ref as $Ref, VotingSessionState>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, VotingSessionState>, + AsyncValue, + Object?, + Object?>; + element.handleValue(ref, created); + } +} + +/// Rounds persisted in the voting DB for the current wallet. + +@ProviderFor(votingRoundList) +const votingRoundListProvider = VotingRoundListProvider._(); + +/// Rounds persisted in the voting DB for the current wallet. + +final class VotingRoundListProvider extends $FunctionalProvider< + AsyncValue>, + List, + FutureOr>> + with + $FutureModifier>, + $FutureProvider> { + /// Rounds persisted in the voting DB for the current wallet. + const VotingRoundListProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'votingRoundListProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingRoundListHash(); + + @$internal + @override + $FutureProviderElement> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + return votingRoundList(ref); + } +} + +String _$votingRoundListHash() => r'12d2cfda4753a04d9343e21a6637789106c3ffb5'; + +/// Resolved and authenticated voting config for the configured source URL. +/// Resolves fresh on build; on failure falls back to the last cached config. + +@ProviderFor(VotingConfigNotifier) +const votingConfigProvider = VotingConfigNotifierProvider._(); + +/// Resolved and authenticated voting config for the configured source URL. +/// Resolves fresh on build; on failure falls back to the last cached config. +final class VotingConfigNotifierProvider + extends $AsyncNotifierProvider { + /// Resolved and authenticated voting config for the configured source URL. + /// Resolves fresh on build; on failure falls back to the last cached config. + const VotingConfigNotifierProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'votingConfigProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingConfigNotifierHash(); + + @$internal + @override + VotingConfigNotifier create() => VotingConfigNotifier(); +} + +String _$votingConfigNotifierHash() => + r'ed064685d2a96f9c26b4e3e40636d03d32287caf'; + +/// Resolved and authenticated voting config for the configured source URL. +/// Resolves fresh on build; on failure falls back to the last cached config. + +abstract class _$VotingConfigNotifier extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref, VotingConfig?>; + final element = ref.element as $ClassProviderElement< + AnyNotifier, VotingConfig?>, + AsyncValue, + Object?, + Object?>; + element.handleValue(ref, created); + } +} + +/// Blocks destructive wallet actions (account deletion, vault sign-out, +/// wallet removal) while a voting submission job is in flight. + +@ProviderFor(VotingSubmissionGuard) +const votingSubmissionGuardProvider = VotingSubmissionGuardProvider._(); + +/// Blocks destructive wallet actions (account deletion, vault sign-out, +/// wallet removal) while a voting submission job is in flight. +final class VotingSubmissionGuardProvider + extends $NotifierProvider { + /// Blocks destructive wallet actions (account deletion, vault sign-out, + /// wallet removal) while a voting submission job is in flight. + const VotingSubmissionGuardProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'votingSubmissionGuardProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingSubmissionGuardHash(); + + @$internal + @override + VotingSubmissionGuard create() => VotingSubmissionGuard(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(bool value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$votingSubmissionGuardHash() => + r'7fbcb88ac8361aa94083e9d98321f96c521a2777'; + +/// Blocks destructive wallet actions (account deletion, vault sign-out, +/// wallet removal) while a voting submission job is in flight. + +abstract class _$VotingSubmissionGuard extends $Notifier { + bool build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref; + final element = ref.element as $ClassProviderElement< + AnyNotifier, bool, Object?, Object?>; + element.handleValue(ref, created); + } +} + +/// Delegation execution job for one round. Runs the serialized chain: +/// prepare (or resume) → setup → build submission (progress stream) → +/// broadcast → mark submitted → poll confirmation → confirm. Vote casting +/// lands in a later phase. Restart-safe: the resume plan decides which steps +/// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. + +@ProviderFor(VotingSubmissionJob) +const votingSubmissionJobProvider = VotingSubmissionJobFamily._(); + +/// Delegation execution job for one round. Runs the serialized chain: +/// prepare (or resume) → setup → build submission (progress stream) → +/// broadcast → mark submitted → poll confirmation → confirm. Vote casting +/// lands in a later phase. Restart-safe: the resume plan decides which steps +/// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. +final class VotingSubmissionJobProvider + extends $NotifierProvider { + /// Delegation execution job for one round. Runs the serialized chain: + /// prepare (or resume) → setup → build submission (progress stream) → + /// broadcast → mark submitted → poll confirmation → confirm. Vote casting + /// lands in a later phase. Restart-safe: the resume plan decides which steps + /// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. + const VotingSubmissionJobProvider._( + {required VotingSubmissionJobFamily super.from, + required String super.argument}) + : super( + retry: null, + name: r'votingSubmissionJobProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingSubmissionJobHash(); + + @override + String toString() { + return r'votingSubmissionJobProvider' + '' + '($argument)'; + } + + @$internal + @override + VotingSubmissionJob create() => VotingSubmissionJob(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(VotingSubmissionJobState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } + + @override + bool operator ==(Object other) { + return other is VotingSubmissionJobProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$votingSubmissionJobHash() => + r'5dfea23a8350a2f2194fe16b725caffd2a1f33a6'; + +/// Delegation execution job for one round. Runs the serialized chain: +/// prepare (or resume) → setup → build submission (progress stream) → +/// broadcast → mark submitted → poll confirmation → confirm. Vote casting +/// lands in a later phase. Restart-safe: the resume plan decides which steps +/// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. + +final class VotingSubmissionJobFamily extends $Family + with + $ClassFamilyOverride { + const VotingSubmissionJobFamily._() + : super( + retry: null, + name: r'votingSubmissionJobProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: false, + ); + + /// Delegation execution job for one round. Runs the serialized chain: + /// prepare (or resume) → setup → build submission (progress stream) → + /// broadcast → mark submitted → poll confirmation → confirm. Vote casting + /// lands in a later phase. Restart-safe: the resume plan decides which steps + /// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. + + VotingSubmissionJobProvider call( + String roundId, + ) => + VotingSubmissionJobProvider._(argument: roundId, from: this); + + @override + String toString() => r'votingSubmissionJobProvider'; +} + +/// Delegation execution job for one round. Runs the serialized chain: +/// prepare (or resume) → setup → build submission (progress stream) → +/// broadcast → mark submitted → poll confirmation → confirm. Vote casting +/// lands in a later phase. Restart-safe: the resume plan decides which steps +/// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. + +abstract class _$VotingSubmissionJob + extends $Notifier { + late final _$args = ref.$arg as String; + String get roundId => _$args; + + VotingSubmissionJobState build( + String roundId, + ); + @$mustCallSuper + @override + void runBuild() { + final created = build( + _$args, + ); + final ref = + this.ref as $Ref; + final element = ref.element as $ClassProviderElement< + AnyNotifier, + VotingSubmissionJobState, + Object?, + Object?>; + element.handleValue(ref, created); + } +} diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index b063f02a3..02ae2a058 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -6,13 +6,24 @@ //! then van witness → commit → payloads → record execution → confirm. use anyhow::{anyhow, Result}; +use rand_core::{OsRng, RngCore}; use serde::{Deserialize, Serialize}; -use zcash_voting::prelude::{BundlePolicy, NoopProgressReporter, TxEvent}; -use zcash_voting::VotingRoundParams; +use zcash_voting::prelude::{ + BundlePolicy, DelegationProgress, DelegationProgressBridge, DraftVote, NoopProgressReporter, + ShareTimingPolicy, TxEvent, VoteCommitStageBridge, +}; +use zcash_voting::recovery::{ + DelegationRecovery as ForkDelegationRecovery, RoundRecoverySnapshot as ForkRoundRecovery, + ShareWorkflow as ForkShareWorkflow, VoteRecovery as ForkVoteRecovery, +}; +use zcash_voting::round::RoundInfo as ForkRoundInfo; +use zcash_voting::session::{Decision, NextStep, RoundPlan as ForkRoundPlan}; +use zcash_voting::types::ShareDelegationRecord as ForkShareDelegationRecord; +use zcash_voting::{Network as VotingNetwork, VotingRoundParams}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; -use crate::{api::coin::Coin, voting}; +use crate::{api::coin::Coin, frb_generated::StreamSink, voting}; // --------------------------------------------------------------------------- // Mirror types @@ -38,7 +49,7 @@ pub struct VotingPirLayout { } impl VotingPirLayout { - fn to_fork(self) -> zcash_voting::config::PirLayout { + fn to_fork(&self) -> zcash_voting::config::PirLayout { zcash_voting::config::PirLayout { pir_depth: self.pir_depth, tier0_layers: self.tier0_layers, @@ -48,6 +59,17 @@ impl VotingPirLayout { } } +impl From for VotingPirLayout { + fn from(l: zcash_voting::config::PirLayout) -> Self { + Self { + pir_depth: l.pir_depth, + tier0_layers: l.tier0_layers, + tier1_layers: l.tier1_layers, + poly_len: l.poly_len, + } + } +} + #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct VotingDelegationSetup { @@ -75,6 +97,13 @@ pub struct VotingDelegationSubmission { pub tx1_effects: Vec, } +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationBuild { + pub submission: VotingDelegationSubmission, + pub wire_json: String, +} + #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct VotingDelegationConfirmation { @@ -329,7 +358,9 @@ pub async fn voting_hotkey_get(c: &Coin) -> Result { /// /// `round_params_json` is the JSON-serialized `VotingRoundParams` from the /// vote chain. The wallet must be synced through the round snapshot height; -/// witnesses are rooted at the snapshot's Ironwood `nc_root`. +/// witnesses are rooted at the snapshot's Ironwood `nc_root`. On success the +/// round inputs are persisted (props table) so a restart can re-prepare via +/// [`delegation_prepare_resume`]. #[cfg_attr(feature = "flutter", frb)] #[allow(clippy::too_many_arguments)] pub async fn delegation_prepare( @@ -340,6 +371,71 @@ pub async fn delegation_prepare( max_real_notes_per_bundle: Option, lightwalletd_url: &str, c: &Coin, +) -> Result { + let info = prepare_bundle( + round_params_json, + round_name, + session_json, + bundle_index, + max_real_notes_per_bundle, + lightwalletd_url, + c, + ) + .await?; + let mut connection = c.get_connection().await?; + voting::save_round_config( + &mut connection, + &info.round_id, + round_params_json, + round_name, + max_real_notes_per_bundle, + lightwalletd_url, + ) + .await?; + Ok(info) +} + +/// Re-runs [`delegation_prepare`] for a round whose prepared bundle was lost +/// with the process (the prepared-bundle cache is process-local). Inputs come +/// from the config saved by the first prepare; the optional params override +/// the saved values when present. +#[cfg_attr(feature = "flutter", frb)] +pub async fn delegation_prepare_resume( + round_id: &str, + bundle_index: u32, + max_real_notes_per_bundle: Option, + lightwalletd_url: Option, + c: &Coin, +) -> Result { + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let (round_params_json, round_name, saved_policy, saved_lwd) = + voting::load_round_config(&mut connection, &round_id).await?; + drop(connection); + + let bundle_policy = max_real_notes_per_bundle.or(saved_policy); + let lightwalletd_url = lightwalletd_url.unwrap_or(saved_lwd); + prepare_bundle( + &round_params_json, + &round_name, + None, + bundle_index, + bundle_policy, + &lightwalletd_url, + c, + ) + .await +} + +/// Shared prepare pipeline; see [`delegation_prepare`]. +async fn prepare_bundle( + round_params_json: &str, + round_name: &str, + session_json: Option, + bundle_index: u32, + max_real_notes_per_bundle: Option, + lightwalletd_url: &str, + c: &Coin, ) -> Result { let account = c.account; let wallet_network = &c.network(); @@ -427,7 +523,7 @@ pub async fn delegation_sign_and_submit( let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; let seed = voting::account_seed(&mut connection, c.account).await?; - let submission = voting::prove_and_submit_delegation( + let (submission, _wire_json) = voting::prove_and_submit_delegation( c.get_pool()?, &wallet_id, &prepared, @@ -465,151 +561,1557 @@ pub async fn delegation_confirm( Ok(confirmation.into()) } -// --------------------------------------------------------------------------- -// Vote casting flow -// --------------------------------------------------------------------------- - -/// Syncs the vote-authority-note tree and derives this bundle's VAN witness. +/// Builds and signs the delegation payload with live progress events +/// (`delegation_sign_and_submit` without the progress stream). +/// +/// `pir_layout` is persisted on first use; pass `None` after a restart to +/// resume with the saved layout. Returns the submission together with its +/// vote-chain wire JSON body (ready for `votechain_submit_delegation`). #[cfg_attr(feature = "flutter", frb)] -pub async fn voting_van_witness( +#[allow(clippy::too_many_arguments)] +pub async fn delegation_build_submission( + sink: StreamSink, round_id: &str, bundle_index: u32, - vote_node_url: &str, + pczt_bytes: Vec, + pir_layout: Option, + pir_server_url: &str, c: &Coin, -) -> Result { +) -> Result { + let account = c.account; + let round_id = round_id.to_string(); + let pir_server_url = pir_server_url.to_string(); let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; - let witness = voting::vote_van_witness( + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let pir_server_url = if pir_server_url.is_empty() { + crate::db::get_prop( + &mut connection, + &format!("voting_round_pir_url:{round_id}"), + ) + .await? + .ok_or_else(|| { + anyhow!("no saved PIR server URL for round {round_id}; pass pir_server_url once") + })? + } else { + crate::db::put_prop( + &mut connection, + &format!("voting_round_pir_url:{round_id}"), + &pir_server_url, + ) + .await?; + pir_server_url + }; + let pir_layout = match pir_layout { + Some(layout) => { + voting::save_pir_layout(&mut connection, &round_id, &layout.to_fork()).await?; + layout + } + None => voting::load_pir_layout(&mut connection, &round_id) + .await? + .map(Into::into) + .ok_or_else(|| { + anyhow!("no saved PIR layout for round {round_id}; pass pir_layout once") + })?, + }; + let prepared = voting::load_prepared_bundle(&wallet_id, &round_id, bundle_index)?; + let seed = voting::account_seed(&mut connection, account).await?; + + let progress = DelegationProgressBridge::new(move |p| { + let _ = sink.add(p.into()); + }); + let (submission, wire_json) = voting::prove_and_submit_delegation_with_progress( c.get_pool()?, &wallet_id, - round_id, - bundle_index, - vote_node_url, + &prepared, + &seed, + pczt_bytes, + pir_layout.to_fork(), + &pir_server_url, + &progress, ) .await?; - Ok(witness.into()) + // The FRB boundary drops this return value (StreamSink params take over), + // so persist the wire body for `delegation_wire_json` to pick up. This also + // makes a crash between proving and broadcasting resumable without + // re-proving. + crate::db::put_prop( + &mut connection, + &format!("voting_round_delegation_wire:{round_id}:{bundle_index}"), + &wire_json, + ) + .await?; + Ok(VotingDelegationBuild { + submission: submission.into(), + wire_json, + }) } -/// Commits a batch of vote drafts for one bundle (hotkey-signed). -/// -/// Chains the VAN witness derivation internally, so this may be called right -/// after `voting_van_witness` or standalone. +/// Returns the vote-chain wire JSON built by the last +/// [`delegation_build_submission`] run for a bundle, if any. #[cfg_attr(feature = "flutter", frb)] -pub async fn voting_commit( +pub async fn delegation_wire_json( + round_id: &str, + bundle_index: u32, + c: &Coin, +) -> Result> { + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + Ok( + crate::db::get_prop( + &mut connection, + &format!("voting_round_delegation_wire:{round_id}:{bundle_index}"), + ) + .await?, + ) +} + +/// Atomically records a delegation transaction hash with idempotency checks, +/// so a restart between broadcast and confirmation resumes via `PollDelegation` +/// instead of re-broadcasting. +#[cfg_attr(feature = "flutter", frb)] +pub async fn delegation_mark_submitted( + round_id: &str, + bundle_index: u32, + tx_hash: &str, + c: &Coin, +) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let tx_hash = tx_hash.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + db.mark_delegation_submitted(&round_id, bundle_index, &tx_hash) + .await?; + Ok(()) +} + +/// Returns the recorded delegation transaction hash for a bundle, if any. +#[cfg_attr(feature = "flutter", frb)] +pub async fn delegation_tx_hash( + round_id: &str, + bundle_index: u32, + c: &Coin, +) -> Result> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + Ok(db.get_delegation_tx_hash(&round_id, bundle_index).await?) +} + +// --------------------------------------------------------------------------- +// Vote flow +// --------------------------------------------------------------------------- + +/// Persists the voter's terminal decision for one proposal before any +/// zero-knowledge work, so a crash cannot lose the ballot and later votes are +/// conflict-checked against it. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_set_ballot_intent( + round_id: &str, + proposal_id: u32, + skipped: bool, + choice: u32, + num_options: u32, + c: &Coin, +) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let decision = if skipped { + Decision::Skipped + } else { + Decision::Choice(choice) + }; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + db.set_ballot_intent(&round_id, proposal_id, decision, num_options) + .await?; + Ok(()) +} + +/// Persists the draft ballot for a round (props table, wallet-scoped). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_drafts_save(round_id: &str, drafts_json: &str, c: &Coin) -> Result<()> { + let round_id = round_id.to_string(); + let drafts_json = drafts_json.to_string(); + let mut connection = c.get_connection().await?; + crate::db::put_prop( + &mut connection, + &format!("voting_drafts:{round_id}"), + &drafts_json, + ) + .await?; + Ok(()) +} + +/// Returns the persisted draft ballot for a round, if any. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_drafts_load(round_id: &str, c: &Coin) -> Result> { + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + Ok(crate::db::get_prop(&mut connection, &format!("voting_drafts:{round_id}")).await?) +} + +/// Commits one bundle's votes with live stage events. Draft votes are +/// JSON-serialized fork `DraftVote`s; the VAN witness is derived internally +/// after syncing the vote tree. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_commit_with_progress( + sink: StreamSink, round_id: &str, bundle_index: u32, drafts_json: &str, vote_node_url: &str, c: &Coin, ) -> Result { - let drafts: Vec = serde_json::from_str(drafts_json)?; + let account = c.account; + let round_id = round_id.to_string(); + let drafts_json = drafts_json.to_string(); + let vote_node_url = vote_node_url.to_string(); + let drafts: Vec = serde_json::from_str(&drafts_json)?; let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; let hotkey = voting::voting_hotkey_load( &mut connection, voting::voting_network(&c.network())?, ) .await?; + let witness = + voting::vote_van_witness(c.get_pool()?, &wallet_id, &round_id, bundle_index, &vote_node_url) + .await?; - let witness = voting::vote_van_witness( - c.get_pool()?, - &wallet_id, - round_id, - bundle_index, - vote_node_url, - ) - .await?; - let commitments = voting::commit_votes( + let stages = VoteCommitStageBridge::new(move |s| { + let _ = sink.add(s.into()); + }); + let commitments = voting::commit_votes_with_progress( c.get_pool()?, &wallet_id, - round_id, + &round_id, bundle_index, &drafts, &witness, &hotkey, + &stages, ) .await?; Ok(commitments.into()) } -/// Returns the chain-ready vote submission and helper-share payloads for one -/// committed vote. +/// Reconstructs the chain-ready wire JSON for a committed vote. #[cfg_attr(feature = "flutter", frb)] -pub async fn voting_payloads( +pub async fn voting_vote_wire_json( round_id: &str, bundle_index: u32, proposal_id: u32, c: &Coin, -) -> Result { +) -> Result { + let account = c.account; + let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; - let (submission, share_payloads) = voting::vote_payloads( + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + voting::vote_wire_json( c.get_pool()?, &wallet_id, - round_id, + &round_id, bundle_index, proposal_id, ) - .await?; - Ok(VotingVotePayloads { - submission: submission.into(), - share_payloads: share_payloads.iter().map(Into::into).collect(), - }) + .await } -/// Records successful vote-chain and helper-share submissions for one vote. +/// Atomically records a cast-vote transaction hash with idempotency checks, so +/// a restart between broadcast and confirmation resumes via `PollVote`. #[cfg_attr(feature = "flutter", frb)] -pub async fn voting_record_execution( +pub async fn voting_mark_vote_submitted( round_id: &str, bundle_index: u32, proposal_id: u32, - vote_tx_hash: &str, - vc_tree_position: u64, - share_deliveries_json: &str, + tx_hash: &str, c: &Coin, ) -> Result<()> { - let share_deliveries: Vec = serde_json::from_str(share_deliveries_json)?; - let shares: Vec<(u32, Vec, u64, bool)> = share_deliveries + let account = c.account; + let round_id = round_id.to_string(); + let tx_hash = tx_hash.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + db.mark_vote_submitted(&round_id, bundle_index, proposal_id, &tx_hash) + .await?; + Ok(()) +} + +// --------------------------------------------------------------------------- +// Share flow +// --------------------------------------------------------------------------- + +/// Records a helper-share submission (derives the nullifier from recovery +/// state). +#[cfg_attr(feature = "flutter", frb)] +#[allow(clippy::too_many_arguments)] +pub async fn voting_share_record( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + share_index: u32, + sent_to_urls: Vec, + submit_at: u64, + c: &Coin, +) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + zcash_voting::share::record( + &db, + &round_id, + bundle_index, + proposal_id, + share_index, + &sent_to_urls, + submit_at, + ) + .await?; + Ok(()) +} + +/// Lists unconfirmed helper-share records for a round. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_unconfirmed( + round_id: &str, + c: &Coin, +) -> Result> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + Ok(zcash_voting::share::unconfirmed(&db, &round_id) + .await? .into_iter() - .map(|d| (d.share_index, d.sent_to_urls, d.submit_at, d.confirmed)) - .collect(); + .map(Into::into) + .collect()) +} + +/// Marks one helper-share record confirmed. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_confirm( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + share_index: u32, + c: &Coin, +) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; - voting::record_vote_execution( - c.get_pool()?, - &wallet_id, - round_id, + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + zcash_voting::share::confirm(&db, &round_id, bundle_index, proposal_id, share_index).await?; + Ok(()) +} + +/// Adds helper URLs to an existing share record after resubmission. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_add_servers( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + share_index: u32, + new_urls: Vec, + c: &Coin, +) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + zcash_voting::share::add_sent_servers( + &db, + &round_id, bundle_index, proposal_id, - vote_tx_hash, - vc_tree_position, - &shares, + share_index, + &new_urls, ) - .await + .await?; + Ok(()) } -/// Records a confirmed cast-vote transaction. +/// Reconstructs one helper-share payload as helper wire JSON from the +/// persisted commitment bundle. #[cfg_attr(feature = "flutter", frb)] -pub async fn voting_confirm( +pub async fn voting_share_wire_json( round_id: &str, bundle_index: u32, proposal_id: u32, - tx_hash: &str, - events_json: &str, + share_index: u32, + vc_tree_position: Option, + submit_at: u64, c: &Coin, -) -> Result { - let events: Vec = serde_json::from_str(events_json)?; +) -> Result { + let account = c.account; + let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; - let confirmation = voting::confirm_vote( + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + voting::share_wire_json( c.get_pool()?, &wallet_id, - round_id, + &round_id, bundle_index, proposal_id, - tx_hash, - &events, + share_index, + vc_tree_position, + submit_at, + ) + .await +} + +/// Best-effort pre-sync of the vote commitment tree for a round, returning +/// the latest synced tree height. Requires the round to exist locally (it is +/// created by the first prepare); callers may ignore failures. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_sync_tree( + round_id: &str, + vote_node_url: &str, + c: &Coin, +) -> Result { + let account = c.account; + let round_id = round_id.to_string(); + let vote_node_url = vote_node_url.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + Ok(zcash_voting::precompute::sync_vote_tree(&db, &round_id, &vote_node_url).await?) +} + +/// Computes the share tracking plan for a round: summary counts, next poll +/// delay, last-moment flag, and freshly planned submissions (with local +/// entropy) for the unconfirmed shares. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_plan( + round_id: &str, + now: u64, + ceremony_start: u64, + vote_end: Option, + server_urls: Vec, + single_share: bool, + c: &Coin, +) -> Result { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let shares = zcash_voting::share::unconfirmed(&db, &round_id).await?; + + let policy = ShareTimingPolicy::default(); + let summary = zcash_voting::share_policy::summarize_share_tracking( + &shares, + now, + vote_end, + policy, + ); + let next_tracking_delay_secs = + zcash_voting::share_policy::next_tracking_delay_seconds(&shares, now, policy); + let last_moment = vote_end.is_some_and(|vote_end| { + zcash_voting::share_policy::is_last_moment(now, ceremony_start, vote_end) + }); + + let submissions = match vote_end { + Some(vote_end) if !shares.is_empty() => { + let mut submit_at_random_bytes = vec![0u8; 512]; + let mut server_random_bytes = vec![0u8; 512]; + OsRng.fill_bytes(&mut submit_at_random_bytes); + OsRng.fill_bytes(&mut server_random_bytes); + zcash_voting::share_policy::plan_share_submissions( + shares.len(), + &server_urls, + now, + vote_end, + zcash_voting::share_policy::last_moment_buffer_seconds(ceremony_start, vote_end), + single_share, + &submit_at_random_bytes, + &server_random_bytes, + )? + .into_iter() + .map(|p| VotingSharePlanItem { + submit_at: p.submit_at, + target_count: p.target_count, + target_servers: p.target_servers, + }) + .collect() + } + _ => Vec::new(), + }; + + Ok(VotingSharePlan { + summary: summary.into(), + next_tracking_delay_secs, + last_moment, + submissions, + }) +} + +// --------------------------------------------------------------------------- +// Config resolution +// --------------------------------------------------------------------------- + +/// Resolves and authenticates the voting config for a source URL. +/// +/// The wallet owns transport: it fetches the static bytes, learns the dynamic +/// URL, fetches the dynamic bytes, then Rust authenticates both and classifies +/// the config switch against the previously resolved summary. The result is +/// cached in the props table so [`voting_config_cached`] can serve as a +/// last-good fallback. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_config_resolve(source: &str, c: &Coin) -> Result { + let source = source.to_string(); + let proxy = votechain_proxy(c); + let mut connection = c.get_connection().await?; + + let static_bytes = crate::net::votechain::fetch_bytes(&source, &proxy).await?; + let resolved_static = + zcash_voting::config::resolve_static_voting_config(&source, &static_bytes)?; + let dynamic_bytes = crate::net::votechain::fetch_bytes( + &resolved_static.dynamic_config_url, + &proxy, + ) + .await?; + let resolved = zcash_voting::config::resolve_dynamic_voting_config( + resolved_static, + &dynamic_bytes, + zcash_voting::config::ResolveVotingConfigOptions::default(), + )?; + + let previous = crate::db::get_prop( + &mut connection, + &format!("voting_config_prev:{source}"), + ) + .await? + .map(|json| { + serde_json::from_str::(&json) + .map_err(anyhow::Error::from) + }) + .transpose()?; + let decision = zcash_voting::config::decide_config_switch( + previous.clone(), + zcash_voting::config::ResolvedVotingConfigSummary::from(&resolved), + ); + + let config = VotingConfig::from_resolved(source.clone(), &resolved, decision.kind); + let fork_json = serde_json::to_string(&resolved)?; + crate::db::put_prop(&mut connection, &format!("voting_config:{source}"), &fork_json) + .await?; + let mirror_json = serde_json::to_string(&config)?; + crate::db::put_prop( + &mut connection, + &format!("voting_config_mirror:{source}"), + &mirror_json, + ) + .await?; + let prev_json = serde_json::to_string( + &zcash_voting::config::ResolvedVotingConfigSummary::from(&resolved), + )?; + crate::db::put_prop( + &mut connection, + &format!("voting_config_prev:{source}"), + &prev_json, + ) + .await?; + Ok(config) +} + +/// Returns the last cached resolved config for a source URL, if any. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_config_cached(source: &str, c: &Coin) -> Result> { + let source = source.to_string(); + let mut connection = c.get_connection().await?; + let Some(json) = + crate::db::get_prop(&mut connection, &format!("voting_config_mirror:{source}")).await? + else { + return Ok(None); + }; + Ok(Some(serde_json::from_str(&json)?)) +} + +/// Builds the round params JSON for `delegation_prepare` from the cached +/// authenticated config plus chain-reported snapshot fields (`ea_pk` is +/// pinned to the authenticated config, so a stale endpoint cannot steer +/// voting to the wrong authority or roots). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_round_params_json( + source: &str, + round_id: &str, + snapshot_height: u64, + nc_root: Vec, + nullifier_imt_root: Vec, + c: &Coin, +) -> Result { + let source = source.to_string(); + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let json = crate::db::get_prop(&mut connection, &format!("voting_config:{source}")) + .await? + .ok_or_else(|| anyhow!("no cached voting config for source {source}; resolve it first"))?; + let config: zcash_voting::config::ResolvedVotingConfig = serde_json::from_str(&json)?; + let params = config.trusted_voting_round_params( + round_id, + snapshot_height, + nc_root, + nullifier_imt_root, + )?; + Ok(serde_json::to_string(¶ms)?) +} + +/// Clears the cached resolved configs (all sources). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_config_clear_cache(c: &Coin) -> Result<()> { + let mut connection = c.get_connection().await?; + crate::db::delete_prop_prefix(&mut connection, "voting_config:").await?; + Ok(()) +} + +// --------------------------------------------------------------------------- +// Vote casting flow +// --------------------------------------------------------------------------- + +/// Syncs the vote-authority-note tree and derives this bundle's VAN witness. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_van_witness( + round_id: &str, + bundle_index: u32, + vote_node_url: &str, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let witness = voting::vote_van_witness( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + vote_node_url, + ) + .await?; + Ok(witness.into()) +} + +/// Commits a batch of vote drafts for one bundle (hotkey-signed). +/// +/// Chains the VAN witness derivation internally, so this may be called right +/// after `voting_van_witness` or standalone. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_commit( + round_id: &str, + bundle_index: u32, + drafts_json: &str, + vote_node_url: &str, + c: &Coin, +) -> Result { + let drafts: Vec = serde_json::from_str(drafts_json)?; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let hotkey = voting::voting_hotkey_load( + &mut connection, + voting::voting_network(&c.network())?, + ) + .await?; + + let witness = voting::vote_van_witness( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + vote_node_url, + ) + .await?; + let commitments = voting::commit_votes( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + &drafts, + &witness, + &hotkey, + ) + .await?; + Ok(commitments.into()) +} + +/// Returns the chain-ready vote submission and helper-share payloads for one +/// committed vote. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_payloads( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + c: &Coin, +) -> Result { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let (submission, share_payloads) = voting::vote_payloads( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + ) + .await?; + Ok(VotingVotePayloads { + submission: submission.into(), + share_payloads: share_payloads.iter().map(Into::into).collect(), + }) +} + +/// Records successful vote-chain and helper-share submissions for one vote. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_record_execution( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + vote_tx_hash: &str, + vc_tree_position: u64, + share_deliveries_json: &str, + c: &Coin, +) -> Result<()> { + let share_deliveries: Vec = serde_json::from_str(share_deliveries_json)?; + let shares: Vec<(u32, Vec, u64, bool)> = share_deliveries + .into_iter() + .map(|d| (d.share_index, d.sent_to_urls, d.submit_at, d.confirmed)) + .collect(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + voting::record_vote_execution( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + vote_tx_hash, + vc_tree_position, + &shares, + ) + .await +} + +/// Records a confirmed cast-vote transaction. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_confirm( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + tx_hash: &str, + events_json: &str, + c: &Coin, +) -> Result { + let events: Vec = serde_json::from_str(events_json)?; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let confirmation = voting::confirm_vote( + c.get_pool()?, + &wallet_id, + round_id, + bundle_index, + proposal_id, + tx_hash, + &events, ) .await?; Ok(confirmation.into()) } + +// --------------------------------------------------------------------------- +// Recovery / plan mirrors +// --------------------------------------------------------------------------- + +/// Round row from the voting DB (rounds list). +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingRoundInfo { + pub round_id: String, + pub network: String, + pub snapshot_height: u64, + pub hotkey_address: Option, + pub eligible_weight_zatoshi: Option, + pub bundle_count: u32, + pub created_at: u64, +} + +/// One remaining unit of recovery work for a round. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingNextStep { + pub kind: String, + pub bundle_index: u32, + pub proposal_id: u32, + pub choice: u32, + pub share_index: u32, +} + +/// Durable delegation state for one eligible bundle. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationStatus { + pub bundle_index: u32, + pub phase: String, + pub tx_hash: Option, +} + +/// Display choice for one proposal in a completed round. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingCompletedVoteChoice { + pub proposal_id: u32, + pub choice: Option, +} + +/// Read-only display summary for a locally completed vote. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingCompletedVoteDisplay { + pub choices: Vec, + pub voted_at: Option, +} + +/// Derived resume state for one round. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingRoundPlan { + pub round_id: String, + pub pending_recovery: bool, + pub next_steps: Vec, + pub open_proposals: Vec, + pub all_decided: bool, + pub delegation_statuses: Vec, + pub blocking_recovery: bool, + pub blocking_share_work: bool, + pub hotkey_bound: bool, + pub completed_vote_artifact: bool, + pub completed_for_display: bool, + pub completed_vote_display: Option, + pub needs_draft_setup: bool, + pub primary_action: String, +} + +/// Delegation recovery state for one bundle. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingDelegationRecovery { + pub bundle_index: u32, + pub phase: String, + pub workflow_phase: String, + pub tx_hash: Option, + pub van_leaf_position: Option, +} + +/// Vote recovery state for one vote key. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingVoteRecovery { + pub bundle_index: u32, + pub proposal_id: u32, + pub choice: u32, + pub phase: String, + pub workflow_phase: String, + pub tx_hash: Option, + pub vc_tree_position: Option, + pub has_commitment_bundle: bool, +} + +/// Share recovery state for one delegated share. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingShareWorkflow { + pub bundle_index: u32, + pub proposal_id: u32, + pub share_index: u32, + pub phase: String, +} + +/// A share delegation record from the local DB. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingShareDelegationRecord { + pub round_id: String, + pub bundle_index: u32, + pub proposal_id: u32, + pub share_index: u32, + pub sent_to_urls: Vec, + pub nullifier: Vec, + pub confirmed: bool, + pub submit_at: u64, + pub created_at: u64, +} + +/// Full read-only recovery snapshot for one round. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingRoundRecovery { + pub round_id: String, + pub bundle_count: u32, + pub delegation: Vec, + pub votes: Vec, + pub shares: Vec, + pub share_delegations: Vec, + pub unconfirmed_share_delegations: Vec, +} + +/// The voter's terminal decision for one proposal. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingBallotIntent { + pub proposal_id: u32, + pub skipped: bool, + pub choice: Option, +} + +/// Delegation proof/signing progress event, one-to-one with the fork's +/// `DelegationProgress`. The bookend variants (`SelectingNotes`, +/// `SigningPayload`, `PayloadReady`) are emitted by the host wrapper; the +/// PCZT/proof stages come from the library. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum VotingDelegationProgress { + SelectingNotes, + PcztBuilding, + PcztBuilt, + ProofStarting, + ProofProgress { progress: f64 }, + ProofComplete, + SigningPayload, + PayloadReady, +} + +impl From for VotingDelegationProgress { + fn from(p: DelegationProgress) -> Self { + match p { + DelegationProgress::SelectingNotes => Self::SelectingNotes, + DelegationProgress::PcztBuilding => Self::PcztBuilding, + DelegationProgress::PcztBuilt => Self::PcztBuilt, + DelegationProgress::ProofStarting => Self::ProofStarting, + DelegationProgress::ProofProgress(progress) => Self::ProofProgress { progress }, + DelegationProgress::ProofComplete => Self::ProofComplete, + DelegationProgress::SigningPayload => Self::SigningPayload, + DelegationProgress::PayloadReady => Self::PayloadReady, + _ => Self::PcztBuilding, + } + } +} + +/// Cast-vote commitment stage event, one-to-one with the fork's +/// `VoteCommitStage`. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum VotingVoteCommitStage { + ProofStarting { + proposal_id: u32, + bundle_index: u32, + }, + ProofProgress { + proposal_id: u32, + bundle_index: u32, + progress: f64, + }, + SharePayloadsBuilding { + proposal_id: u32, + bundle_index: u32, + }, + Signing { + proposal_id: u32, + bundle_index: u32, + }, +} + +impl From for VotingVoteCommitStage { + fn from(s: zcash_voting::vote::VoteCommitStage) -> Self { + match s { + zcash_voting::vote::VoteCommitStage::ProofStarting { + proposal_id, + bundle_index, + } => Self::ProofStarting { + proposal_id, + bundle_index, + }, + zcash_voting::vote::VoteCommitStage::ProofProgress { + proposal_id, + bundle_index, + progress, + } => Self::ProofProgress { + proposal_id, + bundle_index, + progress, + }, + zcash_voting::vote::VoteCommitStage::SharePayloadsBuilding { + proposal_id, + bundle_index, + } => Self::SharePayloadsBuilding { + proposal_id, + bundle_index, + }, + zcash_voting::vote::VoteCommitStage::Signing { + proposal_id, + bundle_index, + } => Self::Signing { + proposal_id, + bundle_index, + }, + _ => Self::Signing { + proposal_id: 0, + bundle_index: 0, + }, + } + } +} + +/// Share tracking summary, one-to-one with the fork's `ShareTrackingSummary`. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingShareTrackingSummary { + pub total: u64, + pub confirmed: u64, + pub waiting: u64, + pub ready: u64, + pub overdue: u64, +} + +/// One planned helper-share submission. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingSharePlanItem { + pub submit_at: u64, + pub target_count: u32, + pub target_servers: Vec, +} + +/// The share tracking plan for a round: summary, next poll delay, last-moment +/// flag, and freshly planned submissions for the unconfirmed shares. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingSharePlan { + pub summary: VotingShareTrackingSummary, + pub next_tracking_delay_secs: Option, + pub last_moment: bool, + pub submissions: Vec, +} + +// --------------------------------------------------------------------------- +// Recovery / plan conversions +// --------------------------------------------------------------------------- + +fn fork_network_string(network: VotingNetwork) -> String { + match network { + VotingNetwork::Mainnet => "mainnet".to_string(), + VotingNetwork::Testnet => "testnet".to_string(), + VotingNetwork::Regtest => "regtest".to_string(), + } +} + +impl From for VotingRoundInfo { + fn from(r: ForkRoundInfo) -> Self { + Self { + round_id: r.round_id, + network: fork_network_string(r.network), + snapshot_height: r.snapshot_height, + hotkey_address: r.hotkey_address, + eligible_weight_zatoshi: r.eligible_weight, + bundle_count: r.bundle_count, + created_at: r.created_at, + } + } +} + +impl From for VotingNextStep { + fn from(step: NextStep) -> Self { + let kind = step.kind().to_string(); + let (bundle_index, proposal_id, choice, share_index) = match step { + NextStep::Delegate { bundle_index } => (bundle_index, 0, 0, 0), + NextStep::PollDelegation { bundle_index } => (bundle_index, 0, 0, 0), + NextStep::CastVote { + bundle_index, + proposal_id, + choice, + } => (bundle_index, proposal_id, choice, 0), + NextStep::SubmitVote { + bundle_index, + proposal_id, + } => (bundle_index, proposal_id, 0, 0), + NextStep::PollVote { + bundle_index, + proposal_id, + } => (bundle_index, proposal_id, 0, 0), + NextStep::SubmitShares { + bundle_index, + proposal_id, + share_index, + } => (bundle_index, proposal_id, 0, share_index), + NextStep::ConfirmShare { + bundle_index, + proposal_id, + share_index, + } => (bundle_index, proposal_id, 0, share_index), + _ => (0, 0, 0, 0), + }; + Self { + kind, + bundle_index, + proposal_id, + choice, + share_index, + } + } +} + +impl From for VotingRoundPlan { + fn from(plan: ForkRoundPlan) -> Self { + Self { + round_id: plan.round_id, + pending_recovery: plan.pending_recovery, + next_steps: plan.next_steps.into_iter().map(Into::into).collect(), + open_proposals: plan.open_proposals, + all_decided: plan.all_decided, + delegation_statuses: plan + .delegation_statuses + .into_iter() + .map(|d| VotingDelegationStatus { + bundle_index: d.bundle_index, + phase: d.phase.as_str().to_string(), + tx_hash: d.tx_hash, + }) + .collect(), + blocking_recovery: plan.blocking_recovery, + blocking_share_work: plan.blocking_share_work, + hotkey_bound: plan.hotkey_bound, + completed_vote_artifact: plan.completed_vote_artifact, + completed_for_display: plan.completed_for_display, + completed_vote_display: plan.completed_vote_display.map(|d| VotingCompletedVoteDisplay { + choices: d + .choices + .into_iter() + .map(|c| VotingCompletedVoteChoice { + proposal_id: c.proposal_id, + choice: c.choice, + }) + .collect(), + voted_at: d.voted_at, + }), + needs_draft_setup: plan.needs_draft_setup, + primary_action: plan.primary_action.as_str().to_string(), + } + } +} + +impl From for VotingDelegationRecovery { + fn from(r: ForkDelegationRecovery) -> Self { + Self { + bundle_index: r.bundle_index, + phase: r.phase.as_str().to_string(), + workflow_phase: r.workflow_phase().as_str().to_string(), + tx_hash: r.tx_hash, + van_leaf_position: r.van_leaf_position, + } + } +} + +impl From for VotingVoteRecovery { + fn from(r: ForkVoteRecovery) -> Self { + Self { + bundle_index: r.bundle_index, + proposal_id: r.proposal_id, + choice: r.choice, + phase: r.phase.as_str().to_string(), + workflow_phase: r.workflow_phase().as_str().to_string(), + tx_hash: r.tx_hash, + vc_tree_position: r.vc_tree_position, + has_commitment_bundle: r.has_commitment_bundle, + } + } +} + +impl From for VotingShareWorkflow { + fn from(s: ForkShareWorkflow) -> Self { + Self { + bundle_index: s.bundle_index, + proposal_id: s.proposal_id, + share_index: s.share_index, + phase: s.phase.as_str().to_string(), + } + } +} + +impl From for VotingShareDelegationRecord { + fn from(r: ForkShareDelegationRecord) -> Self { + Self { + round_id: r.round_id, + bundle_index: r.bundle_index, + proposal_id: r.proposal_id, + share_index: r.share_index, + sent_to_urls: r.sent_to_urls, + nullifier: r.nullifier, + confirmed: r.confirmed, + submit_at: r.submit_at, + created_at: r.created_at, + } + } +} + +impl From for VotingRoundRecovery { + fn from(s: ForkRoundRecovery) -> Self { + Self { + round_id: s.round_id, + bundle_count: s.bundle_count, + delegation: s.delegation.into_iter().map(Into::into).collect(), + votes: s.votes.into_iter().map(Into::into).collect(), + shares: s.shares.into_iter().map(Into::into).collect(), + share_delegations: s.share_delegations.into_iter().map(Into::into).collect(), + unconfirmed_share_delegations: s + .unconfirmed_share_delegations + .into_iter() + .map(Into::into) + .collect(), + } + } +} + +impl From<(u32, Decision)> for VotingBallotIntent { + fn from((proposal_id, decision): (u32, Decision)) -> Self { + match decision { + Decision::Choice(choice) => Self { + proposal_id, + skipped: false, + choice: Some(choice), + }, + Decision::Skipped => Self { + proposal_id, + skipped: true, + choice: None, + }, + } + } +} + +impl From for VotingShareTrackingSummary { + fn from(s: zcash_voting::share_policy::ShareTrackingSummary) -> Self { + Self { + total: s.total, + confirmed: s.confirmed, + waiting: s.waiting, + ready: s.ready, + overdue: s.overdue, + } + } +} + +/// Endpoint advertised by a voting service config. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingServiceEndpoint { + pub url: String, + pub label: String, +} + +/// Round authenticated by the dynamic voting config. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingConfigRound { + pub round_id: String, + pub ea_pk: Vec, +} + +/// Authenticated dynamic voting config, ready for wallet use. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingConfig { + pub source: String, + pub source_fingerprint: String, + pub trusted_key_fingerprint: String, + pub switch_kind: String, + pub vote_servers: Vec, + pub pir_servers: Vec, + pub pir_layout: Option, + pub rounds: Vec, +} + +fn config_switch_kind_string(kind: zcash_voting::config::ConfigSwitchKind) -> String { + match kind { + zcash_voting::config::ConfigSwitchKind::Unchanged => "unchanged".to_string(), + zcash_voting::config::ConfigSwitchKind::InitialLoad => "initial_load".to_string(), + zcash_voting::config::ConfigSwitchKind::SameChainServiceUpdate => { + "same_chain_service_update".to_string() + } + zcash_voting::config::ConfigSwitchKind::NewChainOrRound => "new_chain_or_round".to_string(), + zcash_voting::config::ConfigSwitchKind::ProtocolChanged => "protocol_changed".to_string(), + _ => "unchanged".to_string(), + } +} + +impl VotingConfig { + fn from_resolved( + source: String, + resolved: &zcash_voting::config::ResolvedVotingConfig, + switch_kind: zcash_voting::config::ConfigSwitchKind, + ) -> Self { + Self { + source, + source_fingerprint: resolved.source_fingerprint.clone(), + trusted_key_fingerprint: resolved.trusted_key_fingerprint.clone(), + switch_kind: config_switch_kind_string(switch_kind), + vote_servers: resolved + .vote_servers + .iter() + .map(|e| VotingServiceEndpoint { + url: e.url.clone(), + label: e.label.clone(), + }) + .collect(), + pir_servers: resolved + .pir_endpoints + .iter() + .map(|e| VotingServiceEndpoint { + url: e.url.clone(), + label: e.label.clone(), + }) + .collect(), + pir_layout: if resolved.pir_layout == zcash_voting::config::PirLayout::UNKNOWN { + None + } else { + Some(resolved.pir_layout.into()) + }, + rounds: resolved + .authenticated_rounds + .iter() + .map(|r| VotingConfigRound { + round_id: r.round_id.clone(), + ea_pk: r.ea_pk.clone(), + }) + .collect(), + } + } +} + +// --------------------------------------------------------------------------- +// Recovery / plan reads +// --------------------------------------------------------------------------- + +/// Lists rounds persisted in the voting DB for the current wallet. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_rounds(c: &Coin) -> Result> { + let account = c.account; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let rounds = db.rounds().await?; + Ok(rounds.into_iter().map(Into::into).collect()) +} + +/// Returns the derived resume plan for a round (the ordered work that remains +/// after any restart; empty `next_steps` with `primary_action == "done"` means +/// the round is complete for this wallet). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_plan(round_id: &str, proposal_ids: Vec, c: &Coin) -> Result { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let plan = zcash_voting::session::resume_plan(&db, &round_id, &proposal_ids).await?; + Ok(plan.into()) +} + +/// Returns the full read-only recovery snapshot for a round. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_recovery(round_id: &str, c: &Coin) -> Result { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let snapshot = zcash_voting::recovery::round_snapshot(&db, &round_id).await?; + Ok(snapshot.into()) +} + +/// Clears unconfirmed recovery artifacts for a round. Ballot intents, recorded +/// confirmations, and imported delegation capabilities are preserved. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_recovery_clear(round_id: &str, c: &Coin) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + zcash_voting::recovery::clear(&db, &round_id).await?; + Ok(()) +} + +/// Returns the persisted ballot intents for a round, sorted by proposal id. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_ballot_intents(round_id: &str, c: &Coin) -> Result> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let intents = db.ballot_intents(&round_id).await?; + Ok(intents.into_iter().map(Into::into).collect()) +} + +// --------------------------------------------------------------------------- +// Vote-chain HTTP +// --------------------------------------------------------------------------- + +/// Generic vote-chain HTTP response: status code + raw JSON body. +/// +/// 404 means "not found" (e.g. a transaction that is not confirmed yet) and +/// 422 means a deterministic chain rejection whose body is a `VotingTxResult`. +/// Only network failures surface as `Err`. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingChainResponse { + pub status_code: u16, + pub body: String, +} + +/// Voting traffic honors the external-proxy setting (transport 3) only; it is +/// never routed through the Tor/Nym transports in v1. +fn votechain_proxy(c: &Coin) -> String { + if c.transport == 3 { + c.proxy.clone() + } else { + String::new() + } +} + +/// Lists rounds from the vote server (`{ "rounds": [...] }`). +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_list_rounds(base_url: &str, c: &Coin) -> Result { + let base_url = base_url.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = crate::net::votechain::list_rounds(&base_url, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Fetches one round's status (`{ "round": ... }` envelope). +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_round_status( + base_url: &str, + round_id: &str, + c: &Coin, +) -> Result { + let base_url = base_url.to_string(); + let round_id = round_id.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::round_status(&base_url, &round_id, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Fetches the round tally envelope. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_round_tally( + base_url: &str, + round_id: &str, + c: &Coin, +) -> Result { + let base_url = base_url.to_string(); + let round_id = round_id.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::round_tally(&base_url, &round_id, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Broadcasts a delegation transaction to the vote chain. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_submit_delegation( + base_url: &str, + submission_json: &str, + c: &Coin, +) -> Result { + let base_url = base_url.to_string(); + let submission_json = submission_json.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::submit_delegation(&base_url, &submission_json, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Broadcasts a vote commitment transaction to the vote chain. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_submit_vote( + base_url: &str, + submission_json: &str, + c: &Coin, +) -> Result { + let base_url = base_url.to_string(); + let submission_json = submission_json.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::submit_vote_commitment(&base_url, &submission_json, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Fetches the on-chain confirmation for a transaction; 404 = not confirmed. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_tx_confirmation( + base_url: &str, + tx_hash: &str, + c: &Coin, +) -> Result { + let base_url = base_url.to_string(); + let tx_hash = tx_hash.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::tx_confirmation(&base_url, &tx_hash, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Posts one encrypted share to a helper server. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_submit_share( + server_url: &str, + payload_json: &str, + c: &Coin, +) -> Result { + let server_url = server_url.to_string(); + let payload_json = payload_json.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::submit_share(&server_url, &payload_json, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Resends a previously generated share to a helper server (same endpoint as +/// the initial submission). +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_resubmit_share( + server_url: &str, + payload_json: &str, + c: &Coin, +) -> Result { + let server_url = server_url.to_string(); + let payload_json = payload_json.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::submit_share(&server_url, &payload_json, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} + +/// Checks whether a helper has confirmed a share identified by its nullifier. +#[cfg_attr(feature = "flutter", frb)] +pub async fn votechain_share_status( + server_url: &str, + round_id: &str, + share_id: &str, + c: &Coin, +) -> Result { + let server_url = server_url.to_string(); + let round_id = round_id.to_string(); + let share_id = share_id.to_string(); + let proxy = votechain_proxy(c); + let (status_code, body) = + crate::net::votechain::share_status(&server_url, &round_id, &share_id, &proxy).await?; + Ok(VotingChainResponse { status_code, body }) +} diff --git a/rust/src/db.rs b/rust/src/db.rs index 1c3184728..a072d39e9 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -742,6 +742,14 @@ pub async fn get_prop(connection: &mut SqliteConnection, key: &str) -> Result Result<()> { + sqlx::query("DELETE FROM props WHERE key LIKE ?") + .bind(format!("{prefix}%")) + .execute(&mut *connection) + .await?; + Ok(()) +} + pub async fn store_account_metadata( connection: &mut SqliteConnection, name: &str, diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 89129b65b..66fbae43f 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 88494436; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1766202353; // Section: executor @@ -1653,6 +1653,61 @@ fn wire__crate__api__raptor__decode_impl( }, ) } +fn wire__crate__api__voting__delegation_build_submission_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_build_submission", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_sink = >::sse_decode(&mut deserializer); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_pczt_bytes = >::sse_decode(&mut deserializer); + let api_pir_layout = + >::sse_decode(&mut deserializer); + let api_pir_server_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_build_submission( + api_sink, + &api_round_id, + api_bundle_index, + api_pczt_bytes, + api_pir_layout, + &api_pir_server_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__delegation_confirm_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -1700,6 +1755,51 @@ fn wire__crate__api__voting__delegation_confirm_impl( }, ) } +fn wire__crate__api__voting__delegation_mark_submitted_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_mark_submitted", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_mark_submitted( + &api_round_id, + api_bundle_index, + &api_tx_hash, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__delegation_prepare_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -1751,6 +1851,53 @@ fn wire__crate__api__voting__delegation_prepare_impl( }, ) } +fn wire__crate__api__voting__delegation_prepare_resume_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_prepare_resume", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_max_real_notes_per_bundle = >::sse_decode(&mut deserializer); + let api_lightwalletd_url = >::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_prepare_resume( + &api_round_id, + api_bundle_index, + api_max_real_notes_per_bundle, + api_lightwalletd_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__delegation_setup_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -1844,6 +1991,92 @@ fn wire__crate__api__voting__delegation_sign_and_submit_impl( }, ) } +fn wire__crate__api__voting__delegation_tx_hash_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_tx_hash", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_tx_hash( + &api_round_id, + api_bundle_index, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__delegation_wire_json_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "delegation_wire_json", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::delegation_wire_json( + &api_round_id, + api_bundle_index, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__account__delete_account_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -7056,7 +7289,7 @@ fn wire__crate__api__openalias__validate_zcash_address_impl( }, ) } -fn wire__crate__api__voting__voting_commit_impl( +fn wire__crate__api__voting__votechain_list_rounds_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7064,7 +7297,7 @@ fn wire__crate__api__voting__voting_commit_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_commit", + debug_name: "votechain_list_rounds", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7078,23 +7311,15 @@ fn wire__crate__api__voting__voting_commit_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_round_id = ::sse_decode(&mut deserializer); - let api_bundle_index = ::sse_decode(&mut deserializer); - let api_drafts_json = ::sse_decode(&mut deserializer); - let api_vote_node_url = ::sse_decode(&mut deserializer); + let api_base_url = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_commit( - &api_round_id, - api_bundle_index, - &api_drafts_json, - &api_vote_node_url, - &api_c, - ) - .await?; + let output_ok = + crate::api::voting::votechain_list_rounds(&api_base_url, &api_c) + .await?; Ok(output_ok) })() .await, @@ -7103,7 +7328,7 @@ fn wire__crate__api__voting__voting_commit_impl( }, ) } -fn wire__crate__api__voting__voting_confirm_impl( +fn wire__crate__api__voting__votechain_resubmit_share_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7111,7 +7336,7 @@ fn wire__crate__api__voting__voting_confirm_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_confirm", + debug_name: "votechain_resubmit_share", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7125,22 +7350,16 @@ fn wire__crate__api__voting__voting_confirm_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_round_id = ::sse_decode(&mut deserializer); - let api_bundle_index = ::sse_decode(&mut deserializer); - let api_proposal_id = ::sse_decode(&mut deserializer); - let api_tx_hash = ::sse_decode(&mut deserializer); - let api_events_json = ::sse_decode(&mut deserializer); + let api_server_url = ::sse_decode(&mut deserializer); + let api_payload_json = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_confirm( - &api_round_id, - api_bundle_index, - api_proposal_id, - &api_tx_hash, - &api_events_json, + let output_ok = crate::api::voting::votechain_resubmit_share( + &api_server_url, + &api_payload_json, &api_c, ) .await?; @@ -7152,7 +7371,7 @@ fn wire__crate__api__voting__voting_confirm_impl( }, ) } -fn wire__crate__api__voting__voting_hotkey_create_impl( +fn wire__crate__api__voting__votechain_round_status_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7160,7 +7379,7 @@ fn wire__crate__api__voting__voting_hotkey_create_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_hotkey_create", + debug_name: "votechain_round_status", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7174,12 +7393,19 @@ fn wire__crate__api__voting__voting_hotkey_create_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_base_url = ::sse_decode(&mut deserializer); + let api_round_id = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_hotkey_create(&api_c).await?; + let output_ok = crate::api::voting::votechain_round_status( + &api_base_url, + &api_round_id, + &api_c, + ) + .await?; Ok(output_ok) })() .await, @@ -7188,7 +7414,7 @@ fn wire__crate__api__voting__voting_hotkey_create_impl( }, ) } -fn wire__crate__api__voting__voting_hotkey_get_impl( +fn wire__crate__api__voting__votechain_round_tally_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7196,7 +7422,7 @@ fn wire__crate__api__voting__voting_hotkey_get_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_hotkey_get", + debug_name: "votechain_round_tally", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7210,13 +7436,20 @@ fn wire__crate__api__voting__voting_hotkey_get_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_base_url = ::sse_decode(&mut deserializer); + let api_round_id = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_hotkey_get(&api_c).await?; - Ok(output_ok) + let output_ok = crate::api::voting::votechain_round_tally( + &api_base_url, + &api_round_id, + &api_c, + ) + .await?; + Ok(output_ok) })() .await, ) @@ -7224,7 +7457,7 @@ fn wire__crate__api__voting__voting_hotkey_get_impl( }, ) } -fn wire__crate__api__voting__voting_payloads_impl( +fn wire__crate__api__voting__votechain_share_status_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7232,7 +7465,7 @@ fn wire__crate__api__voting__voting_payloads_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_payloads", + debug_name: "votechain_share_status", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7246,18 +7479,18 @@ fn wire__crate__api__voting__voting_payloads_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_server_url = ::sse_decode(&mut deserializer); let api_round_id = ::sse_decode(&mut deserializer); - let api_bundle_index = ::sse_decode(&mut deserializer); - let api_proposal_id = ::sse_decode(&mut deserializer); + let api_share_id = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_payloads( + let output_ok = crate::api::voting::votechain_share_status( + &api_server_url, &api_round_id, - api_bundle_index, - api_proposal_id, + &api_share_id, &api_c, ) .await?; @@ -7269,7 +7502,7 @@ fn wire__crate__api__voting__voting_payloads_impl( }, ) } -fn wire__crate__api__voting__voting_record_execution_impl( +fn wire__crate__api__voting__votechain_submit_delegation_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7277,7 +7510,218 @@ fn wire__crate__api__voting__voting_record_execution_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_record_execution", + debug_name: "votechain_submit_delegation", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_base_url = ::sse_decode(&mut deserializer); + let api_submission_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::votechain_submit_delegation( + &api_base_url, + &api_submission_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__votechain_submit_share_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "votechain_submit_share", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_server_url = ::sse_decode(&mut deserializer); + let api_payload_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::votechain_submit_share( + &api_server_url, + &api_payload_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__votechain_submit_vote_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "votechain_submit_vote", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_base_url = ::sse_decode(&mut deserializer); + let api_submission_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::votechain_submit_vote( + &api_base_url, + &api_submission_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__votechain_tx_confirmation_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "votechain_tx_confirmation", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_base_url = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::votechain_tx_confirmation( + &api_base_url, + &api_tx_hash, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_ballot_intents_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_ballot_intents", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_ballot_intents(&api_round_id, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_commit_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_commit", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7293,22 +7737,18 @@ fn wire__crate__api__voting__voting_record_execution_impl( flutter_rust_bridge::for_generated::SseDeserializer::new(message); let api_round_id = ::sse_decode(&mut deserializer); let api_bundle_index = ::sse_decode(&mut deserializer); - let api_proposal_id = ::sse_decode(&mut deserializer); - let api_vote_tx_hash = ::sse_decode(&mut deserializer); - let api_vc_tree_position = ::sse_decode(&mut deserializer); - let api_share_deliveries_json = ::sse_decode(&mut deserializer); + let api_drafts_json = ::sse_decode(&mut deserializer); + let api_vote_node_url = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_record_execution( + let output_ok = crate::api::voting::voting_commit( &api_round_id, api_bundle_index, - api_proposal_id, - &api_vote_tx_hash, - api_vc_tree_position, - &api_share_deliveries_json, + &api_drafts_json, + &api_vote_node_url, &api_c, ) .await?; @@ -7320,7 +7760,7 @@ fn wire__crate__api__voting__voting_record_execution_impl( }, ) } -fn wire__crate__api__voting__voting_van_witness_impl( +fn wire__crate__api__voting__voting_commit_with_progress_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -7328,7 +7768,7 @@ fn wire__crate__api__voting__voting_van_witness_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "voting_van_witness", + debug_name: "voting_commit_with_progress", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -7342,17 +7782,24 @@ fn wire__crate__api__voting__voting_van_witness_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_sink = >::sse_decode(&mut deserializer); let api_round_id = ::sse_decode(&mut deserializer); let api_bundle_index = ::sse_decode(&mut deserializer); + let api_drafts_json = ::sse_decode(&mut deserializer); let api_vote_node_url = ::sse_decode(&mut deserializer); let api_c = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::voting::voting_van_witness( + let output_ok = crate::api::voting::voting_commit_with_progress( + api_sink, &api_round_id, api_bundle_index, + &api_drafts_json, &api_vote_node_url, &api_c, ) @@ -7365,41 +7812,1174 @@ fn wire__crate__api__voting__voting_van_witness_impl( }, ) } - -// Section: related_funcs - -fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dart_opaque: flutter_rust_bridge::DartOpaque, -) -> impl Fn( - Vec, -) -> flutter_rust_bridge::DartFnFuture< - std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error>, -> { - use flutter_rust_bridge::IntoDart; - - async fn body( - dart_opaque: flutter_rust_bridge::DartOpaque, - arg0: Vec, - ) -> std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error> { - let args = vec![arg0.into_into_dart().into_dart()]; - let message = FLUTTER_RUST_BRIDGE_HANDLER - .dart_fn_invoke(dart_opaque, args) - .await; - - let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let action = deserializer.cursor.read_u8().unwrap(); - let ans = match action { - 0 => std::result::Result::Ok(<()>::sse_decode(&mut deserializer)), - 1 => std::result::Result::Err( - ::sse_decode(&mut deserializer), - ), - _ => unreachable!(), - }; - deserializer.end(); - ans - } - - move |arg0: Vec| { +fn wire__crate__api__voting__voting_config_cached_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_config_cached", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_source = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_config_cached(&api_source, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_config_clear_cache_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_config_clear_cache", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_config_clear_cache(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_config_resolve_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_config_resolve", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_source = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_config_resolve(&api_source, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_confirm_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_confirm", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_events_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_confirm( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_tx_hash, + &api_events_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_drafts_load_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_drafts_load", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_drafts_load(&api_round_id, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_drafts_save_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_drafts_save", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_drafts_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_drafts_save( + &api_round_id, + &api_drafts_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_hotkey_create_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_hotkey_create", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_hotkey_create(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_hotkey_get_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_hotkey_get", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_hotkey_get(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_mark_vote_submitted_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_mark_vote_submitted", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_tx_hash = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_mark_vote_submitted( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_tx_hash, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_payloads_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_payloads", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_payloads( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_plan_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_plan", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_proposal_ids = >::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_plan( + &api_round_id, + api_proposal_ids, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_record_execution_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_record_execution", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_vote_tx_hash = ::sse_decode(&mut deserializer); + let api_vc_tree_position = ::sse_decode(&mut deserializer); + let api_share_deliveries_json = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_record_execution( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_vote_tx_hash, + api_vc_tree_position, + &api_share_deliveries_json, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_recovery_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_recovery", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_recovery(&api_round_id, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_recovery_clear_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_recovery_clear", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_recovery_clear(&api_round_id, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_round_params_json_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_round_params_json", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_source = ::sse_decode(&mut deserializer); + let api_round_id = ::sse_decode(&mut deserializer); + let api_snapshot_height = ::sse_decode(&mut deserializer); + let api_nc_root = >::sse_decode(&mut deserializer); + let api_nullifier_imt_root = >::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_round_params_json( + &api_source, + &api_round_id, + api_snapshot_height, + api_nc_root, + api_nullifier_imt_root, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_rounds_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_rounds", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_rounds(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_set_ballot_intent_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_set_ballot_intent", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_skipped = ::sse_decode(&mut deserializer); + let api_choice = ::sse_decode(&mut deserializer); + let api_num_options = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_set_ballot_intent( + &api_round_id, + api_proposal_id, + api_skipped, + api_choice, + api_num_options, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_add_servers_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_add_servers", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_share_index = ::sse_decode(&mut deserializer); + let api_new_urls = >::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_add_servers( + &api_round_id, + api_bundle_index, + api_proposal_id, + api_share_index, + api_new_urls, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_confirm_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_confirm", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_share_index = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_confirm( + &api_round_id, + api_bundle_index, + api_proposal_id, + api_share_index, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_plan_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_plan", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_now = ::sse_decode(&mut deserializer); + let api_ceremony_start = ::sse_decode(&mut deserializer); + let api_vote_end = >::sse_decode(&mut deserializer); + let api_server_urls = >::sse_decode(&mut deserializer); + let api_single_share = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_plan( + &api_round_id, + api_now, + api_ceremony_start, + api_vote_end, + api_server_urls, + api_single_share, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_record_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_record", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_share_index = ::sse_decode(&mut deserializer); + let api_sent_to_urls = >::sse_decode(&mut deserializer); + let api_submit_at = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_record( + &api_round_id, + api_bundle_index, + api_proposal_id, + api_share_index, + api_sent_to_urls, + api_submit_at, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_unconfirmed_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_unconfirmed", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_share_unconfirmed(&api_round_id, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_share_wire_json_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_wire_json", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_share_index = ::sse_decode(&mut deserializer); + let api_vc_tree_position = >::sse_decode(&mut deserializer); + let api_submit_at = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_wire_json( + &api_round_id, + api_bundle_index, + api_proposal_id, + api_share_index, + api_vc_tree_position, + api_submit_at, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_sync_tree_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_sync_tree", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_vote_node_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_sync_tree( + &api_round_id, + &api_vote_node_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_van_witness_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_van_witness", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_vote_node_url = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_van_witness( + &api_round_id, + api_bundle_index, + &api_vote_node_url, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_vote_wire_json_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_vote_wire_json", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_bundle_index = ::sse_decode(&mut deserializer); + let api_proposal_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_vote_wire_json( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} + +// Section: related_funcs + +fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn( + Vec, +) -> flutter_rust_bridge::DartFnFuture< + std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error>, +> { + use flutter_rust_bridge::IntoDart; + + async fn body( + dart_opaque: flutter_rust_bridge::DartOpaque, + arg0: Vec, + ) -> std::result::Result<(), flutter_rust_bridge::for_generated::anyhow::Error> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(<()>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + ::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + ans + } + + move |arg0: Vec| { flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( dart_opaque.clone(), arg0, @@ -7554,10 +9134,30 @@ impl SseDecode } impl SseDecode - for StreamSink< - crate::api::migrate::MigrationStatus, - flutter_rust_bridge::for_generated::SseCodec, - > + for StreamSink< + crate::api::migrate::MigrationStatus, + flutter_rust_bridge::for_generated::SseCodec, + > +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return StreamSink::deserialize(inner); + } +} + +impl SseDecode + for StreamSink +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return StreamSink::deserialize(inner); + } +} + +impl SseDecode + for StreamSink { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -7567,7 +9167,7 @@ impl SseDecode } impl SseDecode - for StreamSink + for StreamSink { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -7577,7 +9177,10 @@ impl SseDecode } impl SseDecode - for StreamSink + for StreamSink< + crate::api::voting::VotingDelegationProgress, + flutter_rust_bridge::for_generated::SseCodec, + > { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -7587,7 +9190,10 @@ impl SseDecode } impl SseDecode - for StreamSink + for StreamSink< + crate::api::voting::VotingVoteCommitStage, + flutter_rust_bridge::for_generated::SseCodec, + > { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8291,6 +9897,76 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8305,6 +9981,60 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8319,6 +10049,34 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8331,6 +10089,20 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -8733,6 +10505,43 @@ impl SseDecode for Option { } } +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some( + ::sse_decode(deserializer), + ); + } else { + return None; + } + } +} + +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode( + deserializer, + )); + } else { + return None; + } + } +} + impl SseDecode for Option> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9336,12 +11145,172 @@ impl SseDecode for [usize; 4] { } } -impl SseDecode for crate::api::voting::VotingDelegationConfirmation { +impl SseDecode for crate::api::voting::VotingBallotIntent { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_skipped = ::sse_decode(deserializer); + let mut var_choice = >::sse_decode(deserializer); + return crate::api::voting::VotingBallotIntent { + proposal_id: var_proposalId, + skipped: var_skipped, + choice: var_choice, + }; + } +} + +impl SseDecode for crate::api::voting::VotingChainResponse { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_statusCode = ::sse_decode(deserializer); + let mut var_body = ::sse_decode(deserializer); + return crate::api::voting::VotingChainResponse { + status_code: var_statusCode, + body: var_body, + }; + } +} + +impl SseDecode for crate::api::voting::VotingCompletedVoteChoice { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_choice = >::sse_decode(deserializer); + return crate::api::voting::VotingCompletedVoteChoice { + proposal_id: var_proposalId, + choice: var_choice, + }; + } +} + +impl SseDecode for crate::api::voting::VotingCompletedVoteDisplay { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_choices = + >::sse_decode(deserializer); + let mut var_votedAt = >::sse_decode(deserializer); + return crate::api::voting::VotingCompletedVoteDisplay { + choices: var_choices, + voted_at: var_votedAt, + }; + } +} + +impl SseDecode for crate::api::voting::VotingConfig { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_source = ::sse_decode(deserializer); + let mut var_sourceFingerprint = ::sse_decode(deserializer); + let mut var_trustedKeyFingerprint = ::sse_decode(deserializer); + let mut var_switchKind = ::sse_decode(deserializer); + let mut var_voteServers = + >::sse_decode(deserializer); + let mut var_pirServers = + >::sse_decode(deserializer); + let mut var_pirLayout = + >::sse_decode(deserializer); + let mut var_rounds = >::sse_decode(deserializer); + return crate::api::voting::VotingConfig { + source: var_source, + source_fingerprint: var_sourceFingerprint, + trusted_key_fingerprint: var_trustedKeyFingerprint, + switch_kind: var_switchKind, + vote_servers: var_voteServers, + pir_servers: var_pirServers, + pir_layout: var_pirLayout, + rounds: var_rounds, + }; + } +} + +impl SseDecode for crate::api::voting::VotingConfigRound { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_eaPk = >::sse_decode(deserializer); + return crate::api::voting::VotingConfigRound { + round_id: var_roundId, + ea_pk: var_eaPk, + }; + } +} + +impl SseDecode for crate::api::voting::VotingDelegationBuild { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_submission = + ::sse_decode(deserializer); + let mut var_wireJson = ::sse_decode(deserializer); + return crate::api::voting::VotingDelegationBuild { + submission: var_submission, + wire_json: var_wireJson, + }; + } +} + +impl SseDecode for crate::api::voting::VotingDelegationConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_txHash = ::sse_decode(deserializer); + let mut var_vanLeafPosition = ::sse_decode(deserializer); + return crate::api::voting::VotingDelegationConfirmation { + tx_hash: var_txHash, + van_leaf_position: var_vanLeafPosition, + }; + } +} + +impl SseDecode for crate::api::voting::VotingDelegationProgress { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut tag_ = ::sse_decode(deserializer); + match tag_ { + 0 => { + return crate::api::voting::VotingDelegationProgress::SelectingNotes; + } + 1 => { + return crate::api::voting::VotingDelegationProgress::PcztBuilding; + } + 2 => { + return crate::api::voting::VotingDelegationProgress::PcztBuilt; + } + 3 => { + return crate::api::voting::VotingDelegationProgress::ProofStarting; + } + 4 => { + let mut var_progress = ::sse_decode(deserializer); + return crate::api::voting::VotingDelegationProgress::ProofProgress { + progress: var_progress, + }; + } + 5 => { + return crate::api::voting::VotingDelegationProgress::ProofComplete; + } + 6 => { + return crate::api::voting::VotingDelegationProgress::SigningPayload; + } + 7 => { + return crate::api::voting::VotingDelegationProgress::PayloadReady; + } + _ => { + unimplemented!(""); + } + } + } +} + +impl SseDecode for crate::api::voting::VotingDelegationRecovery { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_txHash = ::sse_decode(deserializer); - let mut var_vanLeafPosition = ::sse_decode(deserializer); - return crate::api::voting::VotingDelegationConfirmation { + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_phase = ::sse_decode(deserializer); + let mut var_workflowPhase = ::sse_decode(deserializer); + let mut var_txHash = >::sse_decode(deserializer); + let mut var_vanLeafPosition = >::sse_decode(deserializer); + return crate::api::voting::VotingDelegationRecovery { + bundle_index: var_bundleIndex, + phase: var_phase, + workflow_phase: var_workflowPhase, tx_hash: var_txHash, van_leaf_position: var_vanLeafPosition, }; @@ -9368,6 +11337,20 @@ impl SseDecode for crate::api::voting::VotingDelegationSetup { } } +impl SseDecode for crate::api::voting::VotingDelegationStatus { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_phase = ::sse_decode(deserializer); + let mut var_txHash = >::sse_decode(deserializer); + return crate::api::voting::VotingDelegationStatus { + bundle_index: var_bundleIndex, + phase: var_phase, + tx_hash: var_txHash, + }; + } +} + impl SseDecode for crate::api::voting::VotingDelegationSubmission { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9412,6 +11395,24 @@ impl SseDecode for crate::api::voting::VotingEncryptedShare { } } +impl SseDecode for crate::api::voting::VotingNextStep { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_kind = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_choice = ::sse_decode(deserializer); + let mut var_shareIndex = ::sse_decode(deserializer); + return crate::api::voting::VotingNextStep { + kind: var_kind, + bundle_index: var_bundleIndex, + proposal_id: var_proposalId, + choice: var_choice, + share_index: var_shareIndex, + }; + } +} + impl SseDecode for crate::api::voting::VotingPirLayout { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9446,6 +11447,130 @@ impl SseDecode for crate::api::voting::VotingPreparedInfo { } } +impl SseDecode for crate::api::voting::VotingRoundInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_network = ::sse_decode(deserializer); + let mut var_snapshotHeight = ::sse_decode(deserializer); + let mut var_hotkeyAddress = >::sse_decode(deserializer); + let mut var_eligibleWeightZatoshi = >::sse_decode(deserializer); + let mut var_bundleCount = ::sse_decode(deserializer); + let mut var_createdAt = ::sse_decode(deserializer); + return crate::api::voting::VotingRoundInfo { + round_id: var_roundId, + network: var_network, + snapshot_height: var_snapshotHeight, + hotkey_address: var_hotkeyAddress, + eligible_weight_zatoshi: var_eligibleWeightZatoshi, + bundle_count: var_bundleCount, + created_at: var_createdAt, + }; + } +} + +impl SseDecode for crate::api::voting::VotingRoundPlan { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_pendingRecovery = ::sse_decode(deserializer); + let mut var_nextSteps = >::sse_decode(deserializer); + let mut var_openProposals = >::sse_decode(deserializer); + let mut var_allDecided = ::sse_decode(deserializer); + let mut var_delegationStatuses = + >::sse_decode(deserializer); + let mut var_blockingRecovery = ::sse_decode(deserializer); + let mut var_blockingShareWork = ::sse_decode(deserializer); + let mut var_hotkeyBound = ::sse_decode(deserializer); + let mut var_completedVoteArtifact = ::sse_decode(deserializer); + let mut var_completedForDisplay = ::sse_decode(deserializer); + let mut var_completedVoteDisplay = + >::sse_decode(deserializer); + let mut var_needsDraftSetup = ::sse_decode(deserializer); + let mut var_primaryAction = ::sse_decode(deserializer); + return crate::api::voting::VotingRoundPlan { + round_id: var_roundId, + pending_recovery: var_pendingRecovery, + next_steps: var_nextSteps, + open_proposals: var_openProposals, + all_decided: var_allDecided, + delegation_statuses: var_delegationStatuses, + blocking_recovery: var_blockingRecovery, + blocking_share_work: var_blockingShareWork, + hotkey_bound: var_hotkeyBound, + completed_vote_artifact: var_completedVoteArtifact, + completed_for_display: var_completedForDisplay, + completed_vote_display: var_completedVoteDisplay, + needs_draft_setup: var_needsDraftSetup, + primary_action: var_primaryAction, + }; + } +} + +impl SseDecode for crate::api::voting::VotingRoundRecovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_bundleCount = ::sse_decode(deserializer); + let mut var_delegation = + >::sse_decode(deserializer); + let mut var_votes = >::sse_decode(deserializer); + let mut var_shares = + >::sse_decode(deserializer); + let mut var_shareDelegations = + >::sse_decode(deserializer); + let mut var_unconfirmedShareDelegations = + >::sse_decode(deserializer); + return crate::api::voting::VotingRoundRecovery { + round_id: var_roundId, + bundle_count: var_bundleCount, + delegation: var_delegation, + votes: var_votes, + shares: var_shares, + share_delegations: var_shareDelegations, + unconfirmed_share_delegations: var_unconfirmedShareDelegations, + }; + } +} + +impl SseDecode for crate::api::voting::VotingServiceEndpoint { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_url = ::sse_decode(deserializer); + let mut var_label = ::sse_decode(deserializer); + return crate::api::voting::VotingServiceEndpoint { + url: var_url, + label: var_label, + }; + } +} + +impl SseDecode for crate::api::voting::VotingShareDelegationRecord { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_shareIndex = ::sse_decode(deserializer); + let mut var_sentToUrls = >::sse_decode(deserializer); + let mut var_nullifier = >::sse_decode(deserializer); + let mut var_confirmed = ::sse_decode(deserializer); + let mut var_submitAt = ::sse_decode(deserializer); + let mut var_createdAt = ::sse_decode(deserializer); + return crate::api::voting::VotingShareDelegationRecord { + round_id: var_roundId, + bundle_index: var_bundleIndex, + proposal_id: var_proposalId, + share_index: var_shareIndex, + sent_to_urls: var_sentToUrls, + nullifier: var_nullifier, + confirmed: var_confirmed, + submit_at: var_submitAt, + created_at: var_createdAt, + }; + } +} + impl SseDecode for crate::api::voting::VotingSharePayload { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9471,6 +11596,72 @@ impl SseDecode for crate::api::voting::VotingSharePayload { } } +impl SseDecode for crate::api::voting::VotingSharePlan { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_summary = + ::sse_decode(deserializer); + let mut var_nextTrackingDelaySecs = >::sse_decode(deserializer); + let mut var_lastMoment = ::sse_decode(deserializer); + let mut var_submissions = + >::sse_decode(deserializer); + return crate::api::voting::VotingSharePlan { + summary: var_summary, + next_tracking_delay_secs: var_nextTrackingDelaySecs, + last_moment: var_lastMoment, + submissions: var_submissions, + }; + } +} + +impl SseDecode for crate::api::voting::VotingSharePlanItem { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_submitAt = ::sse_decode(deserializer); + let mut var_targetCount = ::sse_decode(deserializer); + let mut var_targetServers = >::sse_decode(deserializer); + return crate::api::voting::VotingSharePlanItem { + submit_at: var_submitAt, + target_count: var_targetCount, + target_servers: var_targetServers, + }; + } +} + +impl SseDecode for crate::api::voting::VotingShareTrackingSummary { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_total = ::sse_decode(deserializer); + let mut var_confirmed = ::sse_decode(deserializer); + let mut var_waiting = ::sse_decode(deserializer); + let mut var_ready = ::sse_decode(deserializer); + let mut var_overdue = ::sse_decode(deserializer); + return crate::api::voting::VotingShareTrackingSummary { + total: var_total, + confirmed: var_confirmed, + waiting: var_waiting, + ready: var_ready, + overdue: var_overdue, + }; + } +} + +impl SseDecode for crate::api::voting::VotingShareWorkflow { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_shareIndex = ::sse_decode(deserializer); + let mut var_phase = ::sse_decode(deserializer); + return crate::api::voting::VotingShareWorkflow { + bundle_index: var_bundleIndex, + proposal_id: var_proposalId, + share_index: var_shareIndex, + phase: var_phase, + }; + } +} + impl SseDecode for crate::api::voting::VotingSignedVoteCommitment { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9515,6 +11706,52 @@ impl SseDecode for crate::api::voting::VotingVanWitness { } } +impl SseDecode for crate::api::voting::VotingVoteCommitStage { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut tag_ = ::sse_decode(deserializer); + match tag_ { + 0 => { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteCommitStage::ProofStarting { + proposal_id: var_proposalId, + bundle_index: var_bundleIndex, + }; + } + 1 => { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_progress = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteCommitStage::ProofProgress { + proposal_id: var_proposalId, + bundle_index: var_bundleIndex, + progress: var_progress, + }; + } + 2 => { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteCommitStage::SharePayloadsBuilding { + proposal_id: var_proposalId, + bundle_index: var_bundleIndex, + }; + } + 3 => { + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_bundleIndex = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteCommitStage::Signing { + proposal_id: var_proposalId, + bundle_index: var_bundleIndex, + }; + } + _ => { + unimplemented!(""); + } + } + } +} + impl SseDecode for crate::api::voting::VotingVoteCommitments { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9556,6 +11793,30 @@ impl SseDecode for crate::api::voting::VotingVotePayloads { } } +impl SseDecode for crate::api::voting::VotingVoteRecovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_bundleIndex = ::sse_decode(deserializer); + let mut var_proposalId = ::sse_decode(deserializer); + let mut var_choice = ::sse_decode(deserializer); + let mut var_phase = ::sse_decode(deserializer); + let mut var_workflowPhase = ::sse_decode(deserializer); + let mut var_txHash = >::sse_decode(deserializer); + let mut var_vcTreePosition = >::sse_decode(deserializer); + let mut var_hasCommitmentBundle = ::sse_decode(deserializer); + return crate::api::voting::VotingVoteRecovery { + bundle_index: var_bundleIndex, + proposal_id: var_proposalId, + choice: var_choice, + phase: var_phase, + workflow_phase: var_workflowPhase, + tx_hash: var_txHash, + vc_tree_position: var_vcTreePosition, + has_commitment_bundle: var_hasCommitmentBundle, + }; + } +} + impl SseDecode for crate::api::voting::VotingVoteSubmission { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -9673,1310 +11934,1930 @@ fn pde_ffi_dispatcher_primary_impl( } 35 => wire__crate__api__account__create_new_folder_impl(port, ptr, rust_vec_len, data_len), 36 => wire__crate__api__raptor__decode_impl(port, ptr, rust_vec_len, data_len), - 37 => wire__crate__api__voting__delegation_confirm_impl(port, ptr, rust_vec_len, data_len), - 38 => wire__crate__api__voting__delegation_prepare_impl(port, ptr, rust_vec_len, data_len), - 39 => wire__crate__api__voting__delegation_setup_impl(port, ptr, rust_vec_len, data_len), - 40 => wire__crate__api__voting__delegation_sign_and_submit_impl( + 37 => wire__crate__api__voting__delegation_build_submission_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 38 => wire__crate__api__voting__delegation_confirm_impl(port, ptr, rust_vec_len, data_len), + 39 => wire__crate__api__voting__delegation_mark_submitted_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 40 => wire__crate__api__voting__delegation_prepare_impl(port, ptr, rust_vec_len, data_len), + 41 => wire__crate__api__voting__delegation_prepare_resume_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 42 => wire__crate__api__voting__delegation_setup_impl(port, ptr, rust_vec_len, data_len), + 43 => wire__crate__api__voting__delegation_sign_and_submit_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 44 => wire__crate__api__voting__delegation_tx_hash_impl(port, ptr, rust_vec_len, data_len), + 45 => { + wire__crate__api__voting__delegation_wire_json_impl(port, ptr, rust_vec_len, data_len) + } + 46 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), + 48 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), + 49 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__sapling__download_sapling_params_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 53 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), + 55 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), + 56 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), + 57 => wire__crate__api__contacts__export_contacts_vcard_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 58 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), + 59 => wire__crate__api__account__fetch_address_tx_count_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 60 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), + 61 => wire__crate__api__transaction__fetch_category_amounts_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 62 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 63 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), + 64 => wire__crate__api__transaction__fill_missing_tx_prices_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 65 => wire__crate__api__contacts__find_contacts_for_address_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 66 => wire__crate__api__frost__frost_sign_params_default_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 67 => wire__crate__api__account__generate_next_change_address_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 68 => { + wire__crate__api__account__generate_next_dindex_impl(port, ptr, rust_vec_len, data_len) + } + 70 => { + wire__crate__api__account__get_account_addresses_impl(port, ptr, rust_vec_len, data_len) + } + 71 => wire__crate__api__account__get_account_fingerprint_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 72 => wire__crate__api__account__get_account_frost_params_impl( port, ptr, rust_vec_len, data_len, ), - 41 => wire__crate__api__account__delete_account_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__account__delete_categories_impl(port, ptr, rust_vec_len, data_len), - 43 => wire__crate__api__contacts__delete_contacts_impl(port, ptr, rust_vec_len, data_len), - 44 => wire__crate__api__account__delete_folders_impl(port, ptr, rust_vec_len, data_len), - 45 => wire__crate__api__frost__do_dkg_impl(port, ptr, rust_vec_len, data_len), - 46 => wire__crate__api__frost__do_sign_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__sapling__download_sapling_params_impl( + 73 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), + 74 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), + 75 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), + 76 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), + 77 => { + wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) + } + 78 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), + 79 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), + 80 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 81 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), + 82 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), + 84 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), + 85 => { + wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) + } + 86 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), + 87 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), + 89 => wire__crate__api__network__get_supported_vs_currencies_impl( port, ptr, rust_vec_len, data_len, ), - 48 => wire__crate__api__account__dummy_export_impl(port, ptr, rust_vec_len, data_len), - 49 => wire__crate__api__raptor__encode_impl(port, ptr, rust_vec_len, data_len), - 50 => wire__crate__api__raptor__end_decode_impl(port, ptr, rust_vec_len, data_len), - 51 => wire__crate__api__account__export_account_impl(port, ptr, rust_vec_len, data_len), - 52 => wire__crate__api__contacts__export_contacts_vcard_impl( + 90 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), + 91 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), + 92 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), + 93 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 94 => wire__crate__api__account__has_transparent_pub_key_impl( port, ptr, rust_vec_len, data_len, ), - 53 => wire__crate__api__pay__extract_transaction_impl(port, ptr, rust_vec_len, data_len), - 54 => wire__crate__api__account__fetch_address_tx_count_impl( + 95 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), + 96 => wire__crate__api__contacts__import_contacts_vcard_impl( port, ptr, rust_vec_len, data_len, ), - 55 => wire__crate__api__transaction__fetch_amounts_impl(port, ptr, rust_vec_len, data_len), - 56 => wire__crate__api__transaction__fetch_category_amounts_impl( + 97 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), + 98 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), + 99 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 100 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), + 101 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), + 103 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), + 104 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), + 105 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), + 106 => { + wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len) + } + 107 => { + wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) + } + 115 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), + 116 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), + 117 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 120 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 129 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 57 => wire__crate__api__account__fetch_transparent_address_tx_count_impl( + 135 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 138 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 139 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 140 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 149 => { + wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) + } + 150 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 58 => wire__crate__api__sync__fetch_tx_details_impl(port, ptr, rust_vec_len, data_len), - 59 => wire__crate__api__transaction__fill_missing_tx_prices_impl( + 151 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 60 => wire__crate__api__contacts__find_contacts_for_address_impl( + 152 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 153 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 154 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 155 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 159 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 160 => { + wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) + } + 161 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 162 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 61 => wire__crate__api__frost__frost_sign_params_default_impl( + 164 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 62 => wire__crate__api__account__generate_next_change_address_impl( + 165 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 63 => { - wire__crate__api__account__generate_next_dindex_impl(port, ptr, rust_vec_len, data_len) - } - 65 => { - wire__crate__api__account__get_account_addresses_impl(port, ptr, rust_vec_len, data_len) + 166 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 173 => { + wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 66 => wire__crate__api__account__get_account_fingerprint_impl( + 174 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 175 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 176 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 177 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 179 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 180 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 181 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 182 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 183 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, data_len, ), - 67 => wire__crate__api__account__get_account_frost_params_impl( + 186 => { + wire__crate__api__voting__votechain_list_rounds_impl(port, ptr, rust_vec_len, data_len) + } + 187 => wire__crate__api__voting__votechain_resubmit_share_impl( port, ptr, rust_vec_len, data_len, ), - 68 => wire__crate__api__account__get_account_pools_impl(port, ptr, rust_vec_len, data_len), - 69 => wire__crate__api__account__get_account_seed_impl(port, ptr, rust_vec_len, data_len), - 70 => wire__crate__api__account__get_account_ufvk_impl(port, ptr, rust_vec_len, data_len), - 71 => wire__crate__api__account__get_addresses_impl(port, ptr, rust_vec_len, data_len), - 72 => { - wire__crate__api__network__get_coingecko_price_impl(port, ptr, rust_vec_len, data_len) + 188 => { + wire__crate__api__voting__votechain_round_status_impl(port, ptr, rust_vec_len, data_len) } - 73 => wire__crate__api__network__get_current_height_impl(port, ptr, rust_vec_len, data_len), - 74 => wire__crate__api__sync__get_db_height_impl(port, ptr, rust_vec_len, data_len), - 75 => wire__crate__api__frost__get_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 76 => wire__crate__api__network__get_exchange_rate_impl(port, ptr, rust_vec_len, data_len), - 77 => wire__crate__api__account__get_exported_data_impl(port, ptr, rust_vec_len, data_len), - 79 => wire__crate__api__mempool__get_mempool_tx_impl(port, ptr, rust_vec_len, data_len), - 80 => { - wire__crate__api__migrate__get_migration_status_impl(port, ptr, rust_vec_len, data_len) + 189 => { + wire__crate__api__voting__votechain_round_tally_impl(port, ptr, rust_vec_len, data_len) } - 81 => wire__crate__api__network__get_network_name_impl(port, ptr, rust_vec_len, data_len), - 82 => wire__crate__api__db__get_prop_impl(port, ptr, rust_vec_len, data_len), - 84 => wire__crate__api__network__get_supported_vs_currencies_impl( + 190 => { + wire__crate__api__voting__votechain_share_status_impl(port, ptr, rust_vec_len, data_len) + } + 191 => wire__crate__api__voting__votechain_submit_delegation_impl( port, ptr, rust_vec_len, data_len, ), - 85 => wire__crate__api__coin__get_tor_client_impl(port, ptr, rust_vec_len, data_len), - 86 => wire__crate__api__account__get_tx_details_impl(port, ptr, rust_vec_len, data_len), - 87 => wire__crate__api__frost__has_dkg_addresses_impl(port, ptr, rust_vec_len, data_len), - 88 => wire__crate__api__frost__has_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 89 => wire__crate__api__account__has_transparent_pub_key_impl( + 192 => { + wire__crate__api__voting__votechain_submit_share_impl(port, ptr, rust_vec_len, data_len) + } + 193 => { + wire__crate__api__voting__votechain_submit_vote_impl(port, ptr, rust_vec_len, data_len) + } + 194 => wire__crate__api__voting__votechain_tx_confirmation_impl( port, ptr, rust_vec_len, data_len, ), - 90 => wire__crate__api__account__import_account_impl(port, ptr, rust_vec_len, data_len), - 91 => wire__crate__api__contacts__import_contacts_vcard_impl( + 195 => { + wire__crate__api__voting__voting_ballot_intents_impl(port, ptr, rust_vec_len, data_len) + } + 196 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 197 => wire__crate__api__voting__voting_commit_with_progress_impl( port, ptr, rust_vec_len, data_len, ), - 92 => wire__crate__api__init__init_app_impl(port, ptr, rust_vec_len, data_len), - 93 => wire__crate__api__raptor__init_app_impl(port, ptr, rust_vec_len, data_len), - 94 => wire__crate__api__coin__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 95 => wire__crate__api__network__init_datadir_impl(port, ptr, rust_vec_len, data_len), - 96 => wire__crate__api__frost__init_dkg_impl(port, ptr, rust_vec_len, data_len), - 98 => wire__crate__api__frost__init_sign_impl(port, ptr, rust_vec_len, data_len), - 99 => wire__crate__api__vault__init_vault_impl(port, ptr, rust_vec_len, data_len), - 100 => wire__crate__api__plugin__install_plugin_impl(port, ptr, rust_vec_len, data_len), - 101 => { - wire__crate__api__network__is_ironwood_active_impl(port, ptr, rust_vec_len, data_len) - } - 102 => { - wire__crate__api__frost__is_signing_in_progress_impl(port, ptr, rust_vec_len, data_len) + 198 => { + wire__crate__api__voting__voting_config_cached_impl(port, ptr, rust_vec_len, data_len) } - 110 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), - 111 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 112 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 113 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 114 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 115 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 116 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 128 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 199 => wire__crate__api__voting__voting_config_clear_cache_impl( port, ptr, rust_vec_len, data_len, ), - 130 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 138 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 139 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 140 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 141 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 144 => { - wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) + 200 => { + wire__crate__api__voting__voting_config_resolve_impl(port, ptr, rust_vec_len, data_len) } - 145 => wire__crate__api__openalias__resolve_openalias_all_impl( + 201 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 202 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), + 203 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), + 204 => { + wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) + } + 205 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 206 => wire__crate__api__voting__voting_mark_vote_submitted_impl( port, ptr, rust_vec_len, data_len, ), - 146 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 207 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 208 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 209 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 147 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 150 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 151 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 154 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 155 => { - wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) + 210 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 211 => { + wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 156 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__account__show_ledger_sapling_address_impl( + 212 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 159 => wire__crate__api__account__show_ledger_transparent_address_impl( + 213 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 214 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 160 => wire__crate__api__account__sign_ledger_transaction_impl( + 215 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 161 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 162 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 168 => { - wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) + 216 => { + wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 169 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 170 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 172 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 174 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 175 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 176 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 177 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 178 => wire__crate__api__transaction__update_historical_prices_impl( + 217 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 218 => { + wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) + } + 219 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 181 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), - 182 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 183 => { - wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) + 220 => { + wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 184 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 185 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 186 => wire__crate__api__voting__voting_record_execution_impl( - port, + 221 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 222 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 223 => { + wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) + } + _ => unreachable!(), + } +} + +fn pde_ffi_dispatcher_sync_impl( + func_id: i32, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), + 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), + 13 => { + wire__crate__api__migrate__NoteMigration_update_height_impl(ptr, rust_vec_len, data_len) + } + 24 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), + 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), + 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), + 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), + 32 => wire__crate__api__coin__coin_set_transport_impl(ptr, rust_vec_len, data_len), + 69 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), + 83 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), + 88 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), + 102 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), + 108 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), + 109 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), + 110 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), + 111 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), + 112 => wire__crate__api__network__is_valid_nym_url_impl(ptr, rust_vec_len, data_len), + 113 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), + 114 => { + wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) + } + 134 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 141 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 157 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 158 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 170 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 172 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 187 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 178 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 184 => { + wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) + } + 185 => { + wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) + } _ => unreachable!(), } } - -fn pde_ffi_dispatcher_sync_impl( - func_id: i32, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - 8 => wire__crate__api__mempool__Mempool_new_impl(ptr, rust_vec_len, data_len), - 11 => wire__crate__api__migrate__NoteMigration_new_impl(ptr, rust_vec_len, data_len), - 13 => { - wire__crate__api__migrate__NoteMigration_update_height_impl(ptr, rust_vec_len, data_len) - } - 24 => wire__crate__api__sapling__check_sapling_params_impl(ptr, rust_vec_len, data_len), - 27 => wire__crate__api__coin__coin_new_impl(ptr, rust_vec_len, data_len), - 30 => wire__crate__api__coin__coin_set_lwd_impl(ptr, rust_vec_len, data_len), - 31 => wire__crate__api__coin__coin_set_proxy_impl(ptr, rust_vec_len, data_len), - 32 => wire__crate__api__coin__coin_set_transport_impl(ptr, rust_vec_len, data_len), - 64 => wire__crate__api__key__generate_seed_impl(ptr, rust_vec_len, data_len), - 78 => wire__crate__api__key__get_key_pools_impl(ptr, rust_vec_len, data_len), - 83 => wire__crate__api__raptor__get_qr_bytes_impl(ptr, rust_vec_len, data_len), - 97 => wire__crate__api__plugin__init_plugins_impl(ptr, rust_vec_len, data_len), - 103 => wire__crate__api__key__is_tex_address_impl(ptr, rust_vec_len, data_len), - 104 => wire__crate__api__key__is_valid_address_impl(ptr, rust_vec_len, data_len), - 105 => wire__crate__api__key__is_valid_fvk_impl(ptr, rust_vec_len, data_len), - 106 => wire__crate__api__key__is_valid_key_impl(ptr, rust_vec_len, data_len), - 107 => wire__crate__api__network__is_valid_nym_url_impl(ptr, rust_vec_len, data_len), - 108 => wire__crate__api__key__is_valid_phrase_impl(ptr, rust_vec_len, data_len), - 109 => { - wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) - } - 129 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 136 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 152 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 153 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 165 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 167 => wire__crate__api__openalias__try_validate_zcash_address_impl( - ptr, - rust_vec_len, - data_len, - ), - 173 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 179 => { - wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) - } - 180 => { - wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) + +// Section: rust2dart + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for DartVault { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for Mempool { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for NoteMigration { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} + +impl flutter_rust_bridge::IntoIntoDart> for TransparentScanner { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Account { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.seed.into_into_dart().into_dart(), + self.passphrase.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.dindex.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.position.into_into_dart().into_dart(), + self.hidden.into_into_dart().into_dart(), + self.saved.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + self.internal.into_into_dart().into_dart(), + self.hw.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.balance.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Account {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Account +{ + fn into_into_dart(self) -> crate::api::account::Account { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::AccountUpdate { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.hidden.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::AccountUpdate +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::AccountUpdate +{ + fn into_into_dart(self) -> crate::api::account::AccountUpdate { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Addresses { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.taddr.into_into_dart().into_dart(), + self.saddr.into_into_dart().into_dart(), + self.oaddr.into_into_dart().into_dart(), + self.ua.into_into_dart().into_dart(), + self.diversifier_index.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::Addresses +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Addresses +{ + fn into_into_dart(self) -> crate::api::account::Addresses { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Category { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.is_income.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Category {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Category +{ + fn into_into_dart(self) -> crate::api::account::Category { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::coin::Coin { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.coin.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.db_filepath.into_into_dart().into_dart(), + self.url.into_into_dart().into_dart(), + self.server_type.into_into_dart().into_dart(), + self.transport.into_into_dart().into_dart(), + self.proxy.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::coin::Coin {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::coin::Coin { + fn into_into_dart(self) -> crate::api::coin::Coin { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::contacts::Contact { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.addresses.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::contacts::Contact {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::contacts::Contact +{ + fn into_into_dart(self) -> crate::api::contacts::Contact { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::contacts::ContactMatch { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.contact.into_into_dart().into_dart(), + self.matched_address.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::contacts::ContactMatch +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::contacts::ContactMatch +{ + fn into_into_dart(self) -> crate::api::contacts::ContactMatch { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::db::DbAccountPreview { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::db::DbAccountPreview +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::db::DbAccountPreview +{ + fn into_into_dart(self) -> crate::api::db::DbAccountPreview { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::frost::DKGStatus::WaitParams => [0.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitAddresses(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::frost::DKGStatus::PublishRound1Pkg => [2.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound1Pkg => [3.into_dart()].into_dart(), + crate::api::frost::DKGStatus::PublishRound2Pkg => [4.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound2Pkg => [5.into_dart()].into_dart(), + crate::api::frost::DKGStatus::Finalize => [6.into_dart()].into_dart(), + crate::api::frost::DKGStatus::SharedAddress(field0) => { + [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } } - _ => unreachable!(), } } - -// Section: rust2dart - +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::frost::DKGStatus {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::DKGStatus +{ + fn into_into_dart(self) -> crate::api::frost::DKGStatus { + self + } +} // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::network::ExchangeRate { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.from_price.into_into_dart().into_dart(), + self.to_price.into_into_dart().into_dart(), + self.from_currency.into_into_dart().into_dart(), + self.to_currency.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::network::ExchangeRate +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::network::ExchangeRate +{ + fn into_into_dart(self) -> crate::api::network::ExchangeRate { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Folder { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Folder {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Folder +{ + fn into_into_dart(self) -> crate::api::account::Folder { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::FrostParams { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.n.into_into_dart().into_dart(), + self.t.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::FrostParams +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::FrostParams +{ + fn into_into_dart(self) -> crate::api::account::FrostParams { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::frost::FrostSignParams { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.account.into_into_dart().into_dart(), + self.coordinator.into_into_dart().into_dart(), + self.funding_account.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::frost::FrostSignParams +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::FrostSignParams +{ + fn into_into_dart(self) -> crate::api::frost::FrostSignParams { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::init::LogMessage { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.level.into_into_dart().into_dart(), + self.message.into_into_dart().into_dart(), + self.span.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::init::LogMessage {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::init::LogMessage +{ + fn into_into_dart(self) -> crate::api::init::LogMessage { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::network::LWDInfo { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.url.into_into_dart().into_dart(), + self.is_tor.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.status.into_into_dart().into_dart(), + self.uptime.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.ping.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::network::LWDInfo {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::network::LWDInfo +{ + fn into_into_dart(self) -> crate::api::network::LWDInfo { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Memo { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.id.into_into_dart().into_dart(), + self.id_tx.into_into_dart().into_dart(), + self.id_note.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.vout.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.is_user_memo.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for DartVault { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Memo {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Memo { + fn into_into_dart(self) -> crate::api::account::Memo { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoCell { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.cell_type.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for Mempool { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoCell {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoCell +{ + fn into_into_dart(self) -> crate::api::plugin::MemoCell { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoRow { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [self.cells.into_into_dart().into_dart()].into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for NoteMigration { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoRow {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoRow +{ + fn into_into_dart(self) -> crate::api::plugin::MemoRow { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoSection { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() + [ + self.title.into_into_dart().into_dart(), + self.headers.into_into_dart().into_dart(), + self.rows.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper + for crate::api::plugin::MemoSection { } - -impl flutter_rust_bridge::IntoIntoDart> for TransparentScanner { - fn into_into_dart(self) -> FrbWrapper { - self.into() +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::MemoSection +{ + fn into_into_dart(self) -> crate::api::plugin::MemoSection { + self } } - // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Account { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolAmount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.coin.into_into_dart().into_dart(), - self.id.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), self.name.into_into_dart().into_dart(), - self.seed.into_into_dart().into_dart(), - self.passphrase.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), - self.dindex.into_into_dart().into_dart(), - self.icon.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.position.into_into_dart().into_dart(), - self.hidden.into_into_dart().into_dart(), - self.saved.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), - self.internal.into_into_dart().into_dart(), - self.hw.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.balance.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Account {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Account +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::mempool::MempoolAmount { - fn into_into_dart(self) -> crate::api::account::Account { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolAmount +{ + fn into_into_dart(self) -> crate::api::mempool::MempoolAmount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::AccountUpdate { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolMsg { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.coin.into_into_dart().into_dart(), - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.icon.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.hidden.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), - ] - .into_dart() + match self { + crate::api::mempool::MempoolMsg::BlockHeight(field0) => { + [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::mempool::MempoolMsg::TxId(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::AccountUpdate + for crate::api::mempool::MempoolMsg { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::AccountUpdate +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolMsg { - fn into_into_dart(self) -> crate::api::account::AccountUpdate { + fn into_into_dart(self) -> crate::api::mempool::MempoolMsg { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Addresses { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolNote { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.taddr.into_into_dart().into_dart(), - self.saddr.into_into_dart().into_dart(), - self.oaddr.into_into_dart().into_dart(), - self.ua.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.diversifier.into_into_dart().into_dart(), self.diversifier_index.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::Addresses + for crate::api::mempool::MempoolNote { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Addresses +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolNote { - fn into_into_dart(self) -> crate::api::account::Addresses { + fn into_into_dart(self) -> crate::api::mempool::MempoolNote { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Category { +impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolTx { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.is_income.into_into_dart().into_dart(), + self.txid.into_into_dart().into_dart(), + self.amounts.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + self.size.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Category {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Category +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::mempool::MempoolTx { - fn into_into_dart(self) -> crate::api::account::Category { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::mempool::MempoolTx +{ + fn into_into_dart(self) -> crate::api::mempool::MempoolTx { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::coin::Coin { +impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationEvent { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::migrate::MigrationEvent::SplitComplete { fee } => { + [0.into_dart(), fee.into_into_dart().into_dart()].into_dart() + } + crate::api::migrate::MigrationEvent::MigrateComplete { fee } => { + [1.into_dart(), fee.into_into_dart().into_dart()].into_dart() + } + crate::api::migrate::MigrationEvent::Complete => [2.into_dart()].into_dart(), + crate::api::migrate::MigrationEvent::NothingToDo => [3.into_dart()].into_dart(), + crate::api::migrate::MigrationEvent::Error { message } => { + [4.into_dart(), message.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::migrate::MigrationEvent +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::migrate::MigrationEvent +{ + fn into_into_dart(self) -> crate::api::migrate::MigrationEvent { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.coin.into_into_dart().into_dart(), - self.account.into_into_dart().into_dart(), - self.db_filepath.into_into_dart().into_dart(), - self.url.into_into_dart().into_dart(), - self.server_type.into_into_dart().into_dart(), - self.transport.into_into_dart().into_dart(), - self.proxy.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), + self.split_fees.into_into_dart().into_dart(), + self.migrate_fees.into_into_dart().into_dart(), + self.total_fees.into_into_dart().into_dart(), + self.sd_notes_count.into_into_dart().into_dart(), + self.non_sd_notes_count.into_into_dart().into_dart(), + self.ironwood_sd_count.into_into_dart().into_dart(), + self.progress.into_into_dart().into_dart(), + self.next_action.into_into_dart().into_dart(), + self.work_summary.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::coin::Coin {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::coin::Coin { - fn into_into_dart(self) -> crate::api::coin::Coin { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::migrate::MigrationStatus +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::migrate::MigrationStatus +{ + fn into_into_dart(self) -> crate::api::migrate::MigrationStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::contacts::Contact { +impl flutter_rust_bridge::IntoDart for crate::api::account::NewAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), + self.icon.into_into_dart().into_dart(), self.name.into_into_dart().into_dart(), - self.addresses.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), + self.restore.into_into_dart().into_dart(), + self.key.into_into_dart().into_dart(), + self.passphrase.into_into_dart().into_dart(), + self.fingerprint.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.birth.into_into_dart().into_dart(), + self.folder.into_into_dart().into_dart(), + self.pools.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.internal.into_into_dart().into_dart(), + self.ledger.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::contacts::Contact {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::contacts::Contact +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::NewAccount { - fn into_into_dart(self) -> crate::api::contacts::Contact { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::NewAccount +{ + fn into_into_dart(self) -> crate::api::account::NewAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::contacts::ContactMatch { +impl flutter_rust_bridge::IntoDart for crate::api::openalias::OpenAliasResolution { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.contact.into_into_dart().into_dart(), - self.matched_address.into_into_dart().into_dart(), + self.recipients.into_into_dart().into_dart(), + self.dnssec_status.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::contacts::ContactMatch + for crate::api::openalias::OpenAliasResolution { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::contacts::ContactMatch +impl flutter_rust_bridge::IntoIntoDart + for crate::api::openalias::OpenAliasResolution { - fn into_into_dart(self) -> crate::api::contacts::ContactMatch { + fn into_into_dart(self) -> crate::api::openalias::OpenAliasResolution { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::db::DbAccountPreview { +impl flutter_rust_bridge::IntoDart for crate::api::pay::PaymentOptions { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), + self.src_pools.into_into_dart().into_dart(), + self.recipient_pays_fee.into_into_dart().into_dart(), + self.smart_transparent.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::db::DbAccountPreview + for crate::api::pay::PaymentOptions { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::db::DbAccountPreview +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::PaymentOptions { - fn into_into_dart(self) -> crate::api::db::DbAccountPreview { + fn into_into_dart(self) -> crate::api::pay::PaymentOptions { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { +impl flutter_rust_bridge::IntoDart for crate::api::pay::PcztPackage { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::frost::DKGStatus::WaitParams => [0.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitAddresses(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crate::api::frost::DKGStatus::PublishRound1Pkg => [2.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound1Pkg => [3.into_dart()].into_dart(), - crate::api::frost::DKGStatus::PublishRound2Pkg => [4.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound2Pkg => [5.into_dart()].into_dart(), - crate::api::frost::DKGStatus::Finalize => [6.into_dart()].into_dart(), - crate::api::frost::DKGStatus::SharedAddress(field0) => { - [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.pczt.into_into_dart().into_dart(), + self.n_spends.into_into_dart().into_dart(), + self.sapling_indices.into_into_dart().into_dart(), + self.orchard_indices.into_into_dart().into_dart(), + self.ironwood_indices.into_into_dart().into_dart(), + self.can_sign.into_into_dart().into_dart(), + self.can_broadcast.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.is_issuance.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::frost::DKGStatus {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::DKGStatus +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::PcztPackage {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::PcztPackage { - fn into_into_dart(self) -> crate::api::frost::DKGStatus { + fn into_into_dart(self) -> crate::api::pay::PcztPackage { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::network::ExchangeRate { +impl flutter_rust_bridge::IntoDart for crate::api::plugin::PluginInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.from_price.into_into_dart().into_dart(), - self.to_price.into_into_dart().into_dart(), - self.from_currency.into_into_dart().into_dart(), - self.to_currency.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.author.into_into_dart().into_dart(), + self.description.into_into_dart().into_dart(), + self.enabled.into_into_dart().into_dart(), + self.types.into_into_dart().into_dart(), + self.memo_prefixes.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::network::ExchangeRate + for crate::api::plugin::PluginInfo { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::network::ExchangeRate +impl flutter_rust_bridge::IntoIntoDart + for crate::api::plugin::PluginInfo { - fn into_into_dart(self) -> crate::api::network::ExchangeRate { + fn into_into_dart(self) -> crate::api::plugin::PluginInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Folder { +impl flutter_rust_bridge::IntoDart for crate::api::sync::PoolBalance { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - ] - .into_dart() + [self.0.into_into_dart().into_dart()].into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Folder {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Folder +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::sync::PoolBalance {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sync::PoolBalance { - fn into_into_dart(self) -> crate::api::account::Folder { + fn into_into_dart(self) -> crate::api::sync::PoolBalance { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::FrostParams { +impl flutter_rust_bridge::IntoDart for crate::api::raptor::RaptorQParams { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.n.into_into_dart().into_dart(), - self.t.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.ec_level.into_into_dart().into_dart(), + self.repair.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::FrostParams + for crate::api::raptor::RaptorQParams { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::FrostParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::raptor::RaptorQParams { - fn into_into_dart(self) -> crate::api::account::FrostParams { + fn into_into_dart(self) -> crate::api::raptor::RaptorQParams { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::FrostSignParams { +impl flutter_rust_bridge::IntoDart for crate::api::openalias::RawOpenAliasResolution { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.coordinator.into_into_dart().into_dart(), - self.funding_account.into_into_dart().into_dart(), + self.records.into_into_dart().into_dart(), + self.dnssec_status.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::frost::FrostSignParams + for crate::api::openalias::RawOpenAliasResolution { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::FrostSignParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::openalias::RawOpenAliasResolution { - fn into_into_dart(self) -> crate::api::frost::FrostSignParams { + fn into_into_dart(self) -> crate::api::openalias::RawOpenAliasResolution { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::init::LogMessage { +impl flutter_rust_bridge::IntoDart for crate::api::account::Receivers { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.level.into_into_dart().into_dart(), - self.message.into_into_dart().into_dart(), - self.span.into_into_dart().into_dart(), + self.taddr.into_into_dart().into_dart(), + self.saddr.into_into_dart().into_dart(), + self.oaddr.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::init::LogMessage {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::init::LogMessage +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::account::Receivers { - fn into_into_dart(self) -> crate::api::init::LogMessage { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::Receivers +{ + fn into_into_dart(self) -> crate::api::account::Receivers { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::network::LWDInfo { +impl flutter_rust_bridge::IntoDart for crate::pay::Recipient { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.url.into_into_dart().into_dart(), - self.is_tor.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.status.into_into_dart().into_dart(), - self.uptime.into_into_dart().into_dart(), - self.version.into_into_dart().into_dart(), - self.ping.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.pools.into_into_dart().into_dart(), + self.user_memo.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.asset_base.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::network::LWDInfo {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::network::LWDInfo -{ - fn into_into_dart(self) -> crate::api::network::LWDInfo { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::Recipient {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::Recipient { + fn into_into_dart(self) -> crate::pay::Recipient { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Memo { +impl flutter_rust_bridge::IntoDart for crate::api::vault::RestoredAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.id_tx.into_into_dart().into_dart(), - self.id_note.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.vout.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.is_user_memo.into_into_dart().into_dart(), + self.timestamp.into_into_dart().into_dart(), + self.name.into_into_dart().into_dart(), + self.seed.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + self.use_internal.into_into_dart().into_dart(), + self.birth_height.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Memo {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Memo { - fn into_into_dart(self) -> crate::api::account::Memo { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::vault::RestoredAccount +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::vault::RestoredAccount +{ + fn into_into_dart(self) -> crate::api::vault::RestoredAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoCell { +impl flutter_rust_bridge::IntoDart for crate::api::sapling::SaplingParamsStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.cell_type.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - ] - .into_dart() + [self.downloaded.into_into_dart().into_dart()].into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoCell {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoCell +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::sapling::SaplingParamsStatus { - fn into_into_dart(self) -> crate::api::plugin::MemoCell { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sapling::SaplingParamsStatus +{ + fn into_into_dart(self) -> crate::api::sapling::SaplingParamsStatus { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::account::Seed { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.mnemonic.into_into_dart().into_dart(), + self.phrase.into_into_dart().into_dart(), + self.aindex.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Seed {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Seed { + fn into_into_dart(self) -> crate::api::account::Seed { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoRow { +impl flutter_rust_bridge::IntoDart for crate::api::pay::SigningEvent { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.cells.into_into_dart().into_dart()].into_dart() + match self { + crate::api::pay::SigningEvent::Progress(field0) => { + [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + crate::api::pay::SigningEvent::Result(field0) => { + [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::plugin::MemoRow {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoRow +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::SigningEvent {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::pay::SigningEvent { - fn into_into_dart(self) -> crate::api::plugin::MemoRow { + fn into_into_dart(self) -> crate::api::pay::SigningEvent { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::MemoSection { +impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.title.into_into_dart().into_dart(), - self.headers.into_into_dart().into_dart(), - self.rows.into_into_dart().into_dart(), - ] - .into_dart() + match self { + crate::api::frost::SigningStatus::SendingCommitment => [0.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForCommitments => [1.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SendingSigningPackage => [2.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForSigningPackage => { + [3.into_dart()].into_dart() + } + crate::api::frost::SigningStatus::SendingSignatureShare => [4.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SigningCompleted => [5.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForSignatureShares => { + [6.into_dart()].into_dart() + } + crate::api::frost::SigningStatus::PreparingTransaction => [7.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SendingTransaction => [8.into_dart()].into_dart(), + crate::api::frost::SigningStatus::TransactionSent(field0) => { + [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() + } + _ => { + unimplemented!(""); + } + } } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::plugin::MemoSection + for crate::api::frost::SigningStatus { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::MemoSection +impl flutter_rust_bridge::IntoIntoDart + for crate::api::frost::SigningStatus { - fn into_into_dart(self) -> crate::api::plugin::MemoSection { + fn into_into_dart(self) -> crate::api::frost::SigningStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolAmount { +impl flutter_rust_bridge::IntoDart for crate::io::SyncHeight { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolAmount -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolAmount -{ - fn into_into_dart(self) -> crate::api::mempool::MempoolAmount { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::io::SyncHeight {} +impl flutter_rust_bridge::IntoIntoDart for crate::io::SyncHeight { + fn into_into_dart(self) -> crate::io::SyncHeight { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolMsg { +impl flutter_rust_bridge::IntoDart for crate::api::sync::SyncProgress { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::mempool::MempoolMsg::BlockHeight(field0) => { - [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crate::api::mempool::MempoolMsg::TxId(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolMsg + for crate::api::sync::SyncProgress { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolMsg +impl flutter_rust_bridge::IntoIntoDart + for crate::api::sync::SyncProgress { - fn into_into_dart(self) -> crate::api::mempool::MempoolMsg { + fn into_into_dart(self) -> crate::api::sync::SyncProgress { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolNote { +impl flutter_rust_bridge::IntoDart for crate::api::account::TAddressTxCount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.account.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), self.pool.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.diversifier.into_into_dart().into_dart(), - self.diversifier_index.into_into_dart().into_dart(), self.address.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.dindex.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.tx_count.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolNote + for crate::api::account::TAddressTxCount { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolNote +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TAddressTxCount { - fn into_into_dart(self) -> crate::api::mempool::MempoolNote { + fn into_into_dart(self) -> crate::api::account::TAddressTxCount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::mempool::MempoolTx { +impl flutter_rust_bridge::IntoDart for crate::api::account::Tx { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ + self.id.into_into_dart().into_dart(), self.txid.into_into_dart().into_dart(), - self.amounts.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), - self.size.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.tpe.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.zsa_value.into_into_dart().into_dart(), + self.asset_id.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.is_user_memo.into_into_dart().into_dart(), + self.contact_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::mempool::MempoolTx -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::mempool::MempoolTx -{ - fn into_into_dart(self) -> crate::api::mempool::MempoolTx { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Tx {} +impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Tx { + fn into_into_dart(self) -> crate::api::account::Tx { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationEvent { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxAccount { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::migrate::MigrationEvent::SplitComplete { fee } => { - [0.into_dart(), fee.into_into_dart().into_dart()].into_dart() - } - crate::api::migrate::MigrationEvent::MigrateComplete { fee } => { - [1.into_dart(), fee.into_into_dart().into_dart()].into_dart() - } - crate::api::migrate::MigrationEvent::Complete => [2.into_dart()].into_dart(), - crate::api::migrate::MigrationEvent::NothingToDo => [3.into_dart()].into_dart(), - crate::api::migrate::MigrationEvent::Error { message } => { - [4.into_dart(), message.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.id.into_into_dart().into_dart(), + self.account.into_into_dart().into_dart(), + self.txid.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.time.into_into_dart().into_dart(), + self.price.into_into_dart().into_dart(), + self.category.into_into_dart().into_dart(), + self.notes.into_into_dart().into_dart(), + self.spends.into_into_dart().into_dart(), + self.outputs.into_into_dart().into_dart(), + self.memos.into_into_dart().into_dart(), + self.user_memo.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::migrate::MigrationEvent + for crate::api::account::TxAccount { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::migrate::MigrationEvent +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxAccount { - fn into_into_dart(self) -> crate::api::migrate::MigrationEvent { + fn into_into_dart(self) -> crate::api::account::TxAccount { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::migrate::MigrationStatus { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxMemo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.phase.into_into_dart().into_dart(), - self.split_fees.into_into_dart().into_dart(), - self.migrate_fees.into_into_dart().into_dart(), - self.total_fees.into_into_dart().into_dart(), - self.sd_notes_count.into_into_dart().into_dart(), - self.non_sd_notes_count.into_into_dart().into_dart(), - self.ironwood_sd_count.into_into_dart().into_dart(), - self.progress.into_into_dart().into_dart(), - self.next_action.into_into_dart().into_dart(), - self.work_summary.into_into_dart().into_dart(), + self.note.into_into_dart().into_dart(), + self.output.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.memo_bytes.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::migrate::MigrationStatus -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::migrate::MigrationStatus +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxMemo {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxMemo { - fn into_into_dart(self) -> crate::api::migrate::MigrationStatus { + fn into_into_dart(self) -> crate::api::account::TxMemo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::NewAccount { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxNote { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.icon.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.restore.into_into_dart().into_dart(), - self.key.into_into_dart().into_dart(), - self.passphrase.into_into_dart().into_dart(), - self.fingerprint.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), - self.birth.into_into_dart().into_dart(), - self.folder.into_into_dart().into_dart(), - self.pools.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.internal.into_into_dart().into_dart(), - self.ledger.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.tx.into_into_dart().into_dart(), + self.scope.into_into_dart().into_dart(), + self.diversifier.into_into_dart().into_dart(), + self.diversifier_index.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.locked.into_into_dart().into_dart(), + self.memo.into_into_dart().into_dart(), + self.id_asset.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::NewAccount -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::NewAccount +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxNote {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxNote { - fn into_into_dart(self) -> crate::api::account::NewAccount { + fn into_into_dart(self) -> crate::api::account::TxNote { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::openalias::OpenAliasResolution { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxOutput { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.recipients.into_into_dart().into_dart(), - self.dnssec_status.into_into_dart().into_dart(), + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.contact_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::openalias::OpenAliasResolution -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::openalias::OpenAliasResolution +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxOutput {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxOutput { - fn into_into_dart(self) -> crate::api::openalias::OpenAliasResolution { + fn into_into_dart(self) -> crate::api::account::TxOutput { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::PaymentOptions { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlan { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.src_pools.into_into_dart().into_dart(), - self.recipient_pays_fee.into_into_dart().into_dart(), - self.smart_transparent.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.inputs.into_into_dart().into_dart(), + self.outputs.into_into_dart().into_dart(), + self.fee.into_into_dart().into_dart(), + self.can_sign.into_into_dart().into_dart(), + self.can_broadcast.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::pay::PaymentOptions -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::PaymentOptions -{ - fn into_into_dart(self) -> crate::api::pay::PaymentOptions { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlan {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlan { + fn into_into_dart(self) -> crate::pay::TxPlan { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::PcztPackage { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanIn { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pczt.into_into_dart().into_dart(), - self.n_spends.into_into_dart().into_dart(), - self.sapling_indices.into_into_dart().into_dart(), - self.orchard_indices.into_into_dart().into_dart(), - self.ironwood_indices.into_into_dart().into_dart(), - self.can_sign.into_into_dart().into_dart(), - self.can_broadcast.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.is_issuance.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::PcztPackage {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::PcztPackage -{ - fn into_into_dart(self) -> crate::api::pay::PcztPackage { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanIn {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanIn { + fn into_into_dart(self) -> crate::pay::TxPlanIn { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::plugin::PluginInfo { +impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanOut { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.version.into_into_dart().into_dart(), - self.author.into_into_dart().into_dart(), - self.description.into_into_dart().into_dart(), - self.enabled.into_into_dart().into_dart(), - self.types.into_into_dart().into_dart(), - self.memo_prefixes.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.amount.into_into_dart().into_dart(), + self.address.into_into_dart().into_dart(), + self.asset_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::plugin::PluginInfo -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::plugin::PluginInfo -{ - fn into_into_dart(self) -> crate::api::plugin::PluginInfo { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanOut {} +impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanOut { + fn into_into_dart(self) -> crate::pay::TxPlanOut { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sync::PoolBalance { +impl flutter_rust_bridge::IntoDart for crate::api::account::TxSpend { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.0.into_into_dart().into_dart()].into_dart() + [ + self.id.into_into_dart().into_dart(), + self.pool.into_into_dart().into_dart(), + self.height.into_into_dart().into_dart(), + self.value.into_into_dart().into_dart(), + self.id_asset.into_into_dart().into_dart(), + self.asset_display.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::sync::PoolBalance {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sync::PoolBalance +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxSpend {} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::account::TxSpend { - fn into_into_dart(self) -> crate::api::sync::PoolBalance { + fn into_into_dart(self) -> crate::api::account::TxSpend { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::raptor::RaptorQParams { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingBallotIntent { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.version.into_into_dart().into_dart(), - self.ec_level.into_into_dart().into_dart(), - self.repair.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.skipped.into_into_dart().into_dart(), + self.choice.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::raptor::RaptorQParams + for crate::api::voting::VotingBallotIntent { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::raptor::RaptorQParams +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingBallotIntent { - fn into_into_dart(self) -> crate::api::raptor::RaptorQParams { + fn into_into_dart(self) -> crate::api::voting::VotingBallotIntent { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::openalias::RawOpenAliasResolution { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingChainResponse { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.records.into_into_dart().into_dart(), - self.dnssec_status.into_into_dart().into_dart(), + self.status_code.into_into_dart().into_dart(), + self.body.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::openalias::RawOpenAliasResolution + for crate::api::voting::VotingChainResponse { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::openalias::RawOpenAliasResolution +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingChainResponse { - fn into_into_dart(self) -> crate::api::openalias::RawOpenAliasResolution { + fn into_into_dart(self) -> crate::api::voting::VotingChainResponse { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Receivers { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingCompletedVoteChoice { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.taddr.into_into_dart().into_dart(), - self.saddr.into_into_dart().into_dart(), - self.oaddr.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.choice.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::Receivers + for crate::api::voting::VotingCompletedVoteChoice { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::Receivers +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingCompletedVoteChoice { - fn into_into_dart(self) -> crate::api::account::Receivers { + fn into_into_dart(self) -> crate::api::voting::VotingCompletedVoteChoice { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::Recipient { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingCompletedVoteDisplay { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.address.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.pools.into_into_dart().into_dart(), - self.user_memo.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.asset_base.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.choices.into_into_dart().into_dart(), + self.voted_at.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::Recipient {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::Recipient { - fn into_into_dart(self) -> crate::pay::Recipient { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingCompletedVoteDisplay +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingCompletedVoteDisplay +{ + fn into_into_dart(self) -> crate::api::voting::VotingCompletedVoteDisplay { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::vault::RestoredAccount { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingConfig { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.timestamp.into_into_dart().into_dart(), - self.name.into_into_dart().into_dart(), - self.seed.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), - self.use_internal.into_into_dart().into_dart(), - self.birth_height.into_into_dart().into_dart(), + self.source.into_into_dart().into_dart(), + self.source_fingerprint.into_into_dart().into_dart(), + self.trusted_key_fingerprint.into_into_dart().into_dart(), + self.switch_kind.into_into_dart().into_dart(), + self.vote_servers.into_into_dart().into_dart(), + self.pir_servers.into_into_dart().into_dart(), + self.pir_layout.into_into_dart().into_dart(), + self.rounds.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::vault::RestoredAccount + for crate::api::voting::VotingConfig { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::vault::RestoredAccount +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingConfig { - fn into_into_dart(self) -> crate::api::vault::RestoredAccount { + fn into_into_dart(self) -> crate::api::voting::VotingConfig { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sapling::SaplingParamsStatus { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingConfigRound { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.downloaded.into_into_dart().into_dart()].into_dart() + [ + self.round_id.into_into_dart().into_dart(), + self.ea_pk.into_into_dart().into_dart(), + ] + .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::sapling::SaplingParamsStatus + for crate::api::voting::VotingConfigRound { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sapling::SaplingParamsStatus +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingConfigRound { - fn into_into_dart(self) -> crate::api::sapling::SaplingParamsStatus { + fn into_into_dart(self) -> crate::api::voting::VotingConfigRound { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Seed { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationBuild { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.mnemonic.into_into_dart().into_dart(), - self.phrase.into_into_dart().into_dart(), - self.aindex.into_into_dart().into_dart(), + self.submission.into_into_dart().into_dart(), + self.wire_json.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Seed {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Seed { - fn into_into_dart(self) -> crate::api::account::Seed { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingDelegationBuild +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationBuild +{ + fn into_into_dart(self) -> crate::api::voting::VotingDelegationBuild { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::pay::SigningEvent { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationConfirmation { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self { - crate::api::pay::SigningEvent::Progress(field0) => { - [0.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crate::api::pay::SigningEvent::Result(field0) => { - [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - _ => { - unimplemented!(""); - } - } + [ + self.tx_hash.into_into_dart().into_dart(), + self.van_leaf_position.into_into_dart().into_dart(), + ] + .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::pay::SigningEvent {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::pay::SigningEvent +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingDelegationConfirmation { - fn into_into_dart(self) -> crate::api::pay::SigningEvent { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationConfirmation +{ + fn into_into_dart(self) -> crate::api::voting::VotingDelegationConfirmation { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationProgress { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { match self { - crate::api::frost::SigningStatus::SendingCommitment => [0.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForCommitments => [1.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SendingSigningPackage => [2.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForSigningPackage => { + crate::api::voting::VotingDelegationProgress::SelectingNotes => { + [0.into_dart()].into_dart() + } + crate::api::voting::VotingDelegationProgress::PcztBuilding => { + [1.into_dart()].into_dart() + } + crate::api::voting::VotingDelegationProgress::PcztBuilt => [2.into_dart()].into_dart(), + crate::api::voting::VotingDelegationProgress::ProofStarting => { [3.into_dart()].into_dart() } - crate::api::frost::SigningStatus::SendingSignatureShare => [4.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SigningCompleted => [5.into_dart()].into_dart(), - crate::api::frost::SigningStatus::WaitingForSignatureShares => { + crate::api::voting::VotingDelegationProgress::ProofProgress { progress } => { + [4.into_dart(), progress.into_into_dart().into_dart()].into_dart() + } + crate::api::voting::VotingDelegationProgress::ProofComplete => { + [5.into_dart()].into_dart() + } + crate::api::voting::VotingDelegationProgress::SigningPayload => { [6.into_dart()].into_dart() } - crate::api::frost::SigningStatus::PreparingTransaction => [7.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SendingTransaction => [8.into_dart()].into_dart(), - crate::api::frost::SigningStatus::TransactionSent(field0) => { - [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() + crate::api::voting::VotingDelegationProgress::PayloadReady => { + [7.into_dart()].into_dart() } _ => { unimplemented!(""); @@ -10984,457 +13865,463 @@ impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { } } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::frost::SigningStatus -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::frost::SigningStatus -{ - fn into_into_dart(self) -> crate::api::frost::SigningStatus { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::io::SyncHeight { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - ] - .into_dart() - } +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingDelegationProgress +{ } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::io::SyncHeight {} -impl flutter_rust_bridge::IntoIntoDart for crate::io::SyncHeight { - fn into_into_dart(self) -> crate::io::SyncHeight { +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationProgress +{ + fn into_into_dart(self) -> crate::api::voting::VotingDelegationProgress { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::sync::SyncProgress { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationRecovery { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), + self.workflow_phase.into_into_dart().into_dart(), + self.tx_hash.into_into_dart().into_dart(), + self.van_leaf_position.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::sync::SyncProgress + for crate::api::voting::VotingDelegationRecovery { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::sync::SyncProgress +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationRecovery { - fn into_into_dart(self) -> crate::api::sync::SyncProgress { + fn into_into_dart(self) -> crate::api::voting::VotingDelegationRecovery { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TAddressTxCount { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSetup { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.dindex.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.tx_count.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), + self.pczt_bytes.into_into_dart().into_dart(), + self.pczt_sighash.into_into_dart().into_dart(), + self.rk.into_into_dart().into_dart(), + self.action_index.into_into_dart().into_dart(), + self.action_bytes.into_into_dart().into_dart(), + self.tx1_effects.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::TAddressTxCount + for crate::api::voting::VotingDelegationSetup { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TAddressTxCount +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationSetup { - fn into_into_dart(self) -> crate::api::account::TAddressTxCount { + fn into_into_dart(self) -> crate::api::voting::VotingDelegationSetup { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::Tx { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationStatus { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.txid.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.tpe.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.zsa_value.into_into_dart().into_dart(), - self.asset_id.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.is_user_memo.into_into_dart().into_dart(), - self.contact_name.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), + self.tx_hash.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::Tx {} -impl flutter_rust_bridge::IntoIntoDart for crate::api::account::Tx { - fn into_into_dart(self) -> crate::api::account::Tx { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingDelegationStatus +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationStatus +{ + fn into_into_dart(self) -> crate::api::voting::VotingDelegationStatus { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxAccount { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSubmission { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.account.into_into_dart().into_dart(), - self.txid.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.time.into_into_dart().into_dart(), - self.price.into_into_dart().into_dart(), - self.category.into_into_dart().into_dart(), - self.notes.into_into_dart().into_dart(), - self.spends.into_into_dart().into_dart(), - self.outputs.into_into_dart().into_dart(), - self.memos.into_into_dart().into_dart(), - self.user_memo.into_into_dart().into_dart(), + self.proof.into_into_dart().into_dart(), + self.rk.into_into_dart().into_dart(), + self.nf_signed.into_into_dart().into_dart(), + self.cmx_new.into_into_dart().into_dart(), + self.gov_comm.into_into_dart().into_dart(), + self.gov_nullifiers.into_into_dart().into_dart(), + self.alpha.into_into_dart().into_dart(), + self.vote_round_id.into_into_dart().into_dart(), + self.spend_auth_sig.into_into_dart().into_dart(), + self.sighash.into_into_dart().into_dart(), + self.tx1_effects.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::account::TxAccount + for crate::api::voting::VotingDelegationSubmission { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxAccount +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingDelegationSubmission { - fn into_into_dart(self) -> crate::api::account::TxAccount { + fn into_into_dart(self) -> crate::api::voting::VotingDelegationSubmission { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxMemo { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingEncryptedShare { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.note.into_into_dart().into_dart(), - self.output.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.memo_bytes.into_into_dart().into_dart(), + self.c1.into_into_dart().into_dart(), + self.c2.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxMemo {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxMemo +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingEncryptedShare { - fn into_into_dart(self) -> crate::api::account::TxMemo { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingEncryptedShare +{ + fn into_into_dart(self) -> crate::api::voting::VotingEncryptedShare { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxNote { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingNextStep { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.tx.into_into_dart().into_dart(), - self.scope.into_into_dart().into_dart(), - self.diversifier.into_into_dart().into_dart(), - self.diversifier_index.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.locked.into_into_dart().into_dart(), - self.memo.into_into_dart().into_dart(), - self.id_asset.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), + self.kind.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.choice.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxNote {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxNote +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingNextStep { - fn into_into_dart(self) -> crate::api::account::TxNote { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingNextStep +{ + fn into_into_dart(self) -> crate::api::voting::VotingNextStep { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxOutput { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPirLayout { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.contact_name.into_into_dart().into_dart(), + self.pir_depth.into_into_dart().into_dart(), + self.tier0_layers.into_into_dart().into_dart(), + self.tier1_layers.into_into_dart().into_dart(), + self.poly_len.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxOutput {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxOutput +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingPirLayout { - fn into_into_dart(self) -> crate::api::account::TxOutput { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingPirLayout +{ + fn into_into_dart(self) -> crate::api::voting::VotingPirLayout { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlan { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPreparedInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.height.into_into_dart().into_dart(), - self.inputs.into_into_dart().into_dart(), - self.outputs.into_into_dart().into_dart(), - self.fee.into_into_dart().into_dart(), - self.can_sign.into_into_dart().into_dart(), - self.can_broadcast.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.eligible_weight_zatoshi.into_into_dart().into_dart(), + self.delegated_weight_zatoshi.into_into_dart().into_dart(), + self.round_name.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlan {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlan { - fn into_into_dart(self) -> crate::pay::TxPlan { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingPreparedInfo +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingPreparedInfo +{ + fn into_into_dart(self) -> crate::api::voting::VotingPreparedInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanIn { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingRoundInfo { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.network.into_into_dart().into_dart(), + self.snapshot_height.into_into_dart().into_dart(), + self.hotkey_address.into_into_dart().into_dart(), + self.eligible_weight_zatoshi.into_into_dart().into_dart(), + self.bundle_count.into_into_dart().into_dart(), + self.created_at.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanIn {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanIn { - fn into_into_dart(self) -> crate::pay::TxPlanIn { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingRoundInfo +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingRoundInfo +{ + fn into_into_dart(self) -> crate::api::voting::VotingRoundInfo { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::pay::TxPlanOut { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingRoundPlan { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pool.into_into_dart().into_dart(), - self.amount.into_into_dart().into_dart(), - self.address.into_into_dart().into_dart(), - self.asset_name.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.pending_recovery.into_into_dart().into_dart(), + self.next_steps.into_into_dart().into_dart(), + self.open_proposals.into_into_dart().into_dart(), + self.all_decided.into_into_dart().into_dart(), + self.delegation_statuses.into_into_dart().into_dart(), + self.blocking_recovery.into_into_dart().into_dart(), + self.blocking_share_work.into_into_dart().into_dart(), + self.hotkey_bound.into_into_dart().into_dart(), + self.completed_vote_artifact.into_into_dart().into_dart(), + self.completed_for_display.into_into_dart().into_dart(), + self.completed_vote_display.into_into_dart().into_dart(), + self.needs_draft_setup.into_into_dart().into_dart(), + self.primary_action.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::pay::TxPlanOut {} -impl flutter_rust_bridge::IntoIntoDart for crate::pay::TxPlanOut { - fn into_into_dart(self) -> crate::pay::TxPlanOut { +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingRoundPlan +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingRoundPlan +{ + fn into_into_dart(self) -> crate::api::voting::VotingRoundPlan { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::account::TxSpend { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingRoundRecovery { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.id.into_into_dart().into_dart(), - self.pool.into_into_dart().into_dart(), - self.height.into_into_dart().into_dart(), - self.value.into_into_dart().into_dart(), - self.id_asset.into_into_dart().into_dart(), - self.asset_display.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.bundle_count.into_into_dart().into_dart(), + self.delegation.into_into_dart().into_dart(), + self.votes.into_into_dart().into_dart(), + self.shares.into_into_dart().into_dart(), + self.share_delegations.into_into_dart().into_dart(), + self.unconfirmed_share_delegations + .into_into_dart() + .into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::account::TxSpend {} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::account::TxSpend +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingRoundRecovery { - fn into_into_dart(self) -> crate::api::account::TxSpend { +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingRoundRecovery +{ + fn into_into_dart(self) -> crate::api::voting::VotingRoundRecovery { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationConfirmation { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingServiceEndpoint { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.tx_hash.into_into_dart().into_dart(), - self.van_leaf_position.into_into_dart().into_dart(), + self.url.into_into_dart().into_dart(), + self.label.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingDelegationConfirmation + for crate::api::voting::VotingServiceEndpoint { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingDelegationConfirmation +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingServiceEndpoint { - fn into_into_dart(self) -> crate::api::voting::VotingDelegationConfirmation { + fn into_into_dart(self) -> crate::api::voting::VotingServiceEndpoint { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSetup { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingShareDelegationRecord { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pczt_bytes.into_into_dart().into_dart(), - self.pczt_sighash.into_into_dart().into_dart(), - self.rk.into_into_dart().into_dart(), - self.action_index.into_into_dart().into_dart(), - self.action_bytes.into_into_dart().into_dart(), - self.tx1_effects.into_into_dart().into_dart(), + self.round_id.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), + self.sent_to_urls.into_into_dart().into_dart(), + self.nullifier.into_into_dart().into_dart(), + self.confirmed.into_into_dart().into_dart(), + self.submit_at.into_into_dart().into_dart(), + self.created_at.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingDelegationSetup + for crate::api::voting::VotingShareDelegationRecord { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingDelegationSetup +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingShareDelegationRecord { - fn into_into_dart(self) -> crate::api::voting::VotingDelegationSetup { + fn into_into_dart(self) -> crate::api::voting::VotingShareDelegationRecord { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingDelegationSubmission { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSharePayload { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.proof.into_into_dart().into_dart(), - self.rk.into_into_dart().into_dart(), - self.nf_signed.into_into_dart().into_dart(), - self.cmx_new.into_into_dart().into_dart(), - self.gov_comm.into_into_dart().into_dart(), - self.gov_nullifiers.into_into_dart().into_dart(), - self.alpha.into_into_dart().into_dart(), - self.vote_round_id.into_into_dart().into_dart(), - self.spend_auth_sig.into_into_dart().into_dart(), - self.sighash.into_into_dart().into_dart(), - self.tx1_effects.into_into_dart().into_dart(), + self.shares_hash.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.vote_decision.into_into_dart().into_dart(), + self.enc_share.into_into_dart().into_dart(), + self.tree_position.into_into_dart().into_dart(), + self.all_enc_shares.into_into_dart().into_dart(), + self.share_comms.into_into_dart().into_dart(), + self.primary_blind.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingDelegationSubmission + for crate::api::voting::VotingSharePayload { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingDelegationSubmission +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingSharePayload { - fn into_into_dart(self) -> crate::api::voting::VotingDelegationSubmission { + fn into_into_dart(self) -> crate::api::voting::VotingSharePayload { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingEncryptedShare { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSharePlan { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.c1.into_into_dart().into_dart(), - self.c2.into_into_dart().into_dart(), - self.share_index.into_into_dart().into_dart(), + self.summary.into_into_dart().into_dart(), + self.next_tracking_delay_secs.into_into_dart().into_dart(), + self.last_moment.into_into_dart().into_dart(), + self.submissions.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingEncryptedShare + for crate::api::voting::VotingSharePlan { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingEncryptedShare +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingSharePlan { - fn into_into_dart(self) -> crate::api::voting::VotingEncryptedShare { + fn into_into_dart(self) -> crate::api::voting::VotingSharePlan { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPirLayout { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSharePlanItem { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.pir_depth.into_into_dart().into_dart(), - self.tier0_layers.into_into_dart().into_dart(), - self.tier1_layers.into_into_dart().into_dart(), - self.poly_len.into_into_dart().into_dart(), + self.submit_at.into_into_dart().into_dart(), + self.target_count.into_into_dart().into_dart(), + self.target_servers.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingPirLayout + for crate::api::voting::VotingSharePlanItem { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingPirLayout +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingSharePlanItem { - fn into_into_dart(self) -> crate::api::voting::VotingPirLayout { + fn into_into_dart(self) -> crate::api::voting::VotingSharePlanItem { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingPreparedInfo { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingShareTrackingSummary { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.round_id.into_into_dart().into_dart(), - self.bundle_index.into_into_dart().into_dart(), - self.eligible_weight_zatoshi.into_into_dart().into_dart(), - self.delegated_weight_zatoshi.into_into_dart().into_dart(), - self.round_name.into_into_dart().into_dart(), + self.total.into_into_dart().into_dart(), + self.confirmed.into_into_dart().into_dart(), + self.waiting.into_into_dart().into_dart(), + self.ready.into_into_dart().into_dart(), + self.overdue.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingPreparedInfo + for crate::api::voting::VotingShareTrackingSummary { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingPreparedInfo +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingShareTrackingSummary { - fn into_into_dart(self) -> crate::api::voting::VotingPreparedInfo { + fn into_into_dart(self) -> crate::api::voting::VotingShareTrackingSummary { self } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingSharePayload { +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingShareWorkflow { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.shares_hash.into_into_dart().into_dart(), + self.bundle_index.into_into_dart().into_dart(), self.proposal_id.into_into_dart().into_dart(), - self.vote_decision.into_into_dart().into_dart(), - self.enc_share.into_into_dart().into_dart(), - self.tree_position.into_into_dart().into_dart(), - self.all_enc_shares.into_into_dart().into_dart(), - self.share_comms.into_into_dart().into_dart(), - self.primary_blind.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), ] .into_dart() } } impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::voting::VotingSharePayload + for crate::api::voting::VotingShareWorkflow { } -impl flutter_rust_bridge::IntoIntoDart - for crate::api::voting::VotingSharePayload +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingShareWorkflow { - fn into_into_dart(self) -> crate::api::voting::VotingSharePayload { + fn into_into_dart(self) -> crate::api::voting::VotingShareWorkflow { self } } @@ -11491,6 +14378,65 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteCommitStage { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + match self { + crate::api::voting::VotingVoteCommitStage::ProofStarting { + proposal_id, + bundle_index, + } => [ + 0.into_dart(), + proposal_id.into_into_dart().into_dart(), + bundle_index.into_into_dart().into_dart(), + ] + .into_dart(), + crate::api::voting::VotingVoteCommitStage::ProofProgress { + proposal_id, + bundle_index, + progress, + } => [ + 1.into_dart(), + proposal_id.into_into_dart().into_dart(), + bundle_index.into_into_dart().into_dart(), + progress.into_into_dart().into_dart(), + ] + .into_dart(), + crate::api::voting::VotingVoteCommitStage::SharePayloadsBuilding { + proposal_id, + bundle_index, + } => [ + 2.into_dart(), + proposal_id.into_into_dart().into_dart(), + bundle_index.into_into_dart().into_dart(), + ] + .into_dart(), + crate::api::voting::VotingVoteCommitStage::Signing { + proposal_id, + bundle_index, + } => [ + 3.into_dart(), + proposal_id.into_into_dart().into_dart(), + bundle_index.into_into_dart().into_dart(), + ] + .into_dart(), + _ => { + unimplemented!(""); + } + } + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVoteCommitStage +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVoteCommitStage +{ + fn into_into_dart(self) -> crate::api::voting::VotingVoteCommitStage { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteCommitments { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -11555,6 +14501,33 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteRecovery { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.bundle_index.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.choice.into_into_dart().into_dart(), + self.phase.into_into_dart().into_dart(), + self.workflow_phase.into_into_dart().into_dart(), + self.tx_hash.into_into_dart().into_dart(), + self.vc_tree_position.into_into_dart().into_dart(), + self.has_commitment_bundle.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingVoteRecovery +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::voting::VotingVoteRecovery +{ + fn into_into_dart(self) -> crate::api::voting::VotingVoteRecovery { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVoteSubmission { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -11764,6 +14737,30 @@ impl SseEncode } } +impl SseEncode + for StreamSink< + crate::api::voting::VotingDelegationProgress, + flutter_rust_bridge::for_generated::SseCodec, + > +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + unimplemented!("") + } +} + +impl SseEncode + for StreamSink< + crate::api::voting::VotingVoteCommitStage, + flutter_rust_bridge::for_generated::SseCodec, + > +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + unimplemented!("") + } +} + impl SseEncode for String { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -12146,187 +15143,307 @@ impl SseEncode for Vec { fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec<(String, f64, bool)> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + <(String, f64, bool)>::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec<(u32, f64)> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + <(u32, f64)>::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec<(String, f64, bool)> { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - <(String, f64, bool)>::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec<(u32, f64)> { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - <(u32, f64)>::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } -impl SseEncode for Vec { +impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { ::sse_encode(self.len() as _, serializer); for item in self { - ::sse_encode(item, serializer); + ::sse_encode(item, serializer); } } } @@ -12628,6 +15745,36 @@ impl SseEncode for Option { } } +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + impl SseEncode for Option> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13059,6 +16206,69 @@ impl SseEncode for [usize; 4] { } } +impl SseEncode for crate::api::voting::VotingBallotIntent { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.skipped, serializer); + >::sse_encode(self.choice, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingChainResponse { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.status_code, serializer); + ::sse_encode(self.body, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingCompletedVoteChoice { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.proposal_id, serializer); + >::sse_encode(self.choice, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingCompletedVoteDisplay { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.choices, serializer); + >::sse_encode(self.voted_at, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingConfig { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.source, serializer); + ::sse_encode(self.source_fingerprint, serializer); + ::sse_encode(self.trusted_key_fingerprint, serializer); + ::sse_encode(self.switch_kind, serializer); + >::sse_encode(self.vote_servers, serializer); + >::sse_encode(self.pir_servers, serializer); + >::sse_encode(self.pir_layout, serializer); + >::sse_encode(self.rounds, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingConfigRound { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + >::sse_encode(self.ea_pk, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingDelegationBuild { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.submission, serializer); + ::sse_encode(self.wire_json, serializer); + } +} + impl SseEncode for crate::api::voting::VotingDelegationConfirmation { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13067,6 +16277,53 @@ impl SseEncode for crate::api::voting::VotingDelegationConfirmation { } } +impl SseEncode for crate::api::voting::VotingDelegationProgress { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + match self { + crate::api::voting::VotingDelegationProgress::SelectingNotes => { + ::sse_encode(0, serializer); + } + crate::api::voting::VotingDelegationProgress::PcztBuilding => { + ::sse_encode(1, serializer); + } + crate::api::voting::VotingDelegationProgress::PcztBuilt => { + ::sse_encode(2, serializer); + } + crate::api::voting::VotingDelegationProgress::ProofStarting => { + ::sse_encode(3, serializer); + } + crate::api::voting::VotingDelegationProgress::ProofProgress { progress } => { + ::sse_encode(4, serializer); + ::sse_encode(progress, serializer); + } + crate::api::voting::VotingDelegationProgress::ProofComplete => { + ::sse_encode(5, serializer); + } + crate::api::voting::VotingDelegationProgress::SigningPayload => { + ::sse_encode(6, serializer); + } + crate::api::voting::VotingDelegationProgress::PayloadReady => { + ::sse_encode(7, serializer); + } + _ => { + unimplemented!(""); + } + } + } +} + +impl SseEncode for crate::api::voting::VotingDelegationRecovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.phase, serializer); + ::sse_encode(self.workflow_phase, serializer); + >::sse_encode(self.tx_hash, serializer); + >::sse_encode(self.van_leaf_position, serializer); + } +} + impl SseEncode for crate::api::voting::VotingDelegationSetup { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13079,6 +16336,15 @@ impl SseEncode for crate::api::voting::VotingDelegationSetup { } } +impl SseEncode for crate::api::voting::VotingDelegationStatus { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.phase, serializer); + >::sse_encode(self.tx_hash, serializer); + } +} + impl SseEncode for crate::api::voting::VotingDelegationSubmission { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13105,6 +16371,17 @@ impl SseEncode for crate::api::voting::VotingEncryptedShare { } } +impl SseEncode for crate::api::voting::VotingNextStep { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.kind, serializer); + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.choice, serializer); + ::sse_encode(self.share_index, serializer); + } +} + impl SseEncode for crate::api::voting::VotingPirLayout { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13126,6 +16403,90 @@ impl SseEncode for crate::api::voting::VotingPreparedInfo { } } +impl SseEncode for crate::api::voting::VotingRoundInfo { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + ::sse_encode(self.network, serializer); + ::sse_encode(self.snapshot_height, serializer); + >::sse_encode(self.hotkey_address, serializer); + >::sse_encode(self.eligible_weight_zatoshi, serializer); + ::sse_encode(self.bundle_count, serializer); + ::sse_encode(self.created_at, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingRoundPlan { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + ::sse_encode(self.pending_recovery, serializer); + >::sse_encode(self.next_steps, serializer); + >::sse_encode(self.open_proposals, serializer); + ::sse_encode(self.all_decided, serializer); + >::sse_encode( + self.delegation_statuses, + serializer, + ); + ::sse_encode(self.blocking_recovery, serializer); + ::sse_encode(self.blocking_share_work, serializer); + ::sse_encode(self.hotkey_bound, serializer); + ::sse_encode(self.completed_vote_artifact, serializer); + ::sse_encode(self.completed_for_display, serializer); + >::sse_encode( + self.completed_vote_display, + serializer, + ); + ::sse_encode(self.needs_draft_setup, serializer); + ::sse_encode(self.primary_action, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingRoundRecovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + ::sse_encode(self.bundle_count, serializer); + >::sse_encode( + self.delegation, + serializer, + ); + >::sse_encode(self.votes, serializer); + >::sse_encode(self.shares, serializer); + >::sse_encode( + self.share_delegations, + serializer, + ); + >::sse_encode( + self.unconfirmed_share_delegations, + serializer, + ); + } +} + +impl SseEncode for crate::api::voting::VotingServiceEndpoint { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.url, serializer); + ::sse_encode(self.label, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingShareDelegationRecord { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.round_id, serializer); + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.share_index, serializer); + >::sse_encode(self.sent_to_urls, serializer); + >::sse_encode(self.nullifier, serializer); + ::sse_encode(self.confirmed, serializer); + ::sse_encode(self.submit_at, serializer); + ::sse_encode(self.created_at, serializer); + } +} + impl SseEncode for crate::api::voting::VotingSharePayload { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13143,6 +16504,46 @@ impl SseEncode for crate::api::voting::VotingSharePayload { } } +impl SseEncode for crate::api::voting::VotingSharePlan { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.summary, serializer); + >::sse_encode(self.next_tracking_delay_secs, serializer); + ::sse_encode(self.last_moment, serializer); + >::sse_encode(self.submissions, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingSharePlanItem { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.submit_at, serializer); + ::sse_encode(self.target_count, serializer); + >::sse_encode(self.target_servers, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingShareTrackingSummary { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.total, serializer); + ::sse_encode(self.confirmed, serializer); + ::sse_encode(self.waiting, serializer); + ::sse_encode(self.ready, serializer); + ::sse_encode(self.overdue, serializer); + } +} + +impl SseEncode for crate::api::voting::VotingShareWorkflow { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.share_index, serializer); + ::sse_encode(self.phase, serializer); + } +} + impl SseEncode for crate::api::voting::VotingSignedVoteCommitment { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13169,6 +16570,51 @@ impl SseEncode for crate::api::voting::VotingVanWitness { } } +impl SseEncode for crate::api::voting::VotingVoteCommitStage { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + match self { + crate::api::voting::VotingVoteCommitStage::ProofStarting { + proposal_id, + bundle_index, + } => { + ::sse_encode(0, serializer); + ::sse_encode(proposal_id, serializer); + ::sse_encode(bundle_index, serializer); + } + crate::api::voting::VotingVoteCommitStage::ProofProgress { + proposal_id, + bundle_index, + progress, + } => { + ::sse_encode(1, serializer); + ::sse_encode(proposal_id, serializer); + ::sse_encode(bundle_index, serializer); + ::sse_encode(progress, serializer); + } + crate::api::voting::VotingVoteCommitStage::SharePayloadsBuilding { + proposal_id, + bundle_index, + } => { + ::sse_encode(2, serializer); + ::sse_encode(proposal_id, serializer); + ::sse_encode(bundle_index, serializer); + } + crate::api::voting::VotingVoteCommitStage::Signing { + proposal_id, + bundle_index, + } => { + ::sse_encode(3, serializer); + ::sse_encode(proposal_id, serializer); + ::sse_encode(bundle_index, serializer); + } + _ => { + unimplemented!(""); + } + } + } +} + impl SseEncode for crate::api::voting::VotingVoteCommitments { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -13197,6 +16643,20 @@ impl SseEncode for crate::api::voting::VotingVotePayloads { } } +impl SseEncode for crate::api::voting::VotingVoteRecovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.bundle_index, serializer); + ::sse_encode(self.proposal_id, serializer); + ::sse_encode(self.choice, serializer); + ::sse_encode(self.phase, serializer); + ::sse_encode(self.workflow_phase, serializer); + >::sse_encode(self.tx_hash, serializer); + >::sse_encode(self.vc_tree_position, serializer); + ::sse_encode(self.has_commitment_bundle, serializer); + } +} + impl SseEncode for crate::api::voting::VotingVoteSubmission { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { diff --git a/rust/src/net/mod.rs b/rust/src/net/mod.rs index dbecc09d6..e9fddf0e0 100644 --- a/rust/src/net/mod.rs +++ b/rust/src/net/mod.rs @@ -9,6 +9,7 @@ use crate::{api::coin::Network, lwd::*}; pub mod lwd; pub mod nym; pub mod nym_service; +pub mod votechain; pub mod zebra; #[async_trait] diff --git a/rust/src/net/votechain.rs b/rust/src/net/votechain.rs new file mode 100644 index 000000000..b97c066a4 --- /dev/null +++ b/rust/src/net/votechain.rs @@ -0,0 +1,142 @@ +//! Minimal REST client for the vote-sdk `/shielded-vote/v1` API surface. +//! +//! Chain-facing calls use the configured vote server base URL; helper-server +//! share calls take an explicit server URL because foreground submission and +//! recovery may target different helper subsets over time. +//! +//! JSON envelopes are returned as raw bodies — the vote-sdk schema is still +//! evolving and the Dart UI parses leniently (mirroring vizor's client). +//! HTTP status is preserved for 2xx, 404, and 422 (422 = deterministic chain +//! rejection whose body is a `VotingTxResult`), so the UI can distinguish a +//! rejection from a transport error; only network failures produce `Err`. + +use anyhow::{anyhow, Result}; +use std::time::Duration; + +/// Returns the status code and body of a GET, without erroring on 404. +async fn get(base_url: &str, path: &str, proxy: &str) -> Result<(u16, String)> { + let url = endpoint(base_url, path)?; + let response = client(proxy, Duration::from_secs(15))? + .get(&url) + .send() + .await + .map_err(|e| anyhow!("vote chain GET {url}: {e}"))?; + let status = response.status().as_u16(); + let body = response.text().await?; + if status != 404 && (status < 200 || status >= 300) { + return Err(anyhow!("vote chain GET {url}: HTTP {status}: {body}")); + } + Ok((status, body)) +} + +/// Returns the status code and body of a POST, without erroring on 422 +/// (deterministic chain rejection). +async fn post(base_url: &str, path: &str, body_json: &str, proxy: &str) -> Result<(u16, String)> { + let url = endpoint(base_url, path)?; + let response = client(proxy, Duration::from_secs(60))? + .post(&url) + .header("content-type", "application/json") + .body(body_json.to_string()) + .send() + .await + .map_err(|e| anyhow!("vote chain POST {url}: {e}"))?; + let status = response.status().as_u16(); + let body = response.text().await?; + if status != 422 && (status < 200 || status >= 300) { + return Err(anyhow!("vote chain POST {url}: HTTP {status}: {body}")); + } + Ok((status, body)) +} + +/// Builds a `/shielded-vote/v1/...` URL under `base_url`. +fn endpoint(base_url: &str, path: &str) -> Result { + let base = base_url.trim_end_matches('/'); + Ok(format!("{base}/shielded-vote/v1/{path}")) +} + +fn client(proxy: &str, timeout: Duration) -> Result { + let mut builder = reqwest::Client::builder() + .user_agent("zkool/1.0") + .timeout(timeout); + if !proxy.is_empty() { + builder = builder.proxy(reqwest::Proxy::all(proxy)?); + } + Ok(builder.build()?) +} + +/// Lists rounds from the vote server. Current vote-sdk returns +/// `{ "rounds": [...] }`; an empty `{}` means no rounds. +pub async fn list_rounds(base_url: &str, proxy: &str) -> Result<(u16, String)> { + get(base_url, "rounds", proxy).await +} + +/// Fetches one round's status (`{ "round": ... }` envelope). +pub async fn round_status(base_url: &str, round_id: &str, proxy: &str) -> Result<(u16, String)> { + get(base_url, &format!("round/{round_id}"), proxy).await +} + +/// Fetches the round tally envelope (`tally-results`). +pub async fn round_tally(base_url: &str, round_id: &str, proxy: &str) -> Result<(u16, String)> { + get(base_url, &format!("tally-results/{round_id}"), proxy).await +} + +/// Broadcasts a delegation transaction to the vote chain. +pub async fn submit_delegation( + base_url: &str, + submission_json: &str, + proxy: &str, +) -> Result<(u16, String)> { + post(base_url, "delegate-vote", submission_json, proxy).await +} + +/// Broadcasts a vote commitment transaction to the vote chain. +pub async fn submit_vote_commitment( + base_url: &str, + commitment_json: &str, + proxy: &str, +) -> Result<(u16, String)> { + post(base_url, "cast-vote", commitment_json, proxy).await +} + +/// Fetches the on-chain confirmation for a transaction; 404 = not confirmed. +pub async fn tx_confirmation( + base_url: &str, + tx_hash: &str, + proxy: &str, +) -> Result<(u16, String)> { + get(base_url, &format!("tx/{tx_hash}"), proxy).await +} + +/// Posts one encrypted share to a helper server. The payload must already +/// carry the `vote_round_id` field required by the helper API. +pub async fn submit_share( + server_url: &str, + payload_json: &str, + proxy: &str, +) -> Result<(u16, String)> { + post(server_url, "shares", payload_json, proxy).await +} + +/// Checks whether a helper has confirmed a share identified by its nullifier. +pub async fn share_status( + server_url: &str, + round_id: &str, + share_id: &str, + proxy: &str, +) -> Result<(u16, String)> { + get(server_url, &format!("share-status/{round_id}/{share_id}"), proxy).await +} + +/// Fetches raw bytes from an arbitrary URL (voting config blobs). +pub async fn fetch_bytes(url: &str, proxy: &str) -> Result> { + let response = client(proxy, Duration::from_secs(15))? + .get(url) + .send() + .await + .map_err(|e| anyhow!("config fetch {url}: {e}"))?; + let status = response.status().as_u16(); + if status < 200 || status >= 300 { + return Err(anyhow!("config fetch {url}: HTTP {status}")); + } + Ok(response.bytes().await?.to_vec()) +} diff --git a/rust/src/voting.rs b/rust/src/voting.rs index d2f948201..ecde0e875 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -23,11 +23,12 @@ use zip32::AccountId; use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey}; use zcash_voting::prelude::{ confirm_delegation_submission, confirm_vote_submission, generate_random_voting_hotkey, - BundlePolicy, CommittedVote, DelegationConfirmation, DelegationKeys, DelegationSigningRequest, - DelegationSubmission, DraftVote, NoopProgressReporter, NoteInfo, - PrepareDelegationBundleWithInputsParams, PreparedDelegationBundle, PreparedSigner, SharePayload, - SignedVoteCommitments, TxEvent, VanWitness, VoteConfirmation, VoteSigner, VoteSubmission, - VotingDb, VotingHotkey, WitnessData, + BundlePolicy, CommittedVote, DelegationConfirmation, DelegationKeys, DelegationProgress, + DelegationProgressReporter, DelegationSigningRequest, DelegationSubmission, DraftVote, + NoopProgressReporter, NoteInfo, PrepareDelegationBundleWithInputsParams, + PreparedDelegationBundle, PreparedSigner, SharePayload, SignedVoteCommitments, TxEvent, + VanWitness, VoteCommitStageReporter, VoteConfirmation, VoteSigner, VoteSubmission, VotingDb, + VotingHotkey, WitnessData, }; use zcash_voting::{Network as VotingNetwork, VotingRoundParams}; @@ -115,6 +116,94 @@ pub async fn voting_hotkey_load( Ok(VotingHotkey::from_stored_secret(&secret, network)?) } +/// Persists the round inputs needed to re-run [`prepare_delegation_bundle`] +/// after a restart (the prepared-bundle cache is process-local only). +pub async fn save_round_config( + connection: &mut SqliteConnection, + round_id: &str, + round_params_json: &str, + round_name: &str, + max_real_notes_per_bundle: Option, + lightwalletd_url: &str, +) -> Result<()> { + crate::db::put_prop( + connection, + &format!("voting_round_params:{round_id}"), + round_params_json, + ) + .await?; + crate::db::put_prop( + connection, + &format!("voting_round_name:{round_id}"), + round_name, + ) + .await?; + crate::db::put_prop( + connection, + &format!("voting_round_lwd:{round_id}"), + lightwalletd_url, + ) + .await?; + if let Some(n) = max_real_notes_per_bundle { + crate::db::put_prop( + connection, + &format!("voting_round_bundle_policy:{round_id}"), + &n.to_string(), + ) + .await?; + } + Ok(()) +} + +/// Loads the round config persisted by [`save_round_config`]. +pub async fn load_round_config( + connection: &mut SqliteConnection, + round_id: &str, +) -> Result<(String, String, Option, String)> { + let params = crate::db::get_prop(connection, &format!("voting_round_params:{round_id}")) + .await? + .ok_or_else(|| { + anyhow!("no saved voting config for round {round_id}; run delegation_prepare first") + })?; + let name = crate::db::get_prop(connection, &format!("voting_round_name:{round_id}")) + .await? + .ok_or_else(|| anyhow!("no saved voting round name for round {round_id}"))?; + let lwd = crate::db::get_prop(connection, &format!("voting_round_lwd:{round_id}")) + .await? + .ok_or_else(|| anyhow!("no saved lightwalletd URL for round {round_id}"))?; + let policy = crate::db::get_prop( + connection, + &format!("voting_round_bundle_policy:{round_id}"), + ) + .await? + .and_then(|s| s.parse::().ok()); + Ok((params, name, policy, lwd)) +} + +/// Persists the PIR layout used to build a round's delegation payload, so the +/// proving step can resume after a restart without re-reading the chain config. +pub async fn save_pir_layout( + connection: &mut SqliteConnection, + round_id: &str, + pir_layout: &zcash_voting::config::PirLayout, +) -> Result<()> { + let json = serde_json::to_string(pir_layout)?; + crate::db::put_prop(connection, &format!("voting_round_pir:{round_id}"), &json).await +} + +/// Loads the PIR layout persisted by [`save_pir_layout`]. +pub async fn load_pir_layout( + connection: &mut SqliteConnection, + round_id: &str, +) -> Result> { + let Some(json) = + crate::db::get_prop(connection, &format!("voting_round_pir:{round_id}")).await? + else { + return Ok(None); + }; + Ok(Some(serde_json::from_str(&json)?)) +} + /// Resolves lightwalletd-derived delegation inputs for a voting round. pub async fn gather_lwd_inputs( lightwalletd_url: &str, @@ -378,12 +467,40 @@ pub async fn prove_and_submit_delegation( pczt_bytes: Vec, pir_layout: zcash_voting::config::PirLayout, pir_server_url: &str, -) -> Result { +) -> Result<(DelegationSubmission, String)> { + prove_and_submit_delegation_with_progress( + pool, + wallet_id, + prepared, + seed, + pczt_bytes, + pir_layout, + pir_server_url, + &NoopProgressReporter, + ) + .await +} + +/// [`prove_and_submit_delegation`] with a live progress reporter. The library +/// emits the PCZT/proof stages; the host emits `SigningPayload` and +/// `PayloadReady` bookends around signing and assembly. Returns the +/// submission together with its vote-chain wire JSON body. +#[allow(clippy::too_many_arguments)] +pub async fn prove_and_submit_delegation_with_progress( + pool: SqlitePool, + wallet_id: &str, + prepared: &PreparedDelegationBundle, + seed: &[u8], + pczt_bytes: Vec, + pir_layout: zcash_voting::config::PirLayout, + pir_server_url: &str, + progress: &dyn DelegationProgressReporter, +) -> Result<(DelegationSubmission, String)> { let db = open_voting_db(pool, wallet_id).await?; - let progress = NoopProgressReporter; - let _setup = prepared.setup(&db, &progress).await?; + let _setup = prepared.setup(&db, progress).await?; let request = prepared.signing_request(&db).await?; + progress.on_progress(DelegationProgress::SigningPayload); let (sig, sighash) = sign_delegation_request(seed, request)?; let pir_client = zcash_voting::connect_pir_blocking( @@ -391,12 +508,16 @@ pub async fn prove_and_submit_delegation( pir_server_url, Arc::new(zcash_voting::HyperTransport::new()), )?; - prepared.prove(&db, &pir_client, &progress).await?; + prepared.prove(&db, &pir_client, progress).await?; let bundle = prepared .signed_bundle(&db, pczt_bytes, PreparedSigner::signature(sig, sighash)) .await?; - Ok(bundle.submission) + progress.on_progress(DelegationProgress::PayloadReady); + + let wire = zcash_voting::wire::DelegationSubmissionWire::try_from(&bundle.submission)?; + let wire_json = wire.to_json()?; + Ok((bundle.submission, wire_json)) } /// Records a confirmed delegation transaction (persists the bundle's public @@ -451,6 +572,32 @@ pub async fn commit_votes( drafts: &[DraftVote], witness: &VanWitness, hotkey: &VotingHotkey, +) -> Result { + commit_votes_with_progress( + pool, + wallet_id, + round_id, + bundle_index, + drafts, + witness, + hotkey, + &NoopProgressReporter, + ) + .await +} + +/// [`commit_votes`] with a live stage reporter (proof / share-payload / +/// signing stages per proposal). +#[allow(clippy::too_many_arguments)] +pub async fn commit_votes_with_progress( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + drafts: &[DraftVote], + witness: &VanWitness, + hotkey: &VotingHotkey, + stages: &dyn VoteCommitStageReporter, ) -> Result { let db = open_voting_db(pool, wallet_id).await?; Ok(zcash_voting::prelude::commit_batch( @@ -460,7 +607,7 @@ pub async fn commit_votes( drafts, witness, VoteSigner::hotkey(hotkey), - &NoopProgressReporter, + stages, ) .await?) } @@ -482,6 +629,55 @@ pub async fn vote_payloads( )) } +/// Reconstructs the chain-ready wire JSON for a committed vote. +pub async fn vote_wire_json( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + proposal_id: u32, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; + let signed = committed.signed_commitment(&db).await?; + Ok(zcash_voting::wire::VoteCommitmentWire::try_from(&signed)?.to_json()?) +} + +/// Reconstructs one helper-share payload as helper wire JSON from the +/// persisted commitment bundle. +pub async fn share_wire_json( + pool: SqlitePool, + wallet_id: &str, + round_id: &str, + bundle_index: u32, + proposal_id: u32, + share_index: u32, + vc_tree_position: Option, + submit_at: u64, +) -> Result { + let db = open_voting_db(pool, wallet_id).await?; + let bundle = zcash_voting::recovery::recoverable_commitment_bundle( + &db, + round_id, + bundle_index, + proposal_id, + ) + .await? + .ok_or_else(|| { + anyhow!( + "commitment bundle not found for round {round_id} bundle {bundle_index} proposal {proposal_id}" + ) + })?; + let position = vc_tree_position.unwrap_or(bundle.vc_tree_position); + Ok(zcash_voting::share::recover_wire_json( + &bundle.commitment_bundle_json, + proposal_id, + share_index, + position, + submit_at, + )?) +} + /// Records successful vote-chain and helper-share submissions for one vote. pub async fn record_vote_execution( pool: SqlitePool, From 15732302d4ea72dbfd357bf919515ee292659868 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 16:50:32 +0800 Subject: [PATCH 064/189] ci: run rust tests on PRs and pushes to main --- .github/workflows/test-rust.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/test-rust.yml diff --git a/.github/workflows/test-rust.yml b/.github/workflows/test-rust.yml new file mode 100644 index 000000000..db8dd3018 --- /dev/null +++ b/.github/workflows/test-rust.yml @@ -0,0 +1,28 @@ +name: Test Rust + +on: + workflow_dispatch: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + test: + if: ${{ !startsWith(github.head_ref, 'release-please--branches--') }} + runs-on: ubuntu-latest + steps: + - name: Install RUST + uses: dtolnay/rust-toolchain@stable + - name: Checkout code + uses: actions/checkout@v6 + - name: Cache cargo artifacts + uses: Swatinem/rust-cache@v2 + with: + workspaces: rust + - name: Run tests + run: | + cd rust + cargo test --lib From da834b2d32ec0b847220682634919d9d24a3a0d4 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 17:08:28 +0800 Subject: [PATCH 065/189] refactor: pass memo explicitly to plugin process_memo Replace the global CURRENT_MEMO buffer with a Memo value passed as a process_memo(memo) argument. Fixes the cross-thread race that made the rhai plugin tests flaky under parallel test execution. --- rust/src/plugin/mod.rs | 23 ++- rust/src/plugin/rhai_api.rs | 314 +++++++++++++++++++----------------- tools/test_plugin/main.rhai | 6 +- 3 files changed, 180 insertions(+), 163 deletions(-) diff --git a/rust/src/plugin/mod.rs b/rust/src/plugin/mod.rs index 5723caa15..fd11f8a17 100644 --- a/rust/src/plugin/mod.rs +++ b/rust/src/plugin/mod.rs @@ -4,7 +4,7 @@ //! 1. **Install**: download archive → extract to `$DATADIR/plugins//` → validate manifest → //! create engine → compile script → call `get_prefixes()` → store in DB. //! 2. **Load (startup)**: read all enabled plugins from DB → compile AST → cache AST. -//! 3. **Dispatch**: given memo bytes, find plugins whose prefixes match → call `process_memo()`. +//! 3. **Dispatch**: given memo bytes, find plugins whose prefixes match → call `process_memo(memo)`. //! 4. **Remove**: delete plugin directory → remove DB row → evict AST cache. pub mod db; @@ -22,7 +22,7 @@ use std::sync::OnceLock; use crate::api::coin::Coin; use crate::plugin::db as plugin_db; use crate::plugin::rhai_api::{ - create_sandboxed_engine, extract_prefixes, extract_sections, with_memo_bytes, ParsedMemoCell, + create_sandboxed_engine, extract_prefixes, extract_sections, Memo, ParsedMemoCell, ParsedMemoSection, }; @@ -223,18 +223,17 @@ pub async fn parse_memo_with_plugins(c: &Coin, memo_bytes: &[u8]) -> Result(&mut Scope::new(), &ast, "process_memo", ()) { - Ok(result) => { - for section in extract_sections(result) { - sections.push(MemoSection::from(section)); - } - } - Err(e) => { - tracing::warn!("Plugin process_memo failed: {e}"); + let memo = Memo::new(payload.to_vec()); + match engine.call_fn::(&mut Scope::new(), &ast, "process_memo", (memo,)) { + Ok(result) => { + for section in extract_sections(result) { + sections.push(MemoSection::from(section)); } } - }); + Err(e) => { + tracing::warn!("Plugin process_memo failed: {e}"); + } + } } Ok(sections) diff --git a/rust/src/plugin/rhai_api.rs b/rust/src/plugin/rhai_api.rs index 6b65c7f87..62d9677f6 100644 --- a/rust/src/plugin/rhai_api.rs +++ b/rust/src/plugin/rhai_api.rs @@ -1,111 +1,101 @@ //! Rhai sandbox API exposed to plugin scripts. //! -//! Scripts call `memo::read_u8(offset)`, `cell_string("value")`, `section(...)`, etc. -//! The memo bytes are stored in a global `Mutex` before calling `process_memo` so the -//! `memo::*` functions can read from them implicitly. - -use rhai::{Dynamic, Engine, EvalAltResult, Module}; -use std::sync::{LazyLock, Mutex}; - -/// Global memo payload for the currently-executing script. -static CURRENT_MEMO: LazyLock>> = LazyLock::new(|| Mutex::new(Vec::new())); - -/// Set the memo bytes, execute a closure, then clear the bytes. -pub fn with_memo_bytes(bytes: &[u8], f: F) -> R -where - F: FnOnce() -> R, -{ - { - let mut guard = CURRENT_MEMO.lock().unwrap(); - *guard = bytes.to_vec(); - } - let result = f(); - { - let mut guard = CURRENT_MEMO.lock().unwrap(); - guard.clear(); - } - result +//! Scripts call `process_memo(memo)` where `memo` is a [`Memo`] value passed +//! explicitly by the host, and read it via methods like `memo.read_u8(offset)`, +//! `memo.read_string(offset, len)`, etc. The memo bytes are per-call state — +//! no globals. + +use rhai::{Blob, Dynamic, Engine, Scope}; + +/// Memo payload exposed to plugin scripts. +/// +/// Passed to `process_memo(memo)` as an argument. Provides the read methods +/// scripts use to decode the memo. +#[derive(Debug, Clone)] +pub struct Memo { + data: Blob, } -// ── memo module functions (fallible for Module::set_native_fn) ───────── - -type RhaiResult = Result>; +impl Memo { + pub fn new(data: Vec) -> Self { + Self { data: data.into() } + } -fn memo_len() -> RhaiResult { - Ok(CURRENT_MEMO.lock().unwrap().len() as i64) -} + fn len(&mut self) -> i64 { + self.data.len() as i64 + } -fn memo_read_u8(offset: i64) -> RhaiResult { - let idx = offset as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - Ok(if idx < guard.len() { - guard[idx] as i64 - } else { - 0 - }) -} + fn read_u8(&mut self, offset: i64) -> i64 { + let idx = offset as usize; + if idx < self.data.len() { + self.data[idx] as i64 + } else { + 0 + } + } -fn memo_read_u16_le(offset: i64) -> RhaiResult { - let idx = offset as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - Ok(if idx + 1 < guard.len() { - u16::from_le_bytes([guard[idx], guard[idx + 1]]) as i64 - } else { - 0 - }) -} + fn read_u16_le(&mut self, offset: i64) -> i64 { + let idx = offset as usize; + if idx + 1 < self.data.len() { + u16::from_le_bytes([self.data[idx], self.data[idx + 1]]) as i64 + } else { + 0 + } + } -fn memo_read_u32_le(offset: i64) -> RhaiResult { - let idx = offset as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - Ok(if idx + 3 < guard.len() { - u32::from_le_bytes([guard[idx], guard[idx + 1], guard[idx + 2], guard[idx + 3]]) as i64 - } else { - 0 - }) -} + fn read_u32_le(&mut self, offset: i64) -> i64 { + let idx = offset as usize; + if idx + 3 < self.data.len() { + u32::from_le_bytes([ + self.data[idx], + self.data[idx + 1], + self.data[idx + 2], + self.data[idx + 3], + ]) as i64 + } else { + 0 + } + } -fn memo_read_u64_le(offset: i64) -> RhaiResult { - let idx = offset as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - Ok(if idx + 7 < guard.len() { - u64::from_le_bytes([ - guard[idx], - guard[idx + 1], - guard[idx + 2], - guard[idx + 3], - guard[idx + 4], - guard[idx + 5], - guard[idx + 6], - guard[idx + 7], - ]) as i64 - } else { - 0 - }) -} + fn read_u64_le(&mut self, offset: i64) -> i64 { + let idx = offset as usize; + if idx + 7 < self.data.len() { + u64::from_le_bytes([ + self.data[idx], + self.data[idx + 1], + self.data[idx + 2], + self.data[idx + 3], + self.data[idx + 4], + self.data[idx + 5], + self.data[idx + 6], + self.data[idx + 7], + ]) as i64 + } else { + 0 + } + } -fn memo_read_bytes(offset: i64, len: i64) -> RhaiResult { - let idx = offset.max(0) as usize; - let n = len.max(0) as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - let end = (idx + n).min(guard.len()); - Ok(guard[idx..end].to_vec()) -} + fn read_bytes(&mut self, offset: i64, len: i64) -> Blob { + let idx = offset.max(0) as usize; + let n = len.max(0) as usize; + let end = (idx + n).min(self.data.len()); + self.data[idx..end].to_vec() + } -fn memo_read_string(offset: i64, len: i64) -> RhaiResult { - let idx = offset.max(0) as usize; - let n = len.max(0) as usize; - let guard = CURRENT_MEMO.lock().unwrap(); - let end = (idx + n).min(guard.len()); - let slice = &guard[idx..end]; - // Trim trailing zeros - let slice = match slice.iter().position(|&b| b == 0) { - Some(zero_pos) => &slice[..zero_pos], - None => slice, - }; - Ok(String::from_utf8_lossy(slice) - .trim_end_matches('\0') - .to_string()) + fn read_string(&mut self, offset: i64, len: i64) -> String { + let idx = offset.max(0) as usize; + let n = len.max(0) as usize; + let end = (idx + n).min(self.data.len()); + let slice = &self.data[idx..end]; + // Trim trailing zeros + let slice = match slice.iter().position(|&b| b == 0) { + Some(zero_pos) => &slice[..zero_pos], + None => slice, + }; + String::from_utf8_lossy(slice) + .trim_end_matches('\0') + .to_string() + } } // ── Constructor functions (global, non-fallible) ─────────────────────── @@ -161,16 +151,16 @@ pub fn create_sandboxed_engine() -> Engine { engine.disable_symbol("call"); engine.disable_symbol("import"); - // Register memo namespace module (memo::read_u8, etc.) - let mut memo_module = Module::new(); - memo_module.set_native_fn("len", memo_len); - memo_module.set_native_fn("read_u8", memo_read_u8); - memo_module.set_native_fn("read_u16_le", memo_read_u16_le); - memo_module.set_native_fn("read_u32_le", memo_read_u32_le); - memo_module.set_native_fn("read_u64_le", memo_read_u64_le); - memo_module.set_native_fn("read_bytes", memo_read_bytes); - memo_module.set_native_fn("read_string", memo_read_string); - engine.register_static_module("memo", memo_module.into()); + // Register the Memo type: scripts receive it as `process_memo(memo)` + // and call methods like `memo.read_u8(4)` on it. + engine.register_type::(); + engine.register_fn("len", Memo::len); + engine.register_fn("read_u8", Memo::read_u8); + engine.register_fn("read_u16_le", Memo::read_u16_le); + engine.register_fn("read_u32_le", Memo::read_u32_le); + engine.register_fn("read_u64_le", Memo::read_u64_le); + engine.register_fn("read_bytes", Memo::read_bytes); + engine.register_fn("read_string", Memo::read_string); // Register section/cell constructors (global) engine.register_fn("section", section as fn(&str, Dynamic, Dynamic) -> Dynamic); @@ -235,13 +225,11 @@ mod tests { #[test] fn test_memo_functions_out_of_bounds() { let engine = create_sandboxed_engine(); - let ast = engine - .compile("fn t() { memo::read_u8(1000) } t()") + let ast = engine.compile("fn t(memo) { memo.read_u8(1000) }").unwrap(); + let result: i64 = engine + .call_fn(&mut Scope::new(), &ast, "t", (Memo::new(vec![0x01, 0x02]),)) .unwrap(); - with_memo_bytes(&[0x01, 0x02], || { - let result: i64 = engine.eval_ast(&ast).unwrap(); - assert_eq!(result, 0, "OOB read should return 0"); - }); + assert_eq!(result, 0, "OOB read should return 0"); } #[test] @@ -249,15 +237,15 @@ mod tests { let engine = create_sandboxed_engine(); let data = vec![0xAA, 0xBB, 0x01, 0x00, 0x00, 0x00]; let ast = engine - .compile("fn t() { [memo::read_u8(0), memo::read_u32_le(2)] } t()") + .compile("fn t(memo) { [memo.read_u8(0), memo.read_u32_le(2)] }") + .unwrap(); + let result: Dynamic = engine + .call_fn(&mut Scope::new(), &ast, "t", (Memo::new(data),)) .unwrap(); - with_memo_bytes(&data, || { - let result: Dynamic = engine.eval_ast(&ast).unwrap(); - let json = serde_json::to_value(&result).unwrap(); - let arr = json.as_array().unwrap(); - assert_eq!(arr[0].as_i64().unwrap(), 0xAA); - assert_eq!(arr[1].as_i64().unwrap(), 1); - }); + let json = serde_json::to_value(&result).unwrap(); + let arr = json.as_array().unwrap(); + assert_eq!(arr[0].as_i64().unwrap(), 0xAA); + assert_eq!(arr[1].as_i64().unwrap(), 1); } #[test] @@ -304,21 +292,20 @@ mod tests { let data = vec![0xde, 0xad, 0xbe, 0xef, 0x01]; let script = r#" fn get_prefixes() { return ["deadbeef"]; } - fn process_memo() { - let version = memo::read_u8(4); + fn process_memo(memo) { + let version = memo.read_u8(4); let headers = ["Version"]; let rows = [[cell_number(version)]]; return [section("Test", headers, rows)]; } - process_memo() "#; let ast = engine.compile(script).unwrap(); - with_memo_bytes(&data, || { - let result: Dynamic = engine.eval_ast(&ast).unwrap(); - let sections = extract_sections(result); - assert_eq!(sections.len(), 1); - assert_eq!(sections[0].rows[0][0].value, "1"); - }); + let result: Dynamic = engine + .call_fn(&mut Scope::new(), &ast, "process_memo", (Memo::new(data),)) + .unwrap(); + let sections = extract_sections(result); + assert_eq!(sections.len(), 1); + assert_eq!(sections[0].rows[0][0].value, "1"); } #[test] @@ -328,12 +315,12 @@ mod tests { data[0..5].copy_from_slice(b"hello"); data[5] = 0; let ast = engine - .compile("fn t() { memo::read_string(0, 32) } t()") + .compile("fn t(memo) { memo.read_string(0, 32) }") + .unwrap(); + let result: String = engine + .call_fn(&mut Scope::new(), &ast, "t", (Memo::new(data),)) .unwrap(); - with_memo_bytes(&data, || { - let result: String = engine.eval_ast(&ast).unwrap(); - assert_eq!(result, "hello"); - }); + assert_eq!(result, "hello"); } #[test] @@ -348,9 +335,9 @@ mod tests { let script = r#" fn get_prefixes() { return ["444b3030"]; } - fn process_memo() { - let from_id = memo::read_u8(4); - let data_len = memo::read_u64_le(5); + fn process_memo(memo) { + let from_id = memo.read_u8(4); + let data_len = memo.read_u64_le(5); let headers = ["Field", "Value"]; let rows = [ [cell_string("Round"), cell_string("DKG Round 0")], @@ -359,17 +346,48 @@ mod tests { ]; return [section("DKG Message", headers, rows)]; } - process_memo() "#; let ast = engine.compile(script).unwrap(); - with_memo_bytes(&data, || { - let result: Dynamic = engine.eval_ast(&ast).unwrap(); - let sections = extract_sections(result); - assert_eq!(sections.len(), 1); - assert_eq!(sections[0].title, "DKG Message"); - assert_eq!(sections[0].rows[0][1].value, "DKG Round 0"); - assert_eq!(sections[0].rows[1][1].value, "1"); // from_id - assert_eq!(sections[0].rows[2][1].value, "32"); // data_len - }); + let result: Dynamic = engine + .call_fn(&mut Scope::new(), &ast, "process_memo", (Memo::new(data),)) + .unwrap(); + let sections = extract_sections(result); + assert_eq!(sections.len(), 1); + assert_eq!(sections[0].title, "DKG Message"); + assert_eq!(sections[0].rows[0][1].value, "DKG Round 0"); + assert_eq!(sections[0].rows[1][1].value, "1"); // from_id + assert_eq!(sections[0].rows[2][1].value, "32"); // data_len + } + + #[test] + fn test_process_memo_isolated_between_threads() { + // Each thread gets its own memo; values must not bleed across threads. + let engine = create_sandboxed_engine(); + let ast = engine + .compile("fn process_memo(memo) { memo.read_u8(0) }") + .unwrap(); + + let handles: Vec<_> = (0..8u8) + .map(|i| { + let ast = ast.clone(); + std::thread::spawn(move || { + let engine = create_sandboxed_engine(); + for _ in 0..100 { + let result: i64 = engine + .call_fn( + &mut Scope::new(), + &ast, + "process_memo", + (Memo::new(vec![i; 4]),), + ) + .unwrap(); + assert_eq!(result, i as i64); + } + }) + }) + .collect(); + for handle in handles { + handle.join().unwrap(); + } } } diff --git a/tools/test_plugin/main.rhai b/tools/test_plugin/main.rhai index 9f332da37..2536b1d60 100644 --- a/tools/test_plugin/main.rhai +++ b/tools/test_plugin/main.rhai @@ -12,9 +12,9 @@ fn get_prefixes() { return ["444b3030"]; // "DK00" in hex } -fn process_memo() { - let from_id = memo::read_u8(4); - let data_len = memo::read_u64_le(5); +fn process_memo(memo) { + let from_id = memo.read_u8(4); + let data_len = memo.read_u64_le(5); let headers = ["Field", "Value"]; let rows = [ From a58529de91b122749cabf8a0ce43ee2bad0e48e5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 17:22:12 +0800 Subject: [PATCH 066/189] fix: decode trailing escaped spaces in OA1 records The OA1 parser trimmed pair and value whitespace before decoding backslash-escaped spaces, so a value ending in '\ ' lost the escaped space and kept a stray trailing backslash (spec: spaces are trimmed unless escaped). Decode escapes before trimming and preserve spaces encoded by a trailing '\ ' run, matching the openalias-rs grammar. --- rust/src/api/voting.rs | 1 - rust/src/openalias.rs | 32 ++++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 02ae2a058..8d2face3f 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -1844,7 +1844,6 @@ fn config_switch_kind_string(kind: zcash_voting::config::ConfigSwitchKind) -> St } zcash_voting::config::ConfigSwitchKind::NewChainOrRound => "new_chain_or_round".to_string(), zcash_voting::config::ConfigSwitchKind::ProtocolChanged => "protocol_changed".to_string(), - _ => "unchanged".to_string(), } } diff --git a/rust/src/openalias.rs b/rust/src/openalias.rs index 9bad1e06d..5b73d0806 100644 --- a/rust/src/openalias.rs +++ b/rust/src/openalias.rs @@ -57,7 +57,9 @@ fn split_oa1_pairs(body: &str) -> Vec<&str> { match b { b'"' => in_quotes = !in_quotes, b';' if !in_quotes => { - let pair = body[start..i].trim(); + // Trim leading only: a trailing space before `;` may be the + // second char of a `\ ` escape and belongs to the value. + let pair = body[start..i].trim_start(); if !pair.is_empty() { pairs.push(pair); } @@ -66,7 +68,7 @@ fn split_oa1_pairs(body: &str) -> Vec<&str> { _ => {} } } - let last = body[start..].trim(); + let last = body[start..].trim_start(); if !last.is_empty() { pairs.push(last); } @@ -81,16 +83,34 @@ fn parse_oa1_pair(pair: &str) -> Option<(String, String)> { let (key, val) = pair.split_once('=')?; let key = key.trim().to_string(); - let val = val.trim(); - let val = if val.starts_with('"') && val.ends_with('"') && val.len() >= 2 { - val[1..val.len() - 1].to_string() + let trimmed = val.trim(); + let val = if trimmed.starts_with('"') && trimmed.ends_with('"') && trimmed.len() >= 2 { + // Quoted value: strip quotes, decode escaped spaces inside. + trimmed[1..trimmed.len() - 1].replace("\\ ", " ") } else { - val.replace("\\ ", " ") + // Unquoted value: decode `\ ` escapes on the raw value. + unescape_oa1_value(val) }; Some((key, val)) } +/// Decode `\ ` escapes in an unquoted OA1 value. +/// +/// Mirrors the openalias-rs grammar (`"\\ "* ... "\\ "*`): unescaped +/// leading/trailing spaces are dropped, but spaces encoded by a trailing +/// `\ ` run survive (e.g. `foo\ ` → `foo `). +fn unescape_oa1_value(raw: &str) -> String { + let raw = raw.trim_start(); + let mut tail = String::new(); + let mut end = raw.len(); + while raw[..end].ends_with("\\ ") { + end -= 2; + tail.push(' '); + } + format!("{}{}", raw[..end].trim_end().replace("\\ ", " "), tail) +} + /// Parse an OA1 TXT record string into an [`Oa1Record`]. /// /// Format: `oa1: key1=val1; key2="val2"; ...` From e2fb677fa3808930ac5e894e513ab617cc3de58c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 19:45:33 +0800 Subject: [PATCH 067/189] fix: save settings on nav away; resolve voting config from form value Settings form edits no longer persist on every keystroke; the save chain now runs once in SettingsPageState.didPop (matching the sub-page pattern) via AppSettingsNotifier.save(). VotingConfigNotifier.build() returns only the cached config so reading the provider never fetches; resolve() takes an optional source so the settings button uses the typed URL. --- lib/settings.dart | 51 +++++++++++++----------------------------- lib/store.dart | 56 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/lib/settings.dart b/lib/settings.dart index 807eb9a3a..d3d13eeaa 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -13,9 +13,7 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:zkool/router.dart'; -import 'package:zkool/src/rust/api/coin.dart'; import 'package:zkool/src/rust/api/network.dart' show isValidNymUrl; -import 'package:zkool/src/rust/api/db.dart'; import 'package:zkool/src/rust/api/init.dart'; import 'package:zkool/src/rust/api/sapling.dart'; import 'package:zkool/src/rust/api/sync.dart'; @@ -35,7 +33,6 @@ class SettingsPage extends ConsumerStatefulWidget { } class SettingsPageState extends ConsumerState with RouteAware { - late Coin c = coinContext.coin; AppSettings? settings; @override @@ -61,39 +58,20 @@ class SettingsPageState extends ConsumerState with RouteAware { if (settings == null) return blank(context); return SettingsForm( settings!, - onChanged: (settings) async { - final prefs = SharedPreferencesAsync(); - await prefs.setString("database", settings.dbName); - await putProp(key: "is_light_node", value: settings.isLightNode.toString(), c: c); - await putProp(key: "lwd", value: settings.lwd, c: c); - await putProp(key: "block_explorer", value: settings.blockExplorer, c: c); - await putProp(key: "actions_per_sync", value: settings.actionsPerSync, c: c); - await putProp(key: "sync_interval", value: settings.syncInterval, c: c); - await prefs.setBool("pin_lock", settings.needPin); - await prefs.setBool("offline", settings.offline); - await prefs.setInt("transport", settings.transport); - await putProp(key: "proxy", value: settings.proxy, c: c); - await prefs.setBool("get_fx", settings.getFx); - await prefs.setString("coingecko", settings.coingecko); - await putProp(key: "qr_enabled", value: settings.qrSettings.enabled.toString(), c: c); - await putProp(key: "qr_size", value: settings.qrSettings.size.toString(), c: c); - await putProp(key: "qr_ecLevel", value: settings.qrSettings.ecLevel.toString(), c: c); - await putProp(key: "qr_delay", value: settings.qrSettings.delay.toString(), c: c); - await putProp(key: "qr_repair", value: settings.qrSettings.repair.toString(), c: c); - c = c.setLwd(url: settings.lwd, serverType: settings.isLightNode ? 0 : 1); - c = c.setTransport(transport: settings.transport); - c = c.setProxy(proxy: settings.proxy); - await prefs.setBool("vault", settings.vault); - await prefs.setBool("expert_mode", settings.expertMode); - await prefs.setString("palette_name", settings.paletteName); - await prefs.setBool("dark_mode", settings.darkMode); - await putProp(key: "currency", value: settings.currency, c: c); - coinContext.set(coin: c); - ref.read(priceProvider.notifier).setAutoFetchFx(settings.getFx, settings.coingecko, settings.currency); - ref.invalidate(appSettingsProvider); - }, + // Keep a snapshot of the latest edits; the changes are applied only + // when leaving this page (see didPop), matching the sub-page pattern. + onChanged: (settings) => this.settings = settings, ); } + + @override + void didPop() { + super.didPop(); + final s = settings; + if (s != null) { + ref.read(appSettingsProvider.notifier).save(s); + } + } } class SettingsForm extends ConsumerStatefulWidget { @@ -563,8 +541,9 @@ class SettingsFormState extends ConsumerState { Future _fetchVotingConfig(BuildContext context) async { try { - final config = - await ref.read(votingConfigProvider.notifier).resolve(); + final config = await ref + .read(votingConfigProvider.notifier) + .resolve(source: settings.votingConfigUrl); if (!context.mounted) return; if (config == null) { await showMessage( diff --git a/lib/store.dart b/lib/store.dart index c0b60e168..34b798145 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -463,6 +463,49 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { voteNodeUrl: url, )); } + + /// Persist all settings to prefs/DB props and apply live coin changes + /// (lwd/transport/proxy). Called once when leaving the settings page. + Future save(AppSettings settings) async { + final c = coinContext.coin; + final prefs = SharedPreferencesAsync(); + await prefs.setString("database", settings.dbName); + await putProp(key: "is_light_node", value: settings.isLightNode.toString(), c: c); + await putProp(key: "lwd", value: settings.lwd, c: c); + await putProp(key: "block_explorer", value: settings.blockExplorer, c: c); + await putProp(key: "actions_per_sync", value: settings.actionsPerSync, c: c); + await putProp(key: "sync_interval", value: settings.syncInterval, c: c); + await prefs.setBool("pin_lock", settings.needPin); + await prefs.setBool("offline", settings.offline); + await prefs.setInt("transport", settings.transport); + await putProp(key: "proxy", value: settings.proxy, c: c); + await prefs.setBool("get_fx", settings.getFx); + await prefs.setString("coingecko", settings.coingecko); + await putProp(key: "qr_enabled", value: settings.qrSettings.enabled.toString(), c: c); + await putProp(key: "qr_size", value: settings.qrSettings.size.toString(), c: c); + await putProp(key: "qr_ecLevel", value: settings.qrSettings.ecLevel.toString(), c: c); + await putProp(key: "qr_delay", value: settings.qrSettings.delay.toString(), c: c); + await putProp(key: "qr_repair", value: settings.qrSettings.repair.toString(), c: c); + await prefs.setBool("vault", settings.vault); + await prefs.setBool("expert_mode", settings.expertMode); + await prefs.setString("palette_name", settings.paletteName); + await prefs.setBool("dark_mode", settings.darkMode); + await putProp(key: "currency", value: settings.currency, c: c); + await putProp(key: "voting_config_url", value: settings.votingConfigUrl, c: c); + await putProp(key: "vote_node_url", value: settings.voteNodeUrl, c: c); + coinContext.set( + coin: c + .setLwd(url: settings.lwd, serverType: settings.isLightNode ? 0 : 1) + .setTransport(transport: settings.transport) + .setProxy(proxy: settings.proxy), + ); + ref.read(priceProvider.notifier).setAutoFetchFx( + settings.getFx, + settings.coingecko, + settings.currency, + ); + state = AsyncValue.data(settings); + } } @Riverpod(keepAlive: true) @@ -1310,7 +1353,9 @@ Future> votingRoundList(Ref ref) async { } /// Resolved and authenticated voting config for the configured source URL. -/// Resolves fresh on build; on failure falls back to the last cached config. +/// `build()` returns the last cached resolved config without touching the +/// network (so merely reading the provider never triggers a fetch); call +/// `resolve()` to fetch fresh, falling back to cached on failure. @Riverpod(keepAlive: true) class VotingConfigNotifier extends _$VotingConfigNotifier { @override @@ -1318,7 +1363,7 @@ class VotingConfigNotifier extends _$VotingConfigNotifier { final settings = await ref.watch(appSettingsProvider.future); final source = settings.votingConfigUrl; if (source.isEmpty) return null; - return _resolve(source); + return votingConfigCached(source: source, c: coinContext.coin); } Future _resolve(String source) async { @@ -1330,9 +1375,10 @@ class VotingConfigNotifier extends _$VotingConfigNotifier { } } - Future resolve() async { - final settings = await ref.read(appSettingsProvider.future); - final source = settings.votingConfigUrl; + /// Resolve the voting config, using [source] when provided or the + /// configured URL from app settings otherwise. + Future resolve({String? source}) async { + source ??= (await ref.read(appSettingsProvider.future)).votingConfigUrl; state = const AsyncValue.loading(); final result = source.isEmpty ? null : await _resolve(source); state = AsyncValue.data(result); From 6c8c98be3d65cf1b2d9faf6c6a4d35b509a3a5ba Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 19:58:57 +0800 Subject: [PATCH 068/189] fix: surface voting config resolve errors instead of swallowing them VotingConfigNotifier.build() returns only the cached config (no network), so reading the provider never triggers a fetch and resolve() is the single fetch path. _resolve logs the real error, serves cache only when present, and rethrows on total failure; voting polls init/refresh show the error via showException. --- lib/pages/voting_polls.dart | 18 +++++++++++++----- lib/store.dart | 22 +++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index 0ad5e6e03..db8f6739c 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -29,9 +29,13 @@ class VotingPollsPageState extends ConsumerState { super.initState(); Future(_guardHardwareAccount); Future(() async { - final settings = await ref.read(appSettingsProvider.future); - if (settings.votingConfigUrl.isNotEmpty) { - await ref.read(votingConfigProvider.notifier).resolve(); + try { + final settings = await ref.read(appSettingsProvider.future); + if (settings.votingConfigUrl.isNotEmpty) { + await ref.read(votingConfigProvider.notifier).resolve(); + } + } on AnyhowException catch (e) { + if (mounted) await showException(context, e.message); } }); } @@ -70,9 +74,13 @@ class VotingPollsPageState extends ConsumerState { actions: [ IconButton( icon: Icon(Icons.refresh), - onPressed: () { + onPressed: () async { ref.invalidate(votingRoundListProvider); - ref.read(votingConfigProvider.notifier).resolve(); + try { + await ref.read(votingConfigProvider.notifier).resolve(); + } on AnyhowException catch (e) { + if (context.mounted) await showException(context, e.message); + } }, ), ], diff --git a/lib/store.dart b/lib/store.dart index 34b798145..c739db810 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1370,19 +1370,31 @@ class VotingConfigNotifier extends _$VotingConfigNotifier { final c = coinContext.coin; try { return await votingConfigResolve(source: source, c: c); - } on Exception { - return await votingConfigCached(source: source, c: c); + } on AnyhowException catch (e) { + logger.e("Voting config resolve failed for $source: ${e.message}"); + final cached = await votingConfigCached(source: source, c: c); + if (cached != null) { + logger.w("Serving cached voting config for $source"); + return cached; + } + rethrow; } } /// Resolve the voting config, using [source] when provided or the /// configured URL from app settings otherwise. + /// Throws when resolution fails and no cached config exists. Future resolve({String? source}) async { source ??= (await ref.read(appSettingsProvider.future)).votingConfigUrl; state = const AsyncValue.loading(); - final result = source.isEmpty ? null : await _resolve(source); - state = AsyncValue.data(result); - return result; + try { + final result = source.isEmpty ? null : await _resolve(source); + state = AsyncValue.data(result); + return result; + } catch (e, stackTrace) { + state = AsyncValue.error(e, stackTrace); + rethrow; + } } } From 2e6f79655e5496fa96d1ec678f7ae4f194e903f5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Sat, 15 Aug 2026 20:43:06 +0800 Subject: [PATCH 069/189] fix: persist ballot intents at cast time; parse option index Ballot intents FK-reference the voting round, which only exists after delegation prepare, so writing intents at proposal-selection time failed with a FOREIGN KEY error. Move intent writes to the submission job before the cast loop (mirroring vizor), sourced from the persisted drafts; the proposal page now persists drafts only. Also parse proposal option ids from 'index' (vote-sdk format, omitted for the first option) so Support/Oppose radios no longer collide on id 0, and surface persistence errors via showException. --- lib/pages/voting_proposal.dart | 49 ++++++++++++++++------------------ lib/store.dart | 23 ++++++++++++++++ lib/store.g.dart | 22 ++++++++++----- 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index cfe99c0b0..0a712d994 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart'; import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/store.dart'; +import 'package:zkool/widgets/error_display.dart'; /// One parsed proposal option. class _Option { @@ -158,11 +159,17 @@ class VotingProposalPageState extends ConsumerState { if (id is! int || id < 1 || id > 15) return null; final title = (value['title'] ?? "Proposal $id").toString(); var options = (value['options'] as List? ?? []) - .map((o) { + .asMap() + .entries + .map((entry) { + final o = entry.value; if (o is! Map) return null; return _Option( - id: (o['id'] is int) ? o['id'] as int : 0, - label: (o['label'] ?? o['title'] ?? "Option").toString(), + // vote-sdk option ids come from `index` (omitted = 0 for the + // first option); fall back to the list position. + id: (o['index'] is int) ? o['index'] as int : entry.key, + label: (o['label'] ?? o['short_title'] ?? o['title'] ?? "Option") + .toString(), ); }) .whereType<_Option>() @@ -177,29 +184,19 @@ class VotingProposalPageState extends ConsumerState { return _Proposal(id: id, title: title, options: options); } + Future _persistSafe() async { + try { + await _persist(); + } on AnyhowException catch (e) { + if (mounted) await showException(context, e.message); + } + } + + /// Persists the draft ballot only; durable ballot intents are written by + /// the submission job from these drafts before the cast loop (mirrors + /// vizor), when the round row already exists in the voting DB. Future _persist() async { final c = coinContext.coin; - for (final p in _proposals) { - if (_skipped.contains(p.id)) { - await votingSetBallotIntent( - roundId: widget.roundId, - proposalId: p.id, - skipped: true, - choice: 0, - numOptions: p.options.length, - c: c, - ); - } else if (_choices.containsKey(p.id)) { - await votingSetBallotIntent( - roundId: widget.roundId, - proposalId: p.id, - skipped: false, - choice: _choices[p.id]!, - numOptions: p.options.length, - c: c, - ); - } - } // Draft votes mirror the fork's DraftVote JSON: skipped = choice == num_options. final drafts = _proposals .where((p) => _skipped.contains(p.id) || _choices.containsKey(p.id)) @@ -259,7 +256,7 @@ class VotingProposalPageState extends ConsumerState { _skipped.remove(p.id); _choices[p.id] = v!; }); - await _persist(); + await _persistSafe(); }, )), RadioListTile( @@ -271,7 +268,7 @@ class VotingProposalPageState extends ConsumerState { _choices.remove(p.id); _skipped.add(p.id); }); - await _persist(); + await _persistSafe(); }, ), ], diff --git a/lib/store.dart b/lib/store.dart index c739db810..0332e2105 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1675,6 +1675,29 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final draftsJson = await votingDraftsLoad(roundId: roundId, c: c); final byBundle = groupBy(voteSteps, (s) => s.bundleIndex); + // Write durable ballot intents before the cast loop (mirrors vizor's + // writeBallotIntents): recovery can resume from the right choice if the + // app dies mid-vote. The round row exists by now (delegation prepared), + // so the FK is satisfied. + if (draftsJson != null && draftsJson.isNotEmpty) { + final drafts = jsonDecode(draftsJson) as List; + for (final d in drafts) { + final map = d as Map; + final proposalId = map['proposal_id'] as int? ?? 0; + final choice = map['choice'] as int? ?? 0; + final numOptions = map['num_options'] as int? ?? 2; + final skipped = choice == numOptions; + await votingSetBallotIntent( + roundId: roundId, + proposalId: proposalId, + skipped: skipped, + choice: skipped ? 0 : choice, + numOptions: numOptions, + c: c, + ); + } + } + for (final entry in byBundle.entries) { final bundleIndex = entry.key; final steps = entry.value; diff --git a/lib/store.g.dart b/lib/store.g.dart index b56267cda..e5919e4cd 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -619,7 +619,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'7772fb1c14262ec8f76f7d44c600d06358ec5ebb'; + r'2892f9bcc456a390e78cdbc18d88bd913c00158c'; abstract class _$AppSettingsNotifier extends $AsyncNotifier { FutureOr build(); @@ -1564,17 +1564,23 @@ final class VotingRoundListProvider extends $FunctionalProvider< String _$votingRoundListHash() => r'12d2cfda4753a04d9343e21a6637789106c3ffb5'; /// Resolved and authenticated voting config for the configured source URL. -/// Resolves fresh on build; on failure falls back to the last cached config. +/// `build()` returns the last cached resolved config without touching the +/// network (so merely reading the provider never triggers a fetch); call +/// `resolve()` to fetch fresh, falling back to cached on failure. @ProviderFor(VotingConfigNotifier) const votingConfigProvider = VotingConfigNotifierProvider._(); /// Resolved and authenticated voting config for the configured source URL. -/// Resolves fresh on build; on failure falls back to the last cached config. +/// `build()` returns the last cached resolved config without touching the +/// network (so merely reading the provider never triggers a fetch); call +/// `resolve()` to fetch fresh, falling back to cached on failure. final class VotingConfigNotifierProvider extends $AsyncNotifierProvider { /// Resolved and authenticated voting config for the configured source URL. - /// Resolves fresh on build; on failure falls back to the last cached config. + /// `build()` returns the last cached resolved config without touching the + /// network (so merely reading the provider never triggers a fetch); call + /// `resolve()` to fetch fresh, falling back to cached on failure. const VotingConfigNotifierProvider._() : super( from: null, @@ -1595,10 +1601,12 @@ final class VotingConfigNotifierProvider } String _$votingConfigNotifierHash() => - r'ed064685d2a96f9c26b4e3e40636d03d32287caf'; + r'bf23634dc2f92cf3ccff2282522f6629e7dc81db'; /// Resolved and authenticated voting config for the configured source URL. -/// Resolves fresh on build; on failure falls back to the last cached config. +/// `build()` returns the last cached resolved config without touching the +/// network (so merely reading the provider never triggers a fetch); call +/// `resolve()` to fetch fresh, falling back to cached on failure. abstract class _$VotingConfigNotifier extends $AsyncNotifier { FutureOr build(); @@ -1740,7 +1748,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'5dfea23a8350a2f2194fe16b725caffd2a1f33a6'; + r'1009f94a4ecc110d5b99e5eef2edcc075608246e'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → From e5d0bad7ebfcad0fed8dd61a165c9fe630ac9fe7 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 00:29:15 +0800 Subject: [PATCH 070/189] chore: bump zcash_voting to async vote-tree transport rev The fork's tree-sync HTTP path was the only blocking transport (Runtime::block_on inside an existing tokio runtime panicked during votingSyncTree). Bump to 54e6c72 which converts the transport chain to async and drops the blocking runtime. --- rust/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e42c70616..3c40cdb14 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,7 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } -zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fd4362b097579782565de553b7b8c5a612cda1e2", features = ["zsa-orchard"] } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "54e6c72ceae7ef4fd27129cf1e5484df5048f0a7", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" From 8da55a120fb8c046a65b141821d013fcc4f3f052 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 01:19:18 +0800 Subject: [PATCH 071/189] test: add unit tests for the coin voting module --- rust/src/api/voting.rs | 1235 ++++++++++++++++++++++++++++++++++++++++ rust/src/voting.rs | 260 ++++++++- 2 files changed, 1494 insertions(+), 1 deletion(-) diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 8d2face3f..a624e47b5 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -732,6 +732,16 @@ pub async fn voting_set_ballot_intent( Ok(()) } +/// Returns the quantized voting weight (zatoshi) for the account's eligible +/// shielded notes at `snapshot_height`, computed with the same canonical +/// bundle planning as the delegation prepare step — but from the local DB +/// only (no witnesses, no tree state). Shown pre-submission as an estimate. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_eligible_weight(snapshot_height: u32, c: &Coin) -> Result { + let mut connection = c.get_connection().await?; + voting::eligible_voting_weight(&mut connection, c.account, snapshot_height).await +} + /// Persists the draft ballot for a round (props table, wallet-scoped). #[cfg_attr(feature = "flutter", frb)] pub async fn voting_drafts_save(round_id: &str, drafts_json: &str, c: &Coin) -> Result<()> { @@ -2114,3 +2124,1228 @@ pub async fn votechain_share_status( crate::net::votechain::share_status(&server_url, &round_id, &share_id, &proxy).await?; Ok(VotingChainResponse { status_code, body }) } + +#[cfg(test)] +mod tests { + use super::*; + use zcash_voting::config::{ + AuthenticatedRound, ConfigCondition, ConfigConditionKind, ConfigSwitchKind, PirLayout, + ResolvedVotingConfig, ServiceEndpoint, SupportedVersions, + }; + use zcash_voting::phases::{DelegationPhase, SharePhase, VotePhase}; + use zcash_voting::prelude::{ + DelegationConfirmation, DelegationSetup, DelegationSubmission, SharePayload, + SignedVoteCommitments, VanWitness, VoteConfirmation, VoteSubmission, + }; + use zcash_voting::session::{ + CompletedVoteChoice, CompletedVoteDisplay, DelegationRecoveryWork, + DelegationRecoveryWorkKind, DelegationStatus, RoundPlanAction, + }; + use zcash_voting::share_policy::ShareTrackingSummary; + use zcash_voting::vote::{SignedVoteCommitment, VoteCommitStage}; + use zcash_voting::WireEncryptedShare; + + fn assert_round_trips(v: T) + where + T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug, + { + let json = serde_json::to_string(&v).unwrap(); + let back: T = serde_json::from_str(&json).unwrap(); + assert_eq!(back, v); + } + + fn coin(transport: u8, proxy: &str) -> Coin { + Coin { + coin: 0, + account: 0, + db_filepath: String::new(), + url: String::new(), + server_type: 0, + transport, + proxy: proxy.to_string(), + } + } + + #[test] + fn voting_pir_layout_from_and_to_fork_round_trip() { + let fork = PirLayout { + pir_depth: 5, + tier0_layers: 2, + tier1_layers: 3, + poly_len: 2048, + }; + let mirror = VotingPirLayout::from(fork); + assert_eq!( + mirror, + VotingPirLayout { + pir_depth: 5, + tier0_layers: 2, + tier1_layers: 3, + poly_len: 2048, + } + ); + assert_eq!(mirror.to_fork(), fork); + } + + #[test] + fn voting_delegation_setup_from_maps_all_fields() { + let fork = DelegationSetup { + pczt_bytes: vec![1, 2], + pczt_sighash: [3u8; 32], + rk: [4u8; 32], + action_index: 65536, + action_bytes: vec![5], + tx1_effects: vec![6], + }; + assert_eq!( + VotingDelegationSetup::from(fork), + VotingDelegationSetup { + pczt_bytes: vec![1, 2], + pczt_sighash: vec![3u8; 32], + rk: vec![4u8; 32], + action_index: 65536, + action_bytes: vec![5], + tx1_effects: vec![6], + } + ); + } + + #[test] + fn voting_delegation_submission_from_maps_all_fields() { + let fork = DelegationSubmission { + proof: vec![1], + rk: [2u8; 32], + nf_signed: [3u8; 32], + cmx_new: [4u8; 32], + gov_comm: [5u8; 32], + gov_nullifiers: [[6u8; 32], [7u8; 32], [8u8; 32], [9u8; 32], [10u8; 32]], + alpha: [11u8; 32], + vote_round_id: "round-1".to_string(), + spend_auth_sig: [12u8; 64], + sighash: [13u8; 32], + tx1_effects: vec![14], + }; + assert_eq!( + VotingDelegationSubmission::from(fork), + VotingDelegationSubmission { + proof: vec![1], + rk: vec![2u8; 32], + nf_signed: vec![3u8; 32], + cmx_new: vec![4u8; 32], + gov_comm: vec![5u8; 32], + gov_nullifiers: vec![ + vec![6u8; 32], + vec![7u8; 32], + vec![8u8; 32], + vec![9u8; 32], + vec![10u8; 32], + ], + alpha: vec![11u8; 32], + vote_round_id: "round-1".to_string(), + spend_auth_sig: vec![12u8; 64], + sighash: vec![13u8; 32], + tx1_effects: vec![14], + } + ); + } + + #[test] + fn voting_delegation_confirmation_from_maps_all_fields() { + let fork = DelegationConfirmation { + tx_hash: "0xabc".to_string(), + van_leaf_position: 9, + }; + assert_eq!( + VotingDelegationConfirmation::from(fork), + VotingDelegationConfirmation { + tx_hash: "0xabc".to_string(), + van_leaf_position: 9, + } + ); + } + + #[test] + fn voting_vote_confirmation_from_maps_all_fields() { + let fork = VoteConfirmation { + tx_hash: "0xdef".to_string(), + van_leaf_position: 9, + vc_tree_position: 7, + }; + assert_eq!( + VotingVoteConfirmation::from(fork), + VotingVoteConfirmation { + tx_hash: "0xdef".to_string(), + van_leaf_position: 9, + vc_tree_position: 7, + } + ); + } + + #[test] + fn voting_van_witness_from_maps_all_fields() { + let fork = VanWitness { + auth_path: vec![vec![1], vec![2, 3]], + position: 4, + anchor_height: 5, + }; + assert_eq!( + VotingVanWitness::from(fork), + VotingVanWitness { + auth_path: vec![vec![1], vec![2, 3]], + position: 4, + anchor_height: 5, + } + ); + } + + #[test] + fn voting_signed_vote_commitments_from_maps_all_fields() { + let fork = SignedVoteCommitments { + bundle_index: 3, + commitments: vec![ + SignedVoteCommitment { + proposal_id: 1, + choice: 2, + vote_round_id: "r".to_string(), + van_nullifier: [3u8; 32], + vote_authority_note_new: [4u8; 32], + vote_commitment: [5u8; 32], + proof: vec![6], + encrypted_shares: vec![], + share_payloads: vec![], + anchor_height: 7, + shares_hash: [8u8; 32], + share_comms: vec![], + r_vpk: [9u8; 32], + vote_auth_sig: [10u8; 64], + commitment_bundle_json: "{}".to_string(), + }, + SignedVoteCommitment { + proposal_id: 11, + choice: 12, + vote_round_id: "r2".to_string(), + van_nullifier: [13u8; 32], + vote_authority_note_new: [14u8; 32], + vote_commitment: [15u8; 32], + proof: vec![16], + encrypted_shares: vec![], + share_payloads: vec![], + anchor_height: 17, + shares_hash: [18u8; 32], + share_comms: vec![], + r_vpk: [19u8; 32], + vote_auth_sig: [20u8; 64], + commitment_bundle_json: "{\"x\":1}".to_string(), + }, + ], + }; + let mirror = VotingVoteCommitments::from(fork); + assert_eq!(mirror.bundle_index, 3); + assert_eq!(mirror.commitments.len(), 2); + assert_eq!( + mirror.commitments[0], + VotingSignedVoteCommitment { + proposal_id: 1, + choice: 2, + vote_round_id: "r".to_string(), + van_nullifier: vec![3u8; 32], + vote_authority_note_new: vec![4u8; 32], + vote_commitment: vec![5u8; 32], + proof: vec![6], + anchor_height: 7, + r_vpk: vec![9u8; 32], + vote_auth_sig: vec![10u8; 64], + commitment_bundle_json: "{}".to_string(), + } + ); + assert_eq!(mirror.commitments[1].commitment_bundle_json, "{\"x\":1}"); + + // Empty edge. + let empty = VotingVoteCommitments::from(SignedVoteCommitments { + bundle_index: 4, + commitments: vec![], + }); + assert!(empty.commitments.is_empty()); + } + + #[test] + fn voting_encrypted_share_from_maps_all_fields() { + let fork = WireEncryptedShare { + c1: vec![1], + c2: vec![2], + share_index: 3, + }; + assert_eq!( + VotingEncryptedShare::from(&fork), + VotingEncryptedShare { + c1: vec![1], + c2: vec![2], + share_index: 3, + } + ); + } + + #[test] + fn voting_share_payload_from_maps_all_fields() { + let fork = SharePayload { + shares_hash: vec![1], + proposal_id: 2, + vote_decision: 3, + enc_share: WireEncryptedShare { + c1: vec![4], + c2: vec![5], + share_index: 6, + }, + tree_position: 7, + all_enc_shares: vec![WireEncryptedShare { + c1: vec![8], + c2: vec![9], + share_index: 10, + }], + share_comms: vec![vec![11]], + primary_blind: vec![12], + }; + assert_eq!( + VotingSharePayload::from(&fork), + VotingSharePayload { + shares_hash: vec![1], + proposal_id: 2, + vote_decision: 3, + enc_share: VotingEncryptedShare { + c1: vec![4], + c2: vec![5], + share_index: 6, + }, + tree_position: 7, + all_enc_shares: vec![VotingEncryptedShare { + c1: vec![8], + c2: vec![9], + share_index: 10, + }], + share_comms: vec![vec![11]], + primary_blind: vec![12], + } + ); + } + + #[test] + fn voting_vote_submission_from_maps_all_fields() { + let fork = VoteSubmission { + vote_round_id: "r".to_string(), + proposal_id: 1, + van_nullifier: [2u8; 32], + vote_authority_note_new: [3u8; 32], + vote_commitment: [4u8; 32], + proof: vec![5], + r_vpk: [6u8; 32], + vote_auth_sig: [7u8; 64], + anchor_height: 8, + }; + assert_eq!( + VotingVoteSubmission::from(fork), + VotingVoteSubmission { + vote_round_id: "r".to_string(), + proposal_id: 1, + van_nullifier: vec![2u8; 32], + vote_authority_note_new: vec![3u8; 32], + vote_commitment: vec![4u8; 32], + proof: vec![5], + r_vpk: vec![6u8; 32], + vote_auth_sig: vec![7u8; 64], + anchor_height: 8, + } + ); + } + + #[test] + fn delegation_progress_maps_every_variant() { + let cases = [ + ( + DelegationProgress::SelectingNotes, + VotingDelegationProgress::SelectingNotes, + ), + ( + DelegationProgress::PcztBuilding, + VotingDelegationProgress::PcztBuilding, + ), + ( + DelegationProgress::PcztBuilt, + VotingDelegationProgress::PcztBuilt, + ), + ( + DelegationProgress::ProofStarting, + VotingDelegationProgress::ProofStarting, + ), + ( + DelegationProgress::ProofProgress(0.5), + VotingDelegationProgress::ProofProgress { progress: 0.5 }, + ), + ( + DelegationProgress::ProofComplete, + VotingDelegationProgress::ProofComplete, + ), + ( + DelegationProgress::SigningPayload, + VotingDelegationProgress::SigningPayload, + ), + ( + DelegationProgress::PayloadReady, + VotingDelegationProgress::PayloadReady, + ), + ]; + for (fork, expected) in cases { + assert_eq!(VotingDelegationProgress::from(fork), expected); + } + } + + #[test] + fn vote_commit_stage_maps_every_variant() { + let cases = [ + ( + VoteCommitStage::ProofStarting { + proposal_id: 1, + bundle_index: 2, + }, + VotingVoteCommitStage::ProofStarting { + proposal_id: 1, + bundle_index: 2, + }, + ), + ( + VoteCommitStage::ProofProgress { + proposal_id: 1, + bundle_index: 2, + progress: 0.25, + }, + VotingVoteCommitStage::ProofProgress { + proposal_id: 1, + bundle_index: 2, + progress: 0.25, + }, + ), + ( + VoteCommitStage::SharePayloadsBuilding { + proposal_id: 1, + bundle_index: 2, + }, + VotingVoteCommitStage::SharePayloadsBuilding { + proposal_id: 1, + bundle_index: 2, + }, + ), + ( + VoteCommitStage::Signing { + proposal_id: 1, + bundle_index: 2, + }, + VotingVoteCommitStage::Signing { + proposal_id: 1, + bundle_index: 2, + }, + ), + ]; + for (fork, expected) in cases { + assert_eq!(VotingVoteCommitStage::from(fork), expected); + } + } + + #[test] + fn round_info_from_maps_all_fields_and_network_string() { + for (network, expected_network) in [ + (VotingNetwork::Mainnet, "mainnet"), + (VotingNetwork::Testnet, "testnet"), + (VotingNetwork::Regtest, "regtest"), + ] { + let fork = ForkRoundInfo { + round_id: "r1".to_string(), + network, + snapshot_height: 100, + hotkey_address: Some("addr".to_string()), + eligible_weight: Some(50_000), + bundle_count: 2, + created_at: 123, + }; + let mirror = VotingRoundInfo::from(fork); + assert_eq!(mirror.round_id, "r1"); + assert_eq!(mirror.network, expected_network); + assert_eq!(mirror.snapshot_height, 100); + assert_eq!(mirror.hotkey_address.as_deref(), Some("addr")); + assert_eq!(mirror.eligible_weight_zatoshi, Some(50_000)); + assert_eq!(mirror.bundle_count, 2); + assert_eq!(mirror.created_at, 123); + } + + let fork = ForkRoundInfo { + round_id: "r2".to_string(), + network: VotingNetwork::Mainnet, + snapshot_height: 0, + hotkey_address: None, + eligible_weight: None, + bundle_count: 0, + created_at: 0, + }; + let mirror = VotingRoundInfo::from(fork); + assert_eq!(mirror.hotkey_address, None); + assert_eq!(mirror.eligible_weight_zatoshi, None); + } + + #[test] + fn next_step_maps_every_variant() { + fn assert_step( + step: NextStep, + kind: &str, + bundle: u32, + proposal: u32, + choice: u32, + share: u32, + ) { + let mirror = VotingNextStep::from(step); + assert_eq!(mirror.kind, kind); + assert_eq!(mirror.bundle_index, bundle); + assert_eq!(mirror.proposal_id, proposal); + assert_eq!(mirror.choice, choice); + assert_eq!(mirror.share_index, share); + } + + assert_step(NextStep::Delegate { bundle_index: 1 }, "delegate", 1, 0, 0, 0); + assert_step( + NextStep::PollDelegation { bundle_index: 2 }, + "poll_delegation", + 2, + 0, + 0, + 0, + ); + assert_step( + NextStep::CastVote { + bundle_index: 3, + proposal_id: 4, + choice: 5, + }, + "cast_vote", + 3, + 4, + 5, + 0, + ); + assert_step( + NextStep::SubmitVote { + bundle_index: 6, + proposal_id: 7, + }, + "submit_vote", + 6, + 7, + 0, + 0, + ); + assert_step( + NextStep::PollVote { + bundle_index: 8, + proposal_id: 9, + }, + "poll_vote", + 8, + 9, + 0, + 0, + ); + assert_step( + NextStep::SubmitShares { + bundle_index: 10, + proposal_id: 11, + share_index: 12, + }, + "submit_shares", + 10, + 11, + 0, + 12, + ); + assert_step( + NextStep::ConfirmShare { + bundle_index: 13, + proposal_id: 14, + share_index: 15, + }, + "confirm_share", + 13, + 14, + 0, + 15, + ); + } + + #[test] + fn round_plan_from_maps_all_fields() { + let fork = ForkRoundPlan { + round_id: "r1".to_string(), + pending_recovery: true, + next_steps: vec![ + NextStep::Delegate { bundle_index: 1 }, + NextStep::PollVote { + bundle_index: 2, + proposal_id: 3, + }, + ], + open_proposals: vec![3, 4], + all_decided: false, + delegation_statuses: vec![DelegationStatus { + bundle_index: 1, + phase: DelegationPhase::Proved, + tx_hash: Some("t1".to_string()), + }], + blocking_recovery: true, + blocking_share_work: false, + hotkey_bound: true, + completed_vote_artifact: true, + completed_for_display: true, + completed_vote_display: Some(CompletedVoteDisplay { + choices: vec![ + CompletedVoteChoice { + proposal_id: 3, + choice: Some(1), + }, + CompletedVoteChoice { + proposal_id: 4, + choice: None, + }, + ], + voted_at: Some(42), + }), + needs_draft_setup: false, + primary_action: RoundPlanAction::Done, + recovered_delegation_work: vec![DelegationRecoveryWork { + kind: DelegationRecoveryWorkKind::PollDelegation, + bundle_index: 1, + phase: DelegationPhase::Submitted, + tx_hash: Some("t1".to_string()), + }], + recovered_vote_work: vec![], + }; + let mirror = VotingRoundPlan::from(fork); + assert_eq!(mirror.round_id, "r1"); + assert!(mirror.pending_recovery); + assert_eq!(mirror.next_steps.len(), 2); + assert_eq!( + mirror.next_steps[0], + VotingNextStep { + kind: "delegate".to_string(), + bundle_index: 1, + proposal_id: 0, + choice: 0, + share_index: 0, + } + ); + assert_eq!(mirror.open_proposals, vec![3, 4]); + assert!(!mirror.all_decided); + assert_eq!( + mirror.delegation_statuses, + vec![VotingDelegationStatus { + bundle_index: 1, + phase: "proved".to_string(), + tx_hash: Some("t1".to_string()), + }] + ); + assert!(mirror.blocking_recovery); + assert!(!mirror.blocking_share_work); + assert!(mirror.hotkey_bound); + assert!(mirror.completed_vote_artifact); + assert!(mirror.completed_for_display); + assert!(!mirror.needs_draft_setup); + assert_eq!(mirror.primary_action, "done"); + let display = mirror.completed_vote_display.unwrap(); + assert_eq!( + display.choices, + vec![ + VotingCompletedVoteChoice { + proposal_id: 3, + choice: Some(1), + }, + VotingCompletedVoteChoice { + proposal_id: 4, + choice: None, + }, + ] + ); + assert_eq!(display.voted_at, Some(42)); + } + + #[test] + fn delegation_recovery_from_maps_all_fields() { + let fork = ForkDelegationRecovery { + bundle_index: 1, + phase: DelegationPhase::Confirmed, + tx_hash: None, + van_leaf_position: Some(2), + }; + let mirror = VotingDelegationRecovery::from(fork); + assert_eq!(mirror.bundle_index, 1); + assert_eq!(mirror.phase, "confirmed"); + assert_eq!(mirror.workflow_phase, "confirmed"); + assert_eq!(mirror.tx_hash, None); + assert_eq!(mirror.van_leaf_position, Some(2)); + } + + #[test] + fn vote_recovery_from_maps_all_fields() { + let fork = ForkVoteRecovery { + bundle_index: 1, + proposal_id: 2, + choice: 3, + phase: VotePhase::Submitted, + tx_hash: Some("t".to_string()), + vc_tree_position: Some(9), + has_commitment_bundle: true, + }; + let mirror = VotingVoteRecovery::from(fork); + assert_eq!(mirror.bundle_index, 1); + assert_eq!(mirror.proposal_id, 2); + assert_eq!(mirror.choice, 3); + assert_eq!(mirror.phase, "submitted"); + assert_eq!(mirror.workflow_phase, "submitted_vote"); + assert_eq!(mirror.tx_hash.as_deref(), Some("t")); + assert_eq!(mirror.vc_tree_position, Some(9)); + assert!(mirror.has_commitment_bundle); + } + + #[test] + fn share_workflow_from_maps_all_fields() { + let fork = ForkShareWorkflow { + bundle_index: 1, + proposal_id: 2, + share_index: 3, + phase: SharePhase::Confirmed, + }; + let mirror = VotingShareWorkflow::from(fork); + assert_eq!(mirror.bundle_index, 1); + assert_eq!(mirror.proposal_id, 2); + assert_eq!(mirror.share_index, 3); + assert_eq!(mirror.phase, "confirmed"); + } + + #[test] + fn share_delegation_record_from_maps_all_fields() { + let fork = ForkShareDelegationRecord { + round_id: "r".to_string(), + bundle_index: 1, + proposal_id: 2, + share_index: 3, + sent_to_urls: vec!["u1".to_string()], + nullifier: vec![1, 2, 3], + confirmed: true, + submit_at: 4, + created_at: 5, + }; + assert_eq!( + VotingShareDelegationRecord::from(fork), + VotingShareDelegationRecord { + round_id: "r".to_string(), + bundle_index: 1, + proposal_id: 2, + share_index: 3, + sent_to_urls: vec!["u1".to_string()], + nullifier: vec![1, 2, 3], + confirmed: true, + submit_at: 4, + created_at: 5, + } + ); + } + + #[test] + fn round_recovery_from_maps_all_fields() { + let fork = ForkRoundRecovery { + round_id: "r".to_string(), + bundle_count: 2, + delegation: vec![ForkDelegationRecovery { + bundle_index: 1, + phase: DelegationPhase::Proved, + tx_hash: None, + van_leaf_position: None, + }], + votes: vec![ForkVoteRecovery { + bundle_index: 1, + proposal_id: 2, + choice: 3, + phase: VotePhase::Committed, + tx_hash: None, + vc_tree_position: None, + has_commitment_bundle: true, + }], + commitment_bundles: vec![], + shares: vec![ForkShareWorkflow { + bundle_index: 1, + proposal_id: 2, + share_index: 3, + phase: SharePhase::Submitted, + }], + share_delegations: vec![ + ForkShareDelegationRecord { + round_id: "r".to_string(), + bundle_index: 1, + proposal_id: 2, + share_index: 3, + sent_to_urls: vec!["u1".to_string()], + nullifier: vec![1], + confirmed: false, + submit_at: 4, + created_at: 5, + }, + ForkShareDelegationRecord { + round_id: "r".to_string(), + bundle_index: 1, + proposal_id: 2, + share_index: 4, + sent_to_urls: vec![], + nullifier: vec![2], + confirmed: true, + submit_at: 6, + created_at: 7, + }, + ], + unconfirmed_share_delegations: vec![ForkShareDelegationRecord { + round_id: "r".to_string(), + bundle_index: 1, + proposal_id: 2, + share_index: 5, + sent_to_urls: vec![], + nullifier: vec![3], + confirmed: false, + submit_at: 8, + created_at: 9, + }], + }; + let mirror = VotingRoundRecovery::from(fork); + assert_eq!(mirror.round_id, "r"); + assert_eq!(mirror.bundle_count, 2); + assert_eq!(mirror.delegation.len(), 1); + assert_eq!(mirror.votes.len(), 1); + assert_eq!(mirror.shares.len(), 1); + assert_eq!(mirror.share_delegations.len(), 2); + assert_eq!(mirror.unconfirmed_share_delegations.len(), 1); + assert_eq!(mirror.votes[0].phase, "committed"); + assert_eq!(mirror.shares[0].phase, "submitted"); + } + + #[test] + fn ballot_intent_from_maps_choice_and_skipped() { + assert_eq!( + VotingBallotIntent::from((7u32, Decision::Choice(3))), + VotingBallotIntent { + proposal_id: 7, + skipped: false, + choice: Some(3), + } + ); + assert_eq!( + VotingBallotIntent::from((7u32, Decision::Skipped)), + VotingBallotIntent { + proposal_id: 7, + skipped: true, + choice: None, + } + ); + } + + #[test] + fn share_tracking_summary_from_maps_all_fields() { + let fork = ShareTrackingSummary { + total: 10, + confirmed: 6, + waiting: 2, + ready: 1, + overdue: 1, + }; + assert_eq!( + VotingShareTrackingSummary::from(fork), + VotingShareTrackingSummary { + total: 10, + confirmed: 6, + waiting: 2, + ready: 1, + overdue: 1, + } + ); + } + + #[test] + fn fork_network_string_maps_each_network() { + assert_eq!(fork_network_string(VotingNetwork::Mainnet), "mainnet"); + assert_eq!(fork_network_string(VotingNetwork::Testnet), "testnet"); + assert_eq!(fork_network_string(VotingNetwork::Regtest), "regtest"); + } + + #[test] + fn config_switch_kind_string_maps_each_kind() { + assert_eq!(config_switch_kind_string(ConfigSwitchKind::Unchanged), "unchanged"); + assert_eq!(config_switch_kind_string(ConfigSwitchKind::InitialLoad), "initial_load"); + assert_eq!( + config_switch_kind_string(ConfigSwitchKind::SameChainServiceUpdate), + "same_chain_service_update" + ); + assert_eq!( + config_switch_kind_string(ConfigSwitchKind::NewChainOrRound), + "new_chain_or_round" + ); + assert_eq!( + config_switch_kind_string(ConfigSwitchKind::ProtocolChanged), + "protocol_changed" + ); + } + + #[test] + fn votechain_proxy_uses_external_proxy_only_for_transport_three() { + assert_eq!( + votechain_proxy(&coin(3, "socks5://127.0.0.1:1080")), + "socks5://127.0.0.1:1080" + ); + assert_eq!(votechain_proxy(&coin(3, "")), ""); + assert_eq!(votechain_proxy(&coin(0, "socks5://x")), ""); + assert_eq!(votechain_proxy(&coin(1, "socks5://x")), ""); + assert_eq!(votechain_proxy(&coin(2, "socks5://x")), ""); + } + + fn resolved_config(pir_layout: PirLayout) -> ResolvedVotingConfig { + ResolvedVotingConfig { + source_fingerprint: "sf".to_string(), + trusted_key_fingerprint: "tf".to_string(), + dynamic_config_fingerprint: "df".to_string(), + vote_servers: vec![ + ServiceEndpoint { + url: "https://v1".to_string(), + label: "vote".to_string(), + }, + ServiceEndpoint { + url: "https://v2".to_string(), + label: "vote2".to_string(), + }, + ], + pir_endpoints: vec![ServiceEndpoint { + url: "https://p".to_string(), + label: "pir".to_string(), + }], + pir_layout, + supported_versions: SupportedVersions { + pir: vec!["1".to_string()], + vote_protocol: "v1".to_string(), + tally: "t1".to_string(), + vote_server: "s1".to_string(), + }, + authenticated_rounds: vec![ + AuthenticatedRound { + round_id: "r1".to_string(), + ea_pk: vec![1, 2], + }, + AuthenticatedRound { + round_id: "r2".to_string(), + ea_pk: vec![3], + }, + ], + skipped_round_ids: vec!["r9".to_string()], + conditions: vec![ConfigCondition { + kind: ConfigConditionKind::VersionsSupported, + status: true, + message: "m".to_string(), + }], + } + } + + #[test] + fn voting_config_from_resolved_maps_all_fields() { + let layout = PirLayout { + pir_depth: 4, + tier0_layers: 2, + tier1_layers: 3, + poly_len: 2048, + }; + let config = VotingConfig::from_resolved( + "https://src".to_string(), + &resolved_config(layout), + ConfigSwitchKind::NewChainOrRound, + ); + assert_eq!(config.source, "https://src"); + assert_eq!(config.source_fingerprint, "sf"); + assert_eq!(config.trusted_key_fingerprint, "tf"); + assert_eq!(config.switch_kind, "new_chain_or_round"); + assert_eq!( + config.vote_servers, + vec![ + VotingServiceEndpoint { + url: "https://v1".to_string(), + label: "vote".to_string(), + }, + VotingServiceEndpoint { + url: "https://v2".to_string(), + label: "vote2".to_string(), + }, + ] + ); + assert_eq!( + config.pir_servers, + vec![VotingServiceEndpoint { + url: "https://p".to_string(), + label: "pir".to_string(), + }] + ); + assert_eq!( + config.pir_layout, + Some(VotingPirLayout { + pir_depth: 4, + tier0_layers: 2, + tier1_layers: 3, + poly_len: 2048, + }) + ); + assert_eq!( + config.rounds, + vec![ + VotingConfigRound { + round_id: "r1".to_string(), + ea_pk: vec![1, 2], + }, + VotingConfigRound { + round_id: "r2".to_string(), + ea_pk: vec![3], + }, + ] + ); + } + + #[test] + fn voting_config_from_resolved_maps_unknown_pir_layout_to_none() { + let config = VotingConfig::from_resolved( + "https://src".to_string(), + &resolved_config(PirLayout::UNKNOWN), + ConfigSwitchKind::InitialLoad, + ); + assert_eq!(config.pir_layout, None); + assert_eq!(config.switch_kind, "initial_load"); + } + + #[test] + fn share_delivery_parses_dart_wire_json() { + let json = r#"{"share_index":1,"sent_to_urls":["https://h1","https://h2"],"submit_at":42,"confirmed":true}"#; + let parsed: VotingShareDelivery = serde_json::from_str(json).unwrap(); + assert_eq!( + parsed, + VotingShareDelivery { + share_index: 1, + sent_to_urls: vec!["https://h1".to_string(), "https://h2".to_string()], + submit_at: 42, + confirmed: true, + } + ); + } + + #[test] + fn progress_and_stage_enums_serde_round_trip() { + assert_round_trips(VotingDelegationProgress::SelectingNotes); + assert_round_trips(VotingDelegationProgress::ProofProgress { progress: 0.25 }); + assert_round_trips(VotingVoteCommitStage::Signing { + proposal_id: 1, + bundle_index: 2, + }); + assert_round_trips(VotingVoteCommitStage::ProofProgress { + proposal_id: 3, + bundle_index: 4, + progress: 0.5, + }); + } + + #[test] + fn leaf_flow_structs_serde_round_trip() { + assert_round_trips(VotingDelegationSetup { + pczt_bytes: vec![1], + pczt_sighash: vec![2u8; 32], + rk: vec![3u8; 32], + action_index: 4, + action_bytes: vec![5], + tx1_effects: vec![6], + }); + assert_round_trips(VotingDelegationSubmission { + proof: vec![1], + rk: vec![2u8; 32], + nf_signed: vec![3u8; 32], + cmx_new: vec![4u8; 32], + gov_comm: vec![5u8; 32], + gov_nullifiers: vec![vec![6u8; 32], vec![7u8; 32]], + alpha: vec![8u8; 32], + vote_round_id: "r".to_string(), + spend_auth_sig: vec![9u8; 64], + sighash: vec![10u8; 32], + tx1_effects: vec![11], + }); + assert_round_trips(VotingDelegationConfirmation { + tx_hash: "0x1".to_string(), + van_leaf_position: 1, + }); + assert_round_trips(VotingVoteConfirmation { + tx_hash: "0x2".to_string(), + van_leaf_position: 2, + vc_tree_position: 3, + }); + assert_round_trips(VotingVanWitness { + auth_path: vec![vec![1], vec![2, 3]], + position: 4, + anchor_height: 5, + }); + assert_round_trips(VotingVoteSubmission { + vote_round_id: "r".to_string(), + proposal_id: 1, + van_nullifier: vec![2u8; 32], + vote_authority_note_new: vec![3u8; 32], + vote_commitment: vec![4u8; 32], + proof: vec![5], + r_vpk: vec![6u8; 32], + vote_auth_sig: vec![7u8; 64], + anchor_height: 8, + }); + assert_round_trips(VotingEncryptedShare { + c1: vec![1], + c2: vec![2], + share_index: 3, + }); + } + + #[test] + fn nested_and_config_structs_serde_round_trip() { + assert_round_trips(VotingSharePayload { + shares_hash: vec![1], + proposal_id: 2, + vote_decision: 3, + enc_share: VotingEncryptedShare { + c1: vec![4], + c2: vec![5], + share_index: 6, + }, + tree_position: 7, + all_enc_shares: vec![VotingEncryptedShare { + c1: vec![8], + c2: vec![9], + share_index: 10, + }], + share_comms: vec![vec![11]], + primary_blind: vec![12], + }); + assert_round_trips(VotingShareDelivery { + share_index: 1, + sent_to_urls: vec!["https://h1".to_string()], + submit_at: 42, + confirmed: false, + }); + assert_round_trips(VotingRoundInfo { + round_id: "r".to_string(), + network: "regtest".to_string(), + snapshot_height: 100, + hotkey_address: None, + eligible_weight_zatoshi: Some(50_000), + bundle_count: 2, + created_at: 123, + }); + assert_round_trips(VotingBallotIntent { + proposal_id: 1, + skipped: false, + choice: Some(2), + }); + assert_round_trips(VotingShareTrackingSummary { + total: 10, + confirmed: 6, + waiting: 2, + ready: 1, + overdue: 1, + }); + assert_round_trips(VotingConfig { + source: "https://src".to_string(), + source_fingerprint: "sf".to_string(), + trusted_key_fingerprint: "tf".to_string(), + switch_kind: "initial_load".to_string(), + vote_servers: vec![VotingServiceEndpoint { + url: "https://v".to_string(), + label: "vote".to_string(), + }], + pir_servers: vec![], + pir_layout: Some(VotingPirLayout { + pir_depth: 4, + tier0_layers: 2, + tier1_layers: 3, + poly_len: 2048, + }), + rounds: vec![VotingConfigRound { + round_id: "r1".to_string(), + ea_pk: vec![1, 2], + }], + }); + assert_round_trips(VotingDelegationBuild { + submission: VotingDelegationSubmission { + proof: vec![1], + rk: vec![2u8; 32], + nf_signed: vec![3u8; 32], + cmx_new: vec![4u8; 32], + gov_comm: vec![5u8; 32], + gov_nullifiers: vec![], + alpha: vec![6u8; 32], + vote_round_id: "r".to_string(), + spend_auth_sig: vec![7u8; 64], + sighash: vec![8u8; 32], + tx1_effects: vec![9], + }, + wire_json: "{}".to_string(), + }); + assert_round_trips(VotingVotePayloads { + submission: VotingVoteSubmission { + vote_round_id: "r".to_string(), + proposal_id: 1, + van_nullifier: vec![2u8; 32], + vote_authority_note_new: vec![3u8; 32], + vote_commitment: vec![4u8; 32], + proof: vec![5], + r_vpk: vec![6u8; 32], + vote_auth_sig: vec![7u8; 64], + anchor_height: 8, + }, + share_payloads: vec![], + }); + assert_round_trips(VotingRoundPlan { + round_id: "r".to_string(), + pending_recovery: false, + next_steps: vec![], + open_proposals: vec![], + all_decided: true, + delegation_statuses: vec![], + blocking_recovery: false, + blocking_share_work: false, + hotkey_bound: false, + completed_vote_artifact: false, + completed_for_display: false, + completed_vote_display: None, + needs_draft_setup: false, + primary_action: "done".to_string(), + }); + assert_round_trips(VotingRoundRecovery { + round_id: "r".to_string(), + bundle_count: 0, + delegation: vec![], + votes: vec![], + shares: vec![], + share_delegations: vec![], + unconfirmed_share_delegations: vec![], + }); + assert_round_trips(VotingSharePlan { + summary: VotingShareTrackingSummary { + total: 1, + confirmed: 0, + waiting: 1, + ready: 0, + overdue: 0, + }, + next_tracking_delay_secs: Some(30), + last_moment: false, + submissions: vec![VotingSharePlanItem { + submit_at: 100, + target_count: 1, + target_servers: vec!["https://h".to_string()], + }], + }); + } +} diff --git a/rust/src/voting.rs b/rust/src/voting.rs index ecde0e875..c62839423 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -30,7 +30,9 @@ use zcash_voting::prelude::{ VanWitness, VoteCommitStageReporter, VoteConfirmation, VoteSigner, VoteSubmission, VotingDb, VotingHotkey, WitnessData, }; -use zcash_voting::{Network as VotingNetwork, VotingRoundParams}; +use zcash_voting::{ + minimum_voting_eligibility_for_notes, Network as VotingNetwork, VotingRoundParams, +}; use crate::api::coin::Network as WalletNetwork; use crate::warp::hasher::{empty_roots, OrchardHasher}; @@ -343,6 +345,70 @@ async fn unspent_ironwood_notes( Ok(notes) } +/// Computes the quantized voting weight for the account's currently-unspent +/// Ironwood ZEC notes at `snapshot_height`, using the same canonical bundle +/// planning as the delegation prepare step (sort by value, greedy chunking, +/// per-bundle ballot quantization) — but from the local DB only: no tree +/// state, no witnesses. +/// +/// Notes received after the snapshot are excluded, mirroring the prepare-time +/// rejection (their witness cannot anchor at the snapshot tree). +pub async fn eligible_voting_weight( + connection: &mut SqliteConnection, + account: u32, + snapshot_height: u32, +) -> Result { + let rows = sqlx::query( + "SELECT a.value, a.position, a.cmx, a.nullifier, a.scope, a.diversifier, a.rcm, a.rho + FROM notes a + LEFT JOIN spends b ON a.id_note = b.id_note + LEFT JOIN assets ast ON a.id_asset = ast.id_asset + WHERE b.id_note IS NULL AND a.account = ? + AND a.pool = 3 AND a.locked = 0 + AND a.height <= ? + AND COALESCE(ast.asset_base, X'0000000000000000000000000000000000000000000000000000000000000000') = X'0000000000000000000000000000000000000000000000000000000000000000'", + ) + .bind(account) + .bind(snapshot_height) + .map(|row: sqlx::sqlite::SqliteRow| { + ( + row.get::(0) as u64, // value + row.get::(1), // position + row.get::, _>(2), // cmx + row.get::, _>(3), // nullifier + row.get::, _>(4), // scope + row.get::, _>(5), // diversifier + row.get::, _>(6), // rcm (rseed) + row.get::, _>(7), // rho + ) + }) + .fetch_all(&mut *connection) + .await?; + + let notes: Vec = rows + .into_iter() + .map( + |(value, position, cmx, nullifier, scope, diversifier, rcm, rho)| NoteInfo { + commitment: cmx, + nullifier, + value, + position: position as u64, + diversifier, + rho, + rseed: rcm, + scope: scope.unwrap_or(0) as u32, + ufvk_str: String::new(), + }, + ) + .collect(); + + Ok( + minimum_voting_eligibility_for_notes(¬es, BundlePolicy::default()) + .map(|e| e.eligible_weight) + .unwrap_or(0), + ) +} + async fn unified_full_viewing_key( network: &WalletNetwork, connection: &mut SqliteConnection, @@ -744,3 +810,195 @@ pub fn load_prepared_bundle( anyhow!("delegation bundle not prepared; run delegation_prepare first") }) } + +#[cfg(test)] +mod tests { + use super::*; + use halo2_proofs::pasta::pallas::Scalar; + use orchard::primitives::redpallas::{Signature, VerificationKey}; + use zcash_protocol::{ + consensus::{BlockHeight, OrchardMode}, + local_consensus::LocalNetwork, + }; + use zip32::fingerprint::SeedFingerprint; + + /// Standard BIP-39 test vector; its 64-byte seed is valid for ZIP-32. + fn test_seed() -> Vec { + Mnemonic::parse( + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + ) + .unwrap() + .to_seed("") + .to_vec() + } + + fn local_network() -> LocalNetwork { + LocalNetwork { + overwinter: Some(BlockHeight::from_u32(1)), + sapling: Some(BlockHeight::from_u32(1)), + blossom: Some(BlockHeight::from_u32(1)), + heartwood: Some(BlockHeight::from_u32(1)), + canopy: Some(BlockHeight::from_u32(1)), + nu5: Some(BlockHeight::from_u32(1)), + nu6: Some(BlockHeight::from_u32(1)), + nu6_1: Some(BlockHeight::from_u32(1)), + nu6_2: Some(BlockHeight::from_u32(1)), + nu6_3: Some(BlockHeight::from_u32(250)), + nu7: None, + orchard_mode: OrchardMode::Normal, + } + } + + fn signing_request( + fingerprint: [u8; 32], + account_index: u32, + alpha: [u8; 32], + ) -> DelegationSigningRequest { + DelegationSigningRequest { + account_index, + network: VotingNetwork::Mainnet, + seed_fingerprint: fingerprint, + sighash: [7u8; 32], + alpha, + } + } + + /// Rebuilds the signing key from the request the same way + /// `sign_delegation_request` does, and verifies the returned signature. + fn assert_valid_signature( + request: &DelegationSigningRequest, + seed: &[u8], + sig_bytes: &[u8; 64], + ) { + let account = AccountId::try_from(request.account_index).unwrap(); + let usk = UnifiedSpendingKey::from_seed(&request.network, seed, account).unwrap(); + let sk = *usk.orchard(); + let ask = orchard::keys::SpendAuthorizingKey::from(&sk); + let alpha = Scalar::from_repr(request.alpha).unwrap(); + let vk = VerificationKey::from(&ask.randomize(&alpha)); + let sig = Signature::from(*sig_bytes); + vk.verify(&request.sighash, &sig).unwrap(); + } + + #[test] + fn voting_network_maps_each_wallet_network_to_fork_network() { + assert_eq!( + voting_network(&WalletNetwork::Main).unwrap(), + VotingNetwork::Mainnet + ); + assert_eq!( + voting_network(&WalletNetwork::Test).unwrap(), + VotingNetwork::Testnet + ); + assert_eq!( + voting_network(&WalletNetwork::Regtest(local_network())).unwrap(), + VotingNetwork::Regtest + ); + } + + #[test] + fn voting_network_rejects_zsa_regtest() { + let err = voting_network(&WalletNetwork::ZsaRegtest(local_network())).unwrap_err(); + assert_eq!(err.to_string(), "voting is not supported on the ZSA network"); + } + + #[test] + fn sign_delegation_request_rejects_invalid_seed_length() { + let request = signing_request([0u8; 32], 0, [0u8; 32]); + let err = sign_delegation_request(&[0xAAu8; 16], request).unwrap_err(); + assert_eq!( + err.to_string(), + "wallet seed length is not valid for ZIP-32" + ); + } + + #[test] + fn sign_delegation_request_rejects_seed_fingerprint_mismatch() { + let seed = test_seed(); + let mut fingerprint = SeedFingerprint::from_seed(&seed).unwrap().to_bytes(); + fingerprint[0] ^= 0x01; + let request = signing_request(fingerprint, 0, [0u8; 32]); + let err = sign_delegation_request(&seed, request).unwrap_err(); + assert_eq!( + err.to_string(), + "wallet seed fingerprint does not match delegation signing request" + ); + } + + #[test] + fn sign_delegation_request_rejects_account_index_at_or_above_2_to_31() { + let seed = test_seed(); + let fingerprint = SeedFingerprint::from_seed(&seed).unwrap().to_bytes(); + let request = signing_request(fingerprint, 1 << 31, [0u8; 32]); + let err = sign_delegation_request(&seed, request).unwrap_err(); + assert_eq!(err.to_string(), "invalid account_index 2147483648"); + + // One below the boundary passes the account-index check; the request + // then fails on the intentionally non-canonical alpha, pinning the + // exact boundary. + let request = signing_request(fingerprint, (1 << 31) - 1, [0xFFu8; 32]); + let err = sign_delegation_request(&seed, request).unwrap_err(); + assert_eq!( + err.to_string(), + "delegation alpha is not a valid Pallas scalar" + ); + } + + #[test] + fn sign_delegation_request_rejects_noncanonical_alpha() { + let seed = test_seed(); + let fingerprint = SeedFingerprint::from_seed(&seed).unwrap().to_bytes(); + let request = signing_request(fingerprint, 0, [0xFFu8; 32]); + let err = sign_delegation_request(&seed, request).unwrap_err(); + assert_eq!( + err.to_string(), + "delegation alpha is not a valid Pallas scalar" + ); + } + + #[test] + fn sign_delegation_request_signs_with_zero_alpha_and_returns_sighash() { + let seed = test_seed(); + let fingerprint = SeedFingerprint::from_seed(&seed).unwrap().to_bytes(); + let request = signing_request(fingerprint, 0, [0u8; 32]); + let (sig_bytes, sighash) = sign_delegation_request(&seed, request).unwrap(); + assert_eq!(sighash, [7u8; 32]); + assert_valid_signature(&request, &seed, &sig_bytes); + } + + #[test] + fn sign_delegation_request_signs_with_nonzero_alpha_under_randomized_key() { + let seed = test_seed(); + let fingerprint = SeedFingerprint::from_seed(&seed).unwrap().to_bytes(); + let mut alpha = [0u8; 32]; + alpha[0] = 7; + let request = signing_request(fingerprint, 0, alpha); + let (sig_bytes, _) = sign_delegation_request(&seed, request).unwrap(); + assert_valid_signature(&request, &seed, &sig_bytes); + + // Negative control: the *unrandomized* ak must not verify, proving + // the alpha randomizer actually enters the signing key. + let account = AccountId::try_from(request.account_index).unwrap(); + let usk = UnifiedSpendingKey::from_seed(&request.network, &seed, account).unwrap(); + let ask = orchard::keys::SpendAuthorizingKey::from(&*usk.orchard()); + let zero = Scalar::from_repr([0u8; 32]).unwrap(); + let vk_ak = VerificationKey::from(&ask.randomize(&zero)); + let sig = Signature::from(sig_bytes); + assert!(vk_ak.verify(&request.sighash, &sig).is_err()); + } + + #[test] + fn bundle_cache_key_formats_wallet_round_bundle() { + assert_eq!( + bundle_cache_key("wallet-abc", "round-42", 0), + "wallet-abc:round-42:0" + ); + assert_eq!(bundle_cache_key("w", "r", u32::MAX), "w:r:4294967295"); + assert_eq!(bundle_cache_key("", "", 0), "::0"); + assert_ne!( + bundle_cache_key("a", "r", 1), + bundle_cache_key("b", "r", 1), + "different wallet ids must not share a cache key" + ); + } +} From 0a7472cb5913446cb6fe74a2e65b3fa0dd25d81a Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 01:21:27 +0800 Subject: [PATCH 072/189] feat: show voting power on voting confirmation and status pages --- Cargo.lock | 6 +-- lib/pages/voting_confirmation.dart | 12 +++++ lib/pages/voting_proposal.dart | 43 ++++++++++++---- lib/pages/voting_status.dart | 9 ++++ lib/src/rust/api/voting.dart | 9 ++++ lib/src/rust/frb_generated.dart | 74 +++++++++++++++++++-------- lib/store.dart | 42 ++++++++------- lib/store.freezed.dart | 75 +++++++++++++++++++++------ lib/store.g.dart | 2 +- lib/utils.dart | 8 +++ rust/src/frb_generated.rs | 82 ++++++++++++++++++++++-------- rust/src/plugin/rhai_api.rs | 4 +- 12 files changed, 275 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7b724f96..0598d1cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13211,7 +13211,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "anyhow", "ff", @@ -13227,7 +13227,7 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "base64 0.22.1", "ff", @@ -14365,7 +14365,7 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fd4362b097579782565de553b7b8c5a612cda1e2#fd4362b097579782565de553b7b8c5a612cda1e2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 588d2af87..5e34c0de0 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart'; import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; /// Receipt screen shown after the submission job completes. class VotingConfirmationPage extends ConsumerStatefulWidget { @@ -21,6 +22,8 @@ class VotingConfirmationPageState extends ConsumerState final pinlock = ref.watch(lifecycleProvider); if (pinlock.value ?? false) return PinLock(); + final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); + return Scaffold( appBar: AppBar(title: const Text("Vote submitted")), body: Center( @@ -41,6 +44,15 @@ class VotingConfirmationPageState extends ConsumerState style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), + if (job.eligibleWeightZatoshi != null) + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + "Voting power: ${formatVotingPower(job.eligibleWeightZatoshi!)}", + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + ), const SizedBox(height: 24), FilledButton( onPressed: () => GoRouter.of(context).go("/voting"), diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index 0a712d994..709f809d9 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart'; import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; /// One parsed proposal option. @@ -55,6 +56,7 @@ class VotingProposalPageState extends ConsumerState { String? _roundParamsJson; String? _roundName; int? _snapshotHeight; + BigInt? _votingPower; @override void initState() { @@ -102,6 +104,8 @@ class VotingProposalPageState extends ConsumerState { final nullifierImtRoot = _find(round, "nullifier_imt_root"); if (snapshotHeight is int && ncRoot is String && nullifierImtRoot is String) { _snapshotHeight = snapshotHeight; + _votingPower = + await votingEligibleWeight(snapshotHeight: snapshotHeight, c: c); _roundName = (_find(round, "round_name") ?? _find(round, "name")) ?.toString() ?? widget.roundId; @@ -280,17 +284,34 @@ class VotingProposalPageState extends ConsumerState { bottomNavigationBar: SafeArea( child: Padding( padding: const EdgeInsets.all(12), - child: FilledButton( - onPressed: allAnswered - ? () => GoRouter.of(context).push("/voting/review", extra: { - "roundId": widget.roundId, - "chainUrl": widget.chainUrl, - "roundParamsJson": _roundParamsJson, - "roundName": _roundName, - "snapshotHeight": _snapshotHeight, - }) - : null, - child: const Text("Review answers"), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (_snapshotHeight != null) + Text( + "Snapshot height: $_snapshotHeight", + textAlign: TextAlign.center, + ), + if (_votingPower != null) + Text( + "Voting power: ${formatVotingPower(_votingPower!)}", + textAlign: TextAlign.center, + ), + if (_snapshotHeight != null || _votingPower != null) + const SizedBox(height: 8), + FilledButton( + onPressed: allAnswered + ? () => GoRouter.of(context).push("/voting/review", extra: { + "roundId": widget.roundId, + "chainUrl": widget.chainUrl, + "roundParamsJson": _roundParamsJson, + "roundName": _roundName, + "snapshotHeight": _snapshotHeight, + }) + : null, + child: const Text("Review answers"), + ), + ], ), ), ), diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index fb5c738ca..4d804fef5 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -149,6 +149,15 @@ class VotingStatusPageState extends ConsumerState { textAlign: TextAlign.center, ), ), + if (job.eligibleWeightZatoshi != null) + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + "Voting power: ${formatVotingPower(job.eligibleWeightZatoshi!)}", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium, + ), + ), const SizedBox(height: 24), if (job.stage == "error") ...[ Text( diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index 108e8b8a4..ec5aa2951 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -163,6 +163,15 @@ Future votingSetBallotIntent( numOptions: numOptions, c: c); +/// Returns the quantized voting weight (zatoshi) for the account's eligible +/// shielded notes at `snapshot_height`, computed with the same canonical +/// bundle planning as the delegation prepare step — but from the local DB +/// only (no witnesses, no tree state). Shown pre-submission as an estimate. +Future votingEligibleWeight( + {required int snapshotHeight, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingEligibleWeight( + snapshotHeight: snapshotHeight, c: c); + /// Persists the draft ballot for a round (props table, wallet-scoped). Future votingDraftsSave( {required String roundId, diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index d646a82c1..f6339f485 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 1766202353; + int get rustContentHash => -440572071; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -746,6 +746,9 @@ abstract class RustLibApi extends BaseApi { Future crateApiVotingVotingDraftsSave( {required String roundId, required String draftsJson, required Coin c}); + Future crateApiVotingVotingEligibleWeight( + {required int snapshotHeight, required Coin c}); + Future crateApiVotingVotingHotkeyCreate({required Coin c}); Future crateApiVotingVotingHotkeyGet({required Coin c}); @@ -6945,15 +6948,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiVotingVotingHotkeyCreate({required Coin c}) { + Future crateApiVotingVotingEligibleWeight( + {required int snapshotHeight, required Coin c}) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(snapshotHeight, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 204, port: port_); }, + codec: SseCodec( + decodeSuccessData: sse_decode_u_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingEligibleWeightConstMeta, + argValues: [snapshotHeight, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingEligibleWeightConstMeta => + const TaskConstMeta( + debugName: "voting_eligible_weight", + argNames: ["snapshotHeight", "c"], + ); + + @override + Future crateApiVotingVotingHotkeyCreate({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 205, port: port_); + }, codec: SseCodec( decodeSuccessData: sse_decode_String, decodeErrorData: sse_decode_AnyhowException, @@ -6979,7 +7011,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 205, port: port_); + funcId: 206, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7015,7 +7047,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txHash, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 206, port: port_); + funcId: 207, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7049,7 +7081,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 207, port: port_); + funcId: 208, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_payloads, @@ -7081,7 +7113,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(proposalIds, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 208, port: port_); + funcId: 209, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_plan, @@ -7120,7 +7152,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(shareDeliveriesJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 209, port: port_); + funcId: 210, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7165,7 +7197,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 210, port: port_); + funcId: 211, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_recovery, @@ -7194,7 +7226,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 211, port: port_); + funcId: 212, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7232,7 +7264,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(nullifierImtRoot, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 212, port: port_); + funcId: 213, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7273,7 +7305,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 213, port: port_); + funcId: 214, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_info, @@ -7310,7 +7342,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 214, port: port_); + funcId: 215, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7355,7 +7387,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 215, port: port_); + funcId: 216, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7398,7 +7430,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 216, port: port_); + funcId: 217, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7438,7 +7470,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 217, port: port_); + funcId: 218, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7494,7 +7526,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 218, port: port_); + funcId: 219, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7540,7 +7572,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + funcId: 220, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7580,7 +7612,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + funcId: 221, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7626,7 +7658,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7660,7 +7692,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -7694,7 +7726,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + funcId: 224, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, diff --git a/lib/store.dart b/lib/store.dart index 0332e2105..84b58f368 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1417,6 +1417,9 @@ sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { required String stage, // idle|preparing|proving|submitting|confirming|done|error required double progress, String? error, + /// Voting weight (zatoshi) delegated by the prepared bundle, shown in + /// the status UI once the delegation prepare step completes. + BigInt? eligibleWeightZatoshi, }) = _VotingSubmissionJobState; } @@ -1515,25 +1518,26 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { String? txHash; if (delegateStep != null) { state = state.copyWith(stage: "preparing"); - if (roundParamsJson != null && roundName != null) { - await delegationPrepare( - roundParamsJson: roundParamsJson, - roundName: roundName, - sessionJson: null, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl ?? "", - c: c, - ); - } else { - await delegationPrepareResume( - roundId: roundId, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl, - c: c, - ); - } + final prepared = roundParamsJson != null && roundName != null + ? await delegationPrepare( + roundParamsJson: roundParamsJson, + roundName: roundName, + sessionJson: null, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl ?? "", + c: c, + ) + : await delegationPrepareResume( + roundId: roundId, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c, + ); + state = state.copyWith( + eligibleWeightZatoshi: prepared.eligibleWeightZatoshi, + ); final setup = await delegationSetup( roundId: roundId, diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index 2ecb9bcaf..d786756a3 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -5053,6 +5053,10 @@ mixin _$VotingSubmissionJobState { double get progress; String? get error; + /// Voting weight (zatoshi) delegated by the prepared bundle, shown in + /// the status UI once the delegation prepare step completes. + BigInt? get eligibleWeightZatoshi; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -5069,15 +5073,18 @@ mixin _$VotingSubmissionJobState { (identical(other.stage, stage) || other.stage == stage) && (identical(other.progress, progress) || other.progress == progress) && - (identical(other.error, error) || other.error == error)); + (identical(other.error, error) || other.error == error) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi)); } @override - int get hashCode => Object.hash(runtimeType, stage, progress, error); + int get hashCode => + Object.hash(runtimeType, stage, progress, error, eligibleWeightZatoshi); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi)'; } } @@ -5087,7 +5094,11 @@ abstract mixin class $VotingSubmissionJobStateCopyWith<$Res> { $Res Function(VotingSubmissionJobState) _then) = _$VotingSubmissionJobStateCopyWithImpl; @useResult - $Res call({String stage, double progress, String? error}); + $Res call( + {String stage, + double progress, + String? error, + BigInt? eligibleWeightZatoshi}); } /// @nodoc @@ -5106,6 +5117,7 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> Object? stage = null, Object? progress = null, Object? error = freezed, + Object? eligibleWeightZatoshi = freezed, }) { return _then(_self.copyWith( stage: null == stage @@ -5120,6 +5132,10 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.error : error // ignore: cast_nullable_to_non_nullable as String?, + eligibleWeightZatoshi: freezed == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } @@ -5215,13 +5231,16 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult maybeWhen( - TResult Function(String stage, double progress, String? error)? $default, { + TResult Function(String stage, double progress, String? error, + BigInt? eligibleWeightZatoshi)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _VotingSubmissionJobState() when $default != null: - return $default(_that.stage, _that.progress, _that.error); + return $default(_that.stage, _that.progress, _that.error, + _that.eligibleWeightZatoshi); case _: return orElse(); } @@ -5242,12 +5261,15 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult when( - TResult Function(String stage, double progress, String? error) $default, + TResult Function(String stage, double progress, String? error, + BigInt? eligibleWeightZatoshi) + $default, ) { final _that = this; switch (_that) { case _VotingSubmissionJobState(): - return $default(_that.stage, _that.progress, _that.error); + return $default(_that.stage, _that.progress, _that.error, + _that.eligibleWeightZatoshi); } } @@ -5265,12 +5287,15 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String stage, double progress, String? error)? $default, + TResult? Function(String stage, double progress, String? error, + BigInt? eligibleWeightZatoshi)? + $default, ) { final _that = this; switch (_that) { case _VotingSubmissionJobState() when $default != null: - return $default(_that.stage, _that.progress, _that.error); + return $default(_that.stage, _that.progress, _that.error, + _that.eligibleWeightZatoshi); case _: return null; } @@ -5281,7 +5306,10 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { class _VotingSubmissionJobState implements VotingSubmissionJobState { _VotingSubmissionJobState( - {required this.stage, required this.progress, this.error}); + {required this.stage, + required this.progress, + this.error, + this.eligibleWeightZatoshi}); @override final String stage; @@ -5291,6 +5319,11 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { @override final String? error; + /// Voting weight (zatoshi) delegated by the prepared bundle, shown in + /// the status UI once the delegation prepare step completes. + @override + final BigInt? eligibleWeightZatoshi; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @override @@ -5308,15 +5341,18 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { (identical(other.stage, stage) || other.stage == stage) && (identical(other.progress, progress) || other.progress == progress) && - (identical(other.error, error) || other.error == error)); + (identical(other.error, error) || other.error == error) && + (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || + other.eligibleWeightZatoshi == eligibleWeightZatoshi)); } @override - int get hashCode => Object.hash(runtimeType, stage, progress, error); + int get hashCode => + Object.hash(runtimeType, stage, progress, error, eligibleWeightZatoshi); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi)'; } } @@ -5328,7 +5364,11 @@ abstract mixin class _$VotingSubmissionJobStateCopyWith<$Res> __$VotingSubmissionJobStateCopyWithImpl; @override @useResult - $Res call({String stage, double progress, String? error}); + $Res call( + {String stage, + double progress, + String? error, + BigInt? eligibleWeightZatoshi}); } /// @nodoc @@ -5347,6 +5387,7 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> Object? stage = null, Object? progress = null, Object? error = freezed, + Object? eligibleWeightZatoshi = freezed, }) { return _then(_VotingSubmissionJobState( stage: null == stage @@ -5361,6 +5402,10 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.error : error // ignore: cast_nullable_to_non_nullable as String?, + eligibleWeightZatoshi: freezed == eligibleWeightZatoshi + ? _self.eligibleWeightZatoshi + : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } diff --git a/lib/store.g.dart b/lib/store.g.dart index e5919e4cd..dba9516bb 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1748,7 +1748,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'1009f94a4ecc110d5b99e5eef2edcc075608246e'; + r'9715bec132ec57c8d4851296748578307db3d5bf'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → diff --git a/lib/utils.dart b/lib/utils.dart index 65602367e..6c092d53c 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -45,6 +45,14 @@ final invertSeparator = NumberFormat.decimalPattern(locale).symbols.DECIMAL_SEP final int zatsPerZec = 100000000; +/// Formats raw zatoshi voting power as e.g. `12.5 ZEC` (up to 4 decimals). +String formatVotingPower(BigInt zatoshi) { + final zec = zatoshi.toDouble() / zatsPerZec; + var s = zec.toStringAsFixed(4); + s = s.replaceFirst(RegExp(r'\.?0+$'), ''); + return "$s ZEC"; +} + /// Format a fiat amount with its currency code. /// Uses the locale-aware number formatter followed by the uppercased currency code. String formatFiat(double amount, String currency) { diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 66fbae43f..bc1f9471c 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1766202353; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -440572071; // Section: executor @@ -8055,6 +8055,45 @@ fn wire__crate__api__voting__voting_drafts_save_impl( }, ) } +fn wire__crate__api__voting__voting_eligible_weight_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_eligible_weight", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_snapshot_height = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_eligible_weight(api_snapshot_height, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_hotkey_create_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -12270,65 +12309,68 @@ fn pde_ffi_dispatcher_primary_impl( 202 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), 203 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), 204 => { + wire__crate__api__voting__voting_eligible_weight_impl(port, ptr, rust_vec_len, data_len) + } + 205 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 205 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 206 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + 206 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 207 => wire__crate__api__voting__voting_mark_vote_submitted_impl( port, ptr, rust_vec_len, data_len, ), - 207 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 208 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), - 209 => wire__crate__api__voting__voting_record_execution_impl( + 208 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 209 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 210 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 210 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), - 211 => { + 211 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 212 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 212 => wire__crate__api__voting__voting_round_params_json_impl( + 213 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 213 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 214 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 214 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 215 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 215 => wire__crate__api__voting__voting_share_add_servers_impl( + 216 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 216 => { + 217 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 217 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 218 => { + 218 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 219 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 219 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 220 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 220 => { + 221 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 221 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 222 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 223 => { + 222 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 223 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 224 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), diff --git a/rust/src/plugin/rhai_api.rs b/rust/src/plugin/rhai_api.rs index 62d9677f6..d8304738f 100644 --- a/rust/src/plugin/rhai_api.rs +++ b/rust/src/plugin/rhai_api.rs @@ -5,7 +5,9 @@ //! `memo.read_string(offset, len)`, etc. The memo bytes are per-call state — //! no globals. -use rhai::{Blob, Dynamic, Engine, Scope}; +use rhai::{Blob, Dynamic, Engine}; +#[cfg(test)] +use rhai::Scope; /// Memo payload exposed to plugin scripts. /// From c48cf9e2b7194c78ca746af70a60fe446dbef654 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 05:18:45 +0800 Subject: [PATCH 073/189] fix: bundle sapling params in desktop and graphql builds Add a bundled-sapling-params cargo feature that embeds the Sapling proving parameters in the binary (via zcash_proofs/bundled-prover). When enabled, get_sapling_prover returns LocalTxProver::bundled() and the download APIs become no-ops; when disabled, behavior is unchanged. Enabled in CI for desktop (mac/linux/windows) and zkool_graphql server builds; mobile builds are unaffected. --- .github/actions/linux/action.yml | 2 +- .github/actions/mac/action.yml | 2 +- .github/actions/windows/action.yml | 2 +- .github/workflows/build-graphql.yml | 2 +- .github/workflows/wallet.yml | 2 +- Cargo.lock | 51 +++++++++++++++ rust/Cargo.toml | 1 + rust/src/api/sapling.rs | 97 +++++++++++++++++++---------- rust/src/pay/plan.rs | 27 +++++--- 9 files changed, 139 insertions(+), 47 deletions(-) diff --git a/.github/actions/linux/action.yml b/.github/actions/linux/action.yml index 63319ac7e..76a4c9856 100644 --- a/.github/actions/linux/action.yml +++ b/.github/actions/linux/action.yml @@ -39,7 +39,7 @@ runs: - name: Build shell: bash run: | - ./misc/mkcargokit_options.sh ledger > rust/cargokit.yaml + ./misc/mkcargokit_options.sh "ledger,bundled-sapling-params" > rust/cargokit.yaml fastforge package --platform=linux --targets=deb,appimage - name: Build Flatpak if: ${{ inputs.arch == 'x86_64' && github.event_name != 'pull_request' }} diff --git a/.github/actions/mac/action.yml b/.github/actions/mac/action.yml index 88687b237..42be2d301 100644 --- a/.github/actions/mac/action.yml +++ b/.github/actions/mac/action.yml @@ -41,7 +41,7 @@ runs: - name: Build shell: bash run: | - ./misc/mkcargokit_options.sh ledger > rust/cargokit.yaml + ./misc/mkcargokit_options.sh "ledger,bundled-sapling-params" > rust/cargokit.yaml flutter build macos - name: Notarization shell: bash diff --git a/.github/actions/windows/action.yml b/.github/actions/windows/action.yml index 3c5906ff8..af1123c23 100644 --- a/.github/actions/windows/action.yml +++ b/.github/actions/windows/action.yml @@ -22,7 +22,7 @@ runs: export PUB_CACHE="$RUNNER_TEMP/.pub-cache" dart pub global activate fastforge echo "$RUNNER_TEMP/.pub-cache/bin" >> $GITHUB_PATH - ./misc/mkcargokit_options.sh ledger > rust/cargokit.yaml + ./misc/mkcargokit_options.sh "ledger,bundled-sapling-params" > rust/cargokit.yaml - name: Build shell: powershell run: | diff --git a/.github/workflows/build-graphql.yml b/.github/workflows/build-graphql.yml index a4e1f22bc..75918d997 100644 --- a/.github/workflows/build-graphql.yml +++ b/.github/workflows/build-graphql.yml @@ -25,7 +25,7 @@ jobs: sudo apt-get update sudo apt-get install -y pkg-config libudev-dev cd rust - cargo build --release --bin zkool_graphql --features=graphql + cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params - name: Create Release if: startsWith(github.ref_name, 'zkool-v') uses: softprops/action-gh-release@v3 diff --git a/.github/workflows/wallet.yml b/.github/workflows/wallet.yml index abdf5fdb7..ef3d89d5f 100644 --- a/.github/workflows/wallet.yml +++ b/.github/workflows/wallet.yml @@ -29,7 +29,7 @@ jobs: sudo apt-get update sudo apt-get install -y pkg-config libudev-dev cd rust - cargo build --release --bin zkool_graphql --features=graphql + cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params - name: Run pytest tests run: | cd tests diff --git a/Cargo.lock b/Cargo.lock index 0598d1cb8..cde1998f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13259,6 +13259,56 @@ dependencies = [ "sinsemilla", ] +[[package]] +name = "wagyu-zcash-parameters" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c904628658374e651288f000934c33ef738b2d8b3e65d4100b70b395dbe2bb" +dependencies = [ + "wagyu-zcash-parameters-1", + "wagyu-zcash-parameters-2", + "wagyu-zcash-parameters-3", + "wagyu-zcash-parameters-4", + "wagyu-zcash-parameters-5", + "wagyu-zcash-parameters-6", +] + +[[package]] +name = "wagyu-zcash-parameters-1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bf2e21bb027d3f8428c60d6a720b54a08bf6ce4e6f834ef8e0d38bb5695da8" + +[[package]] +name = "wagyu-zcash-parameters-2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a616ab2e51e74cc48995d476e94de810fb16fc73815f390bf2941b046cc9ba2c" + +[[package]] +name = "wagyu-zcash-parameters-3" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14da1e2e958ff93c0830ee68e91884069253bf3462a67831b02b367be75d6147" + +[[package]] +name = "wagyu-zcash-parameters-4" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f058aeef03a2070e8666ffb5d1057d8bb10313b204a254a6e6103eb958e9a6d6" + +[[package]] +name = "wagyu-zcash-parameters-5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffe916b30e608c032ae1b734f02574a3e12ec19ab5cc5562208d679efe4969d" + +[[package]] +name = "wagyu-zcash-parameters-6" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b6d5a78adc3e8f198e9cd730f219a695431467f7ec29dcfc63ade885feebe1" + [[package]] name = "walkdir" version = "2.5.0" @@ -14297,6 +14347,7 @@ dependencies = [ "redjubjub", "sapling-crypto", "tracing", + "wagyu-zcash-parameters", "xdg", "zcash_primitives", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 3c40cdb14..f51cd5fa1 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -154,6 +154,7 @@ rand = "0.6" [features] default = ["flutter"] flutter = ["flutter_rust_bridge"] +bundled-sapling-params = ["zcash_proofs/bundled-prover"] graphql = ["juniper", "juniper_warp", "juniper_graphql_ws", "dataloader", "warp", "jsonwebtoken", "bigdecimal", "chrono", "figment", "clap"] ledger = ["hidapi", "ledger-transport"] zemu = ["ledger", "ledger-transport-zemu"] diff --git a/rust/src/api/sapling.rs b/rust/src/api/sapling.rs index 629b34fa2..98b46fefb 100644 --- a/rust/src/api/sapling.rs +++ b/rust/src/api/sapling.rs @@ -1,20 +1,30 @@ use std::path::PathBuf; use std::sync::OnceLock; -use anyhow::{anyhow, Context, Result}; +use anyhow::Result; +#[cfg(not(feature = "bundled-sapling-params"))] +use anyhow::{anyhow, Context}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; // Sapling parameter constants — must match those in zcash_proofs. +// Only needed when the parameters are loaded from disk (not bundled). +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_SPEND_NAME: &str = "sapling-spend.params"; +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_OUTPUT_NAME: &str = "sapling-output.params"; +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_SPEND_HASH: &str = "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c"; +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_OUTPUT_HASH: &str = "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028"; +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_SPEND_BYTES: u64 = 47_958_396; +#[cfg(not(feature = "bundled-sapling-params"))] const SAPLING_OUTPUT_BYTES: u64 = 3_592_860; +#[cfg(not(feature = "bundled-sapling-params"))] const DOWNLOAD_URL: &str = "https://download.z.cash/downloads"; /// Custom Sapling parameters directory, set on platforms where @@ -34,6 +44,7 @@ pub(crate) fn set_sapling_params_dir(dir: PathBuf) { /// /// Returns the custom directory if set (via `set_sapling_params_dir`), /// otherwise falls back to `zcash_proofs::default_params_folder()`. +#[cfg(not(feature = "bundled-sapling-params"))] pub(crate) fn resolve_params_dir() -> Option { SAFLING_PARAMS_DIR .get() @@ -47,54 +58,74 @@ pub struct SaplingParamsStatus { pub downloaded: bool, } -/// Check whether Sapling parameters are already on disk. +/// Check whether Sapling parameters are available. +/// +/// With `bundled-sapling-params` they are compiled into the binary and always +/// considered available. Otherwise checks whether they are on disk. #[cfg_attr(feature = "flutter", frb(sync))] pub fn check_sapling_params() -> SaplingParamsStatus { - let params_dir = resolve_params_dir(); - let downloaded = params_dir - .map(|dir| dir.join(SAPLING_SPEND_NAME).exists() && dir.join(SAPLING_OUTPUT_NAME).exists()) - .unwrap_or(false); - SaplingParamsStatus { downloaded } + #[cfg(feature = "bundled-sapling-params")] + { + return SaplingParamsStatus { downloaded: true }; + } + #[cfg(not(feature = "bundled-sapling-params"))] + { + let params_dir = resolve_params_dir(); + let downloaded = params_dir + .map(|dir| dir.join(SAPLING_SPEND_NAME).exists() && dir.join(SAPLING_OUTPUT_NAME).exists()) + .unwrap_or(false); + SaplingParamsStatus { downloaded } + } } /// Download Sapling parameters from the z.cash download server. /// /// Verifies file size and Blake2b hash upon download. /// Safe to call even if they are already downloaded (no-op if valid). +/// With `bundled-sapling-params` the parameters are compiled into the binary +/// and this is a no-op. #[cfg_attr(feature = "flutter", frb)] pub async fn download_sapling_params() -> Result<()> { - let params_dir = - resolve_params_dir().context("Could not resolve Sapling parameters directory")?; - - // Ensure the params directory exists. - std::fs::create_dir_all(¶ms_dir) - .with_context(|| format!("Failed to create params directory: {:?}", params_dir))?; - - download_and_verify( - ¶ms_dir, - SAPLING_SPEND_NAME, - SAPLING_SPEND_HASH, - SAPLING_SPEND_BYTES, - ) - .await - .context("Failed to download/verify sapling-spend.params")?; - - download_and_verify( - ¶ms_dir, - SAPLING_OUTPUT_NAME, - SAPLING_OUTPUT_HASH, - SAPLING_OUTPUT_BYTES, - ) - .await - .context("Failed to download/verify sapling-output.params")?; - - Ok(()) + #[cfg(feature = "bundled-sapling-params")] + { + Ok(()) + } + #[cfg(not(feature = "bundled-sapling-params"))] + { + let params_dir = + resolve_params_dir().context("Could not resolve Sapling parameters directory")?; + + // Ensure the params directory exists. + std::fs::create_dir_all(¶ms_dir) + .with_context(|| format!("Failed to create params directory: {:?}", params_dir))?; + + download_and_verify( + ¶ms_dir, + SAPLING_SPEND_NAME, + SAPLING_SPEND_HASH, + SAPLING_SPEND_BYTES, + ) + .await + .context("Failed to download/verify sapling-spend.params")?; + + download_and_verify( + ¶ms_dir, + SAPLING_OUTPUT_NAME, + SAPLING_OUTPUT_HASH, + SAPLING_OUTPUT_BYTES, + ) + .await + .context("Failed to download/verify sapling-output.params")?; + + Ok(()) + } } /// Download a single parameter file from `download.z.cash`, verify its size /// and Blake2b hash, then save it to the given directory. /// /// Skips download if an already-validated file exists at the target location. +#[cfg(not(feature = "bundled-sapling-params"))] async fn download_and_verify( dir: &PathBuf, name: &str, diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 19aac0388..9302b174e 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1557,17 +1557,26 @@ pub async fn get_sapling_prover() -> Result<&'static LocalTxProver> { static PROVER: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); PROVER .get_or_try_init(|| async { - let params_dir = crate::api::sapling::resolve_params_dir() - .ok_or_else(|| anyhow::anyhow!("Failed to resolve Sapling parameters directory"))?; - let spend_path = params_dir.join(zcash_proofs::SAPLING_SPEND_NAME); - let output_path = params_dir.join(zcash_proofs::SAPLING_OUTPUT_NAME); + #[cfg(feature = "bundled-sapling-params")] + { + // Parameters compiled into the binary — never touch disk or network. + return Ok(LocalTxProver::bundled()); + } + #[cfg(not(feature = "bundled-sapling-params"))] + { + let params_dir = crate::api::sapling::resolve_params_dir().ok_or_else(|| { + anyhow::anyhow!("Failed to resolve Sapling parameters directory") + })?; + let spend_path = params_dir.join(zcash_proofs::SAPLING_SPEND_NAME); + let output_path = params_dir.join(zcash_proofs::SAPLING_OUTPUT_NAME); - if spend_path.exists() && output_path.exists() { - return Ok(LocalTxProver::new(&spend_path, &output_path)); + if spend_path.exists() && output_path.exists() { + return Ok(LocalTxProver::new(&spend_path, &output_path)); + } + // Parameters not found on disk — download them. + crate::api::sapling::download_sapling_params().await?; + Ok(LocalTxProver::new(&spend_path, &output_path)) } - // Parameters not found on disk — download them. - crate::api::sapling::download_sapling_params().await?; - Ok(LocalTxProver::new(&spend_path, &output_path)) }) .await } From ed4b7520f57c12598f41583da189b6fcc8cc6770 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 07:36:19 +0800 Subject: [PATCH 074/189] fix: run fresh voting submissions end-to-end (delegate + vote) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A fresh round (Join -> ballot -> Confirm & submit) was a no-op: the submission job is driven by the fork's resume_plan, which only emits steps from existing DB state, so a never-joined round had no steps and finished instantly with 'All steps already confirmed' while recording nothing — the round stayed joinable after restart. Mirror vizor's sequencing: - pass draft proposal ids into votingPlan so needs_draft_setup (the fresh-round trigger) actually computes - _runDelegation: treat needs_draft_setup as delegation work for the first un-confirmed bundle (prepare/prove/broadcast/confirm), and fill missing PIR URL/layout from the resolved voting config - _runVotes: write ballot intents from drafts before reading the plan, reload the session, defer votes for bundles whose delegation is still pending, and sanitize drafts for the fork DraftVote deserializer (vc_tree_position/single_share, dropped skipped choices) - _runDelegation/_runVotes/_submitShares report whether they did work; the done label is honest: 'Delegation confirmed' / 'Votes submitted' / 'Shares submitted' / 'All steps already confirmed' Also: the confirmation poll now requires a positive block height (proof of inclusion, not just HTTP 200), and the status screen shows the tx hash + block height as verifiable evidence. --- lib/pages/voting_status.dart | 33 ++- lib/services/votechain_confirmation.dart | 37 +++ lib/store.dart | 236 ++++++++++++++---- lib/store.freezed.dart | 159 ++++++++++-- lib/store.g.dart | 2 +- .../services/votechain_confirmation_test.dart | 65 +++++ 6 files changed, 451 insertions(+), 81 deletions(-) create mode 100644 lib/services/votechain_confirmation.dart create mode 100644 test/services/votechain_confirmation_test.dart diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index 4d804fef5..78599b835 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -73,8 +73,8 @@ class VotingStatusPageState extends ConsumerState { ); } - String _stageLabel(String stage) { - switch (stage) { + String _stageLabel(VotingSubmissionJobState job) { + switch (job.stage) { case "preparing": return "Preparing delegation bundle"; case "proving": @@ -83,8 +83,12 @@ class VotingStatusPageState extends ConsumerState { return "Submitting delegation to the vote chain"; case "confirming": return "Waiting for confirmation"; + case "voting": + return "Casting votes"; + case "shares": + return "Submitting shares"; case "done": - return "Delegation confirmed"; + return job.doneLabel ?? "Delegation confirmed"; case "error": return "Submission failed"; default: @@ -128,7 +132,7 @@ class VotingStatusPageState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - _stageLabel(job.stage), + _stageLabel(job), style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), @@ -136,7 +140,9 @@ class VotingStatusPageState extends ConsumerState { LinearProgressIndicator( value: job.stage == "done" ? 1 - : job.stage == "proving" || job.stage == "confirming" + : job.stage == "proving" || + job.stage == "confirming" || + job.stage == "shares" ? null : job.progress, minHeight: 6, @@ -158,6 +164,23 @@ class VotingStatusPageState extends ConsumerState { style: Theme.of(context).textTheme.bodyMedium, ), ), + if (job.stage == "done" && job.txHash != null) ...[ + const SizedBox(height: 12), + SelectableText( + "Transaction: ${job.txHash}", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall, + ), + if (job.confirmHeight != null) + Padding( + padding: const EdgeInsets.only(top: 4), + child: Text( + "Included in block ${job.confirmHeight}", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall, + ), + ), + ], const SizedBox(height: 24), if (job.stage == "error") ...[ Text( diff --git a/lib/services/votechain_confirmation.dart b/lib/services/votechain_confirmation.dart new file mode 100644 index 000000000..135ec411d --- /dev/null +++ b/lib/services/votechain_confirmation.dart @@ -0,0 +1,37 @@ +import 'dart:convert'; + +/// Parsed proof of block inclusion from a 200 GET tx/{hash} response. +class VoteChainTxConfirmation { + /// JSON-encoded events array from the response (may be `"[]"`). + final String eventsJson; + + /// Block height at which the transaction was included; always > 0. + final int height; + + const VoteChainTxConfirmation({ + required this.eventsJson, + required this.height, + }); +} + +/// Parses a 200 body from the vote chain tx confirmation endpoint. +/// +/// Returns null when the body does not prove block inclusion: malformed +/// JSON, a non-map body, a missing `height`, or `height <= 0`. Callers treat +/// null as "not confirmed yet" and keep polling. +VoteChainTxConfirmation? parseVoteChainTxConfirmation(String body) { + final dynamic decoded; + try { + decoded = jsonDecode(body); + } on FormatException { + return null; + } + if (decoded is! Map) return null; + final rawHeight = decoded['height']; + final height = rawHeight is int ? rawHeight : (rawHeight is num ? rawHeight.toInt() : 0); + if (height <= 0) return null; + return VoteChainTxConfirmation( + eventsJson: jsonEncode(decoded['events'] ?? const []), + height: height, + ); +} diff --git a/lib/store.dart b/lib/store.dart index 84b58f368..17a419eb4 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:zkool/main.dart'; import 'package:zkool/router.dart'; import 'package:zkool/services/block_height_service.dart'; +import 'package:zkool/services/votechain_confirmation.dart'; import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/coin.dart'; import 'package:zkool/src/rust/api/contacts.dart'; @@ -1329,9 +1330,13 @@ class VotingSession extends _$VotingSession { Future _load() async { final c = coinContext.coin; + // Pass the draft proposal ids so the fork's plan can see open proposals: + // `needs_draft_setup` (the fresh-round trigger) and `all_decided` are + // computed against them, and are vacuously false/true with an empty list. + final draftIds = await _draftProposalIds(c); final plan = await votingPlan( roundId: _roundId, - proposalIds: const [], + proposalIds: draftIds, c: c, ); final recovery = await votingRecovery(roundId: _roundId, c: c); @@ -1339,6 +1344,19 @@ class VotingSession extends _$VotingSession { return VotingSessionState(plan: plan, recovery: recovery, intents: intents); } + Future> _draftProposalIds(Coin c) async { + try { + final drafts = await votingDraftsLoad(roundId: _roundId, c: c); + if (drafts == null || drafts.isEmpty) return const []; + return (jsonDecode(drafts) as List) + .map((d) => (d as Map)['proposal_id'] as int? ?? 0) + .where((id) => id > 0) + .toList(); + } on Exception { + return const []; + } + } + Future refresh() async { state = const AsyncValue.loading(); state = await AsyncValue.guard(_load); @@ -1414,12 +1432,19 @@ class VotingSubmissionGuard extends _$VotingSubmissionGuard { @freezed sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { factory VotingSubmissionJobState({ - required String stage, // idle|preparing|proving|submitting|confirming|done|error + required String stage, // idle|preparing|proving|submitting|confirming|voting|shares|done|error required double progress, String? error, /// Voting weight (zatoshi) delegated by the prepared bundle, shown in /// the status UI once the delegation prepare step completes. BigInt? eligibleWeightZatoshi, + /// Chain evidence of what this run confirmed: the delegation tx hash, or + /// the first confirmed vote hash when no delegation ran. + String? txHash, + /// Block height at which [txHash] was included; set together with it. + int? confirmHeight, + /// Honest "done" headline describing what THIS run actually completed. + String? doneLabel, }) = _VotingSubmissionJobState; } @@ -1460,7 +1485,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { state = state.copyWith(stage: "running", progress: 0, error: null); ref.read(votingSubmissionGuardProvider.notifier).setActive(true); try { - await _runDelegation( + final delegated = await _runDelegation( chainUrl: chainUrl, pirServerUrl: pirServerUrl, pirLayout: pirLayout, @@ -1469,20 +1494,24 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { maxRealNotesPerBundle: maxRealNotesPerBundle, lightwalletdUrl: lightwalletdUrl, ); - final session = await ref.read(votingSessionProvider(roundId).future); - await _runVotes( + final voted = await _runVotes( chainUrl: chainUrl, voteNodeUrl: voteNodeUrl, - plan: session.plan, - recovery: session.recovery, ); - await _submitShares( + final shared = await _submitShares( ceremonyStart: ceremonyStart, voteEnd: voteEnd, shareServerUrls: shareServerUrls, singleShare: singleShare, ); - state = state.copyWith(stage: "done", progress: 1); + final doneLabel = delegated + ? "Delegation confirmed" + : voted + ? "Votes submitted" + : shared + ? "Shares submitted" + : "All steps already confirmed"; + state = state.copyWith(stage: "done", progress: 1, doneLabel: doneLabel); ref.read(votingSubmissionGuardProvider.notifier).setActive(false); } on Exception catch (e) { state = state.copyWith(stage: "error", error: e.toString()); @@ -1494,7 +1523,9 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { state = VotingSubmissionJobState(stage: "idle", progress: 0); } - Future _runDelegation({ + /// Runs the delegation steps for this round; returns true when a delegation + /// was confirmed in this run (fresh broadcast or recorded-hash poll). + Future _runDelegation({ required String chainUrl, required String pirServerUrl, VotingPirLayout? pirLayout, @@ -1510,13 +1541,30 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final delegateStep = steps.where((s) => s.kind == "delegate").firstOrNull; final pollStep = steps.where((s) => s.kind == "poll_delegation").firstOrNull; - if (delegateStep == null && pollStep == null) { - return; // no delegation work for this round + // A fresh round has no plan steps at all; the fork's plan flags it with + // `needs_draft_setup`. Treat that as delegation work for the first bundle + // that still needs it (mirrors vizor's roundPlanNeedsDraftSetup trigger). + var freshDelegate = false; + int bundleIndex; + if (delegateStep != null || pollStep != null) { + bundleIndex = (delegateStep ?? pollStep!).bundleIndex; + } else { + final p = plan; + if (p == null || !p.needsDraftSetup) { + return false; // no delegation work for this round + } + final pending = p.delegationStatuses + .where((s) => s.phase == "prepared" || s.phase == "committed") + .firstOrNull; + if (p.delegationStatuses.isNotEmpty && pending == null) { + return false; // all bundles confirmed; _runVotes handles casting + } + bundleIndex = pending?.bundleIndex ?? 0; + freshDelegate = true; } - final bundleIndex = (delegateStep ?? pollStep!).bundleIndex; String? txHash; - if (delegateStep != null) { + if (delegateStep != null || freshDelegate) { state = state.copyWith(stage: "preparing"); final prepared = roundParamsJson != null && roundName != null ? await delegationPrepare( @@ -1546,12 +1594,16 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); state = state.copyWith(stage: "proving"); + final pir = await _resolvePirConfig( + pirServerUrl: pirServerUrl, + pirLayout: pirLayout, + ); final stream = delegationBuildSubmission( roundId: roundId, bundleIndex: bundleIndex, pcztBytes: setup.pcztBytes, - pirLayout: pirLayout, - pirServerUrl: pirServerUrl, + pirLayout: pir.$2, + pirServerUrl: pir.$1, c: c, ); await for (final event in stream) { @@ -1622,19 +1674,46 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } state = state.copyWith(stage: "confirming"); - final eventsJson = - await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash!); + final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash!); await delegationConfirm( roundId: roundId, bundleIndex: bundleIndex, txHash: txHash, - eventsJson: eventsJson, + eventsJson: conf.eventsJson, c: c, ); + state = state.copyWith(txHash: txHash, confirmHeight: conf.height); await ref.read(votingSessionProvider(roundId).notifier).refresh(); + return true; + } + + /// Fills a missing PIR server URL / layout from the resolved voting config + /// (the UI never passes them — both push sites send "" / null). Falls back + /// to the passed values; when the config is unavailable the Rust side + /// errors with a clear message. + Future<(String, VotingPirLayout?)> _resolvePirConfig({ + required String pirServerUrl, + required VotingPirLayout? pirLayout, + }) async { + if (pirServerUrl.isNotEmpty && pirLayout != null) { + return (pirServerUrl, pirLayout); + } + try { + final config = await ref.read(votingConfigProvider.future); + final url = pirServerUrl.isNotEmpty + ? pirServerUrl + : (config?.pirServers.isNotEmpty ?? false) + ? config!.pirServers.first.url + : ""; + return (url, pirLayout ?? config?.pirLayout); + } on Exception { + return (pirServerUrl, pirLayout); + } } - Future _pollTxConfirmation({ + /// Polls the vote chain until the tx is included in a block (HTTP 200 with + /// a positive `height`), returning the parsed confirmation. + Future _pollTxConfirmation({ required String chainUrl, required String txHash, }) async { @@ -1646,9 +1725,8 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); if (res.statusCode == 200) { - final body = jsonDecode(res.body) as Map; - final events = body['events']; - return jsonEncode(events ?? const []); + final conf = parseVoteChainTxConfirmation(res.body); + if (conf != null) return conf; } await Future.delayed(const Duration(seconds: 2)); } @@ -1659,30 +1737,20 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { /// Casts and confirms the remaining votes for a round, recovery-first: /// `cast_vote` steps commit (streamed), `submit_vote` steps broadcast and - /// confirm, `poll_vote` steps only poll a previously recorded tx. - Future _runVotes({ + /// confirm, `poll_vote` steps only poll a previously recorded tx. Ballot + /// intents are written from the drafts BEFORE the plan is read so a fresh + /// round's cast steps appear (mirrors vizor's writeBallotIntents). Returns + /// true when at least one vote was confirmed in this run. + Future _runVotes({ required String chainUrl, required String voteNodeUrl, - required VotingRoundPlan? plan, - required VotingRoundRecovery? recovery, }) async { - if (plan == null) return; final c = coinContext.coin; - final voteSteps = plan.nextSteps - .where((s) => - s.kind == "cast_vote" || - s.kind == "submit_vote" || - s.kind == "poll_vote") - .toList(); - if (voteSteps.isEmpty) return; + // Durable ballot intents first (mirrors vizor's writeBallotIntents): + // recovery can resume from the right choice if the app dies mid-vote. + // The round row exists by now (delegation prepared), so the FK holds. final draftsJson = await votingDraftsLoad(roundId: roundId, c: c); - final byBundle = groupBy(voteSteps, (s) => s.bundleIndex); - - // Write durable ballot intents before the cast loop (mirrors vizor's - // writeBallotIntents): recovery can resume from the right choice if the - // app dies mid-vote. The round row exists by now (delegation prepared), - // so the FK is satisfied. if (draftsJson != null && draftsJson.isNotEmpty) { final drafts = jsonDecode(draftsJson) as List; for (final d in drafts) { @@ -1702,6 +1770,39 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + // Re-read the session: with intents written, the plan now carries the + // cast_vote steps (bundles exist after delegation). + await ref.read(votingSessionProvider(roundId).notifier).refresh(); + final session = await ref.read(votingSessionProvider(roundId).future); + final plan = session.plan; + final recovery = session.recovery; + if (plan == null) return false; + + // Defer votes for bundles whose delegation still needs to run (a fresh + // prepare creates rows for all policy bundles; each run advances one). + final delegateBundles = plan.nextSteps + .where((s) => s.kind == "delegate") + .map((s) => s.bundleIndex) + .toSet(); + final voteSteps = plan.nextSteps + .where( + (s) => + (s.kind == "cast_vote" || + s.kind == "submit_vote" || + s.kind == "poll_vote") && + !delegateBundles.contains(s.bundleIndex), + ) + .toList(); + + if (voteSteps.isEmpty) return false; + var didWork = false; + final byBundle = groupBy(voteSteps, (s) => s.bundleIndex); + + // The commit step deserializes drafts as fork DraftVote, which requires + // vc_tree_position + single_share and rejects skipped choices and empty + // batches — sanitize the UI drafts for the cast call. + final commitDraftsJson = _sanitizedCommitDrafts(draftsJson); + for (final entry in byBundle.entries) { final bundleIndex = entry.key; final steps = entry.value; @@ -1709,17 +1810,17 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final castSteps = steps.where((s) => s.kind == "cast_vote").toList(); if (castSteps.isNotEmpty) { - if (draftsJson == null || draftsJson.isEmpty) { + if (commitDraftsJson == null || commitDraftsJson.isEmpty) { throw AnyhowException( "No draft ballot saved for round $roundId; " "open the ballot and review first", ); } - state = state.copyWith(stage: "voting"); + state = state.copyWith(stage: "voting", progress: 0); final stream = votingCommitWithProgress( roundId: roundId, bundleIndex: bundleIndex, - draftsJson: draftsJson, + draftsJson: commitDraftsJson, voteNodeUrl: voteNodeUrl, c: c, ); @@ -1731,10 +1832,11 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { break; } } + didWork = true; } for (final step in steps.where((s) => s.kind == "submit_vote")) { - state = state.copyWith(stage: "voting"); + state = state.copyWith(stage: "voting", progress: 0); final wireJson = await votingVoteWireJson( roundId: roundId, bundleIndex: bundleIndex, @@ -1773,16 +1875,20 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); state = state.copyWith(stage: "confirming"); - final eventsJson = + final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); await votingConfirm( roundId: roundId, bundleIndex: bundleIndex, proposalId: step.proposalId, txHash: txHash, - eventsJson: eventsJson, + eventsJson: conf.eventsJson, c: c, ); + didWork = true; + if (state.txHash == null) { + state = state.copyWith(txHash: txHash, confirmHeight: conf.height); + } } for (final step in steps.where((s) => s.kind == "poll_vote")) { @@ -1799,24 +1905,51 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); } state = state.copyWith(stage: "confirming"); - final eventsJson = + final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); await votingConfirm( roundId: roundId, bundleIndex: bundleIndex, proposalId: step.proposalId, txHash: txHash, - eventsJson: eventsJson, + eventsJson: conf.eventsJson, c: c, ); + didWork = true; + if (state.txHash == null) { + state = state.copyWith(txHash: txHash, confirmHeight: conf.height); + } } } + return didWork; + } + + /// Converts UI drafts to the fork's DraftVote JSON for the commit step: + /// drops skipped choices (validation rejects choice == num_options) and + /// fills the fields the fork requires with no serde defaults. Returns null + /// when there is nothing to cast (no drafts or all-skipped ballot). + String? _sanitizedCommitDrafts(String? draftsJson) { + if (draftsJson == null || draftsJson.isEmpty) return null; + final drafts = jsonDecode(draftsJson) as List; + final commit = >[ + for (final d in drafts) + if ((d as Map)['choice'] != d['num_options']) + { + 'proposal_id': d['proposal_id'], + 'choice': d['choice'], + 'num_options': d['num_options'], + 'vc_tree_position': 0, + 'single_share': false, + }, + ]; + return commit.isEmpty ? null : jsonEncode(commit); } /// Plans and submits helper shares for unconfirmed share rows. With no /// active vote window or no helper servers configured this is a no-op /// (the real inputs arrive with the dynamic config in a later phase). - Future _submitShares({ + /// Returns true when at least one share was submitted and recorded. + Future _submitShares({ required int ceremonyStart, required int? voteEnd, required List shareServerUrls, @@ -1824,6 +1957,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { }) async { final c = coinContext.coin; state = state.copyWith(stage: "shares"); + var submitted = false; final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; final sharePlan = await votingSharePlan( roundId: roundId, @@ -1872,6 +2006,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { submitAt: item.submitAt, c: c, ); + submitted = true; } // Background tracking until every share confirms (or the vote window ends). @@ -1884,6 +2019,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { singleShare: singleShare, ); } + return submitted; } void _scheduleShareTracking({ diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index d786756a3..4a27b7355 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -5049,7 +5049,8 @@ class __$VotingSessionStateCopyWithImpl<$Res> /// @nodoc mixin _$VotingSubmissionJobState { - String get stage; // idle|preparing|proving|submitting|confirming|done|error + String + get stage; // idle|preparing|proving|submitting|confirming|voting|shares|done|error double get progress; String? get error; @@ -5057,6 +5058,16 @@ mixin _$VotingSubmissionJobState { /// the status UI once the delegation prepare step completes. BigInt? get eligibleWeightZatoshi; + /// Chain evidence of what this run confirmed: the delegation tx hash, or + /// the first confirmed vote hash when no delegation ran. + String? get txHash; + + /// Block height at which [txHash] was included; set together with it. + int? get confirmHeight; + + /// Honest "done" headline describing what THIS run actually completed. + String? get doneLabel; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -5075,16 +5086,21 @@ mixin _$VotingSubmissionJobState { other.progress == progress) && (identical(other.error, error) || other.error == error) && (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || - other.eligibleWeightZatoshi == eligibleWeightZatoshi)); + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.confirmHeight, confirmHeight) || + other.confirmHeight == confirmHeight) && + (identical(other.doneLabel, doneLabel) || + other.doneLabel == doneLabel)); } @override - int get hashCode => - Object.hash(runtimeType, stage, progress, error, eligibleWeightZatoshi); + int get hashCode => Object.hash(runtimeType, stage, progress, error, + eligibleWeightZatoshi, txHash, confirmHeight, doneLabel); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel)'; } } @@ -5098,7 +5114,10 @@ abstract mixin class $VotingSubmissionJobStateCopyWith<$Res> { {String stage, double progress, String? error, - BigInt? eligibleWeightZatoshi}); + BigInt? eligibleWeightZatoshi, + String? txHash, + int? confirmHeight, + String? doneLabel}); } /// @nodoc @@ -5118,6 +5137,9 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> Object? progress = null, Object? error = freezed, Object? eligibleWeightZatoshi = freezed, + Object? txHash = freezed, + Object? confirmHeight = freezed, + Object? doneLabel = freezed, }) { return _then(_self.copyWith( stage: null == stage @@ -5136,6 +5158,18 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.eligibleWeightZatoshi : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable as BigInt?, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + confirmHeight: freezed == confirmHeight + ? _self.confirmHeight + : confirmHeight // ignore: cast_nullable_to_non_nullable + as int?, + doneLabel: freezed == doneLabel + ? _self.doneLabel + : doneLabel // ignore: cast_nullable_to_non_nullable + as String?, )); } } @@ -5231,16 +5265,28 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult maybeWhen( - TResult Function(String stage, double progress, String? error, - BigInt? eligibleWeightZatoshi)? + TResult Function( + String stage, + double progress, + String? error, + BigInt? eligibleWeightZatoshi, + String? txHash, + int? confirmHeight, + String? doneLabel)? $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _VotingSubmissionJobState() when $default != null: - return $default(_that.stage, _that.progress, _that.error, - _that.eligibleWeightZatoshi); + return $default( + _that.stage, + _that.progress, + _that.error, + _that.eligibleWeightZatoshi, + _that.txHash, + _that.confirmHeight, + _that.doneLabel); case _: return orElse(); } @@ -5261,15 +5307,27 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult when( - TResult Function(String stage, double progress, String? error, - BigInt? eligibleWeightZatoshi) + TResult Function( + String stage, + double progress, + String? error, + BigInt? eligibleWeightZatoshi, + String? txHash, + int? confirmHeight, + String? doneLabel) $default, ) { final _that = this; switch (_that) { case _VotingSubmissionJobState(): - return $default(_that.stage, _that.progress, _that.error, - _that.eligibleWeightZatoshi); + return $default( + _that.stage, + _that.progress, + _that.error, + _that.eligibleWeightZatoshi, + _that.txHash, + _that.confirmHeight, + _that.doneLabel); } } @@ -5287,15 +5345,27 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { @optionalTypeArgs TResult? whenOrNull( - TResult? Function(String stage, double progress, String? error, - BigInt? eligibleWeightZatoshi)? + TResult? Function( + String stage, + double progress, + String? error, + BigInt? eligibleWeightZatoshi, + String? txHash, + int? confirmHeight, + String? doneLabel)? $default, ) { final _that = this; switch (_that) { case _VotingSubmissionJobState() when $default != null: - return $default(_that.stage, _that.progress, _that.error, - _that.eligibleWeightZatoshi); + return $default( + _that.stage, + _that.progress, + _that.error, + _that.eligibleWeightZatoshi, + _that.txHash, + _that.confirmHeight, + _that.doneLabel); case _: return null; } @@ -5309,11 +5379,14 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { {required this.stage, required this.progress, this.error, - this.eligibleWeightZatoshi}); + this.eligibleWeightZatoshi, + this.txHash, + this.confirmHeight, + this.doneLabel}); @override final String stage; -// idle|preparing|proving|submitting|confirming|done|error +// idle|preparing|proving|submitting|confirming|voting|shares|done|error @override final double progress; @override @@ -5324,6 +5397,19 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { @override final BigInt? eligibleWeightZatoshi; + /// Chain evidence of what this run confirmed: the delegation tx hash, or + /// the first confirmed vote hash when no delegation ran. + @override + final String? txHash; + + /// Block height at which [txHash] was included; set together with it. + @override + final int? confirmHeight; + + /// Honest "done" headline describing what THIS run actually completed. + @override + final String? doneLabel; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @override @@ -5343,16 +5429,21 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { other.progress == progress) && (identical(other.error, error) || other.error == error) && (identical(other.eligibleWeightZatoshi, eligibleWeightZatoshi) || - other.eligibleWeightZatoshi == eligibleWeightZatoshi)); + other.eligibleWeightZatoshi == eligibleWeightZatoshi) && + (identical(other.txHash, txHash) || other.txHash == txHash) && + (identical(other.confirmHeight, confirmHeight) || + other.confirmHeight == confirmHeight) && + (identical(other.doneLabel, doneLabel) || + other.doneLabel == doneLabel)); } @override - int get hashCode => - Object.hash(runtimeType, stage, progress, error, eligibleWeightZatoshi); + int get hashCode => Object.hash(runtimeType, stage, progress, error, + eligibleWeightZatoshi, txHash, confirmHeight, doneLabel); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel)'; } } @@ -5368,7 +5459,10 @@ abstract mixin class _$VotingSubmissionJobStateCopyWith<$Res> {String stage, double progress, String? error, - BigInt? eligibleWeightZatoshi}); + BigInt? eligibleWeightZatoshi, + String? txHash, + int? confirmHeight, + String? doneLabel}); } /// @nodoc @@ -5388,6 +5482,9 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> Object? progress = null, Object? error = freezed, Object? eligibleWeightZatoshi = freezed, + Object? txHash = freezed, + Object? confirmHeight = freezed, + Object? doneLabel = freezed, }) { return _then(_VotingSubmissionJobState( stage: null == stage @@ -5406,6 +5503,18 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.eligibleWeightZatoshi : eligibleWeightZatoshi // ignore: cast_nullable_to_non_nullable as BigInt?, + txHash: freezed == txHash + ? _self.txHash + : txHash // ignore: cast_nullable_to_non_nullable + as String?, + confirmHeight: freezed == confirmHeight + ? _self.confirmHeight + : confirmHeight // ignore: cast_nullable_to_non_nullable + as int?, + doneLabel: freezed == doneLabel + ? _self.doneLabel + : doneLabel // ignore: cast_nullable_to_non_nullable + as String?, )); } } diff --git a/lib/store.g.dart b/lib/store.g.dart index dba9516bb..f5d315ba4 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1748,7 +1748,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'9715bec132ec57c8d4851296748578307db3d5bf'; + r'ea5e767799c528ecce54ebc14d41c9ac85c64db7'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → diff --git a/test/services/votechain_confirmation_test.dart b/test/services/votechain_confirmation_test.dart new file mode 100644 index 000000000..ace1a1e64 --- /dev/null +++ b/test/services/votechain_confirmation_test.dart @@ -0,0 +1,65 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/services/votechain_confirmation.dart'; + +void main() { + group('parseVoteChainTxConfirmation', () { + test('parses a valid body with events', () { + final conf = parseVoteChainTxConfirmation( + '{"height": 12345, "code": 0, "events": [{"type": "delegate-vote"}]}', + ); + expect(conf, isNotNull); + expect(conf!.height, 12345); + expect(conf.eventsJson, contains('delegate-vote')); + }); + + test('height 0 means not yet included', () { + expect( + parseVoteChainTxConfirmation('{"height": 0, "events": []}'), + isNull, + ); + }); + + test('missing height is not a confirmation', () { + expect( + parseVoteChainTxConfirmation('{"code": 0, "events": []}'), + isNull, + ); + }); + + test('null height is not a confirmation', () { + expect( + parseVoteChainTxConfirmation('{"height": null, "events": []}'), + isNull, + ); + }); + + test('negative height is not a confirmation', () { + expect( + parseVoteChainTxConfirmation('{"height": -5, "events": []}'), + isNull, + ); + }); + + test('numeric height is accepted', () { + final conf = + parseVoteChainTxConfirmation('{"height": 12.0, "events": []}'); + expect(conf, isNotNull); + expect(conf!.height, 12); + }); + + test('malformed JSON is not a confirmation', () { + expect(parseVoteChainTxConfirmation('not json'), isNull); + }); + + test('non-map body is not a confirmation', () { + expect(parseVoteChainTxConfirmation('[1, 2, 3]'), isNull); + }); + + test('missing events defaults to an empty array', () { + final conf = + parseVoteChainTxConfirmation('{"height": 7, "code": 0}'); + expect(conf, isNotNull); + expect(conf!.eventsJson, '[]'); + }); + }); +} From 63acacbbc038671c896d472bd933b61d19469863 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 07:42:12 +0800 Subject: [PATCH 075/189] fix: use app lightwalletd URL for fresh delegation prepare The fresh voting path (Join -> ballot -> Confirm & submit) never passes a lightwalletd URL, so delegation_prepare got '' and the fork's gather_delegation_lwd_inputs failed with 'invalid lightwalletd URL'. Fall back to the app-configured settings.lwd (same source the sync path uses) when the status-page param is empty; the resume path is untouched (its URL comes from the config saved by the first prepare). --- lib/store.dart | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/store.dart b/lib/store.dart index 17a419eb4..cc239d21f 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1566,6 +1566,12 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { String? txHash; if (delegateStep != null || freshDelegate) { state = state.copyWith(stage: "preparing"); + // The voting pages never pass a lightwalletd URL — use the app's + // configured one for the fresh prepare (the fork needs it to fetch + // the snapshot anchor tree state). + final lwdUrl = (lightwalletdUrl == null || lightwalletdUrl!.isEmpty) + ? await _appLwdUrl() + : lightwalletdUrl!; final prepared = roundParamsJson != null && roundName != null ? await delegationPrepare( roundParamsJson: roundParamsJson, @@ -1573,7 +1579,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { sessionJson: null, bundleIndex: bundleIndex, maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl ?? "", + lightwalletdUrl: lwdUrl, c: c, ) : await delegationPrepareResume( @@ -1711,6 +1717,17 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// Returns the app-configured lightwalletd URL (settings `lwd`) — the + /// voting pages never pass one. Empty when unavailable; the fork then + /// errors with a clear message. + Future _appLwdUrl() async { + try { + return (await ref.read(appSettingsProvider.future)).lwd; + } on Exception { + return ""; + } + } + /// Polls the vote chain until the tx is included in a block (HTTP 200 with /// a positive `height`), returning the parsed confirmation. Future _pollTxConfirmation({ From c343a71c9228d84fd7893f56463160a3b1b1ac45 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 07:50:52 +0800 Subject: [PATCH 076/189] fix: exclude post-snapshot notes from delegation prepare unspent_ironwood_notes selected every unspent Ironwood note without a height bound, so a note created after the round snapshot was passed to the prepare path; rewinding its witness to the snapshot anchor edge failed with 'note position is after anchor edge position'. Apply the same a.height <= snapshot_height filter as eligible_voting_weight, so the prepared bundle matches the eligibility shown on the ballot page. --- rust/src/voting.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/rust/src/voting.rs b/rust/src/voting.rs index c62839423..b232d9061 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -252,8 +252,10 @@ pub async fn load_round_inputs( h.height ); - // Select unspent, unlocked Ironwood (pool 3) ZEC notes. - let notes = unspent_ironwood_notes(connection, account).await?; + // Select unspent, unlocked Ironwood (pool 3) ZEC notes that existed at + // the snapshot height (mirrors eligible_voting_weight): notes created + // after the snapshot sit past the anchor edge and cannot be rewound. + let notes = unspent_ironwood_notes(connection, account, snapshot_height).await?; ensure!( !notes.is_empty(), "no unspent Ironwood notes available for voting" @@ -319,10 +321,12 @@ pub async fn load_round_inputs( }) } -/// Unspent, unlocked Ironwood (pool 3) ZEC notes as `(note_id, scope)`. +/// Unspent, unlocked Ironwood (pool 3) ZEC notes that existed at or before +/// `snapshot_height`, as `(note_id, scope)`. async fn unspent_ironwood_notes( connection: &mut SqliteConnection, account: u32, + snapshot_height: u32, ) -> Result> { let notes = sqlx::query( "SELECT a.id_note, a.scope @@ -331,9 +335,11 @@ async fn unspent_ironwood_notes( LEFT JOIN assets ast ON a.id_asset = ast.id_asset WHERE b.id_note IS NULL AND a.account = ? AND a.pool = 3 AND a.locked = 0 + AND a.height <= ? AND COALESCE(ast.asset_base, X'0000000000000000000000000000000000000000000000000000000000000000') = X'0000000000000000000000000000000000000000000000000000000000000000'", ) .bind(account) + .bind(snapshot_height) .map(|row: sqlx::sqlite::SqliteRow| { let id: u32 = row.get(0); let scope: Option = row.get(1); From 06ff09c9867477e91072800f3464bff3509f993e Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 07:55:12 +0800 Subject: [PATCH 077/189] fix: auto-create the voting hotkey at delegation time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delegation keys embed an app-owned voting hotkey, but nothing in the app ever created one, so delegation prepare failed with 'no voting hotkey; create one first' (voting_hotkey_load). Mirror vizor's _ensureHotkey: before preparing, create the hotkey when missing and the round is not yet hotkey-bound — a bound round without the stored key keeps failing instead of silently generating a mismatched key. --- lib/store.dart | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/store.dart b/lib/store.dart index cc239d21f..93df43ed3 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1566,6 +1566,14 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { String? txHash; if (delegateStep != null || freshDelegate) { state = state.copyWith(stage: "preparing"); + // The delegation keys embed an app-owned voting hotkey; auto-create + // one when missing and the round isn't already hotkey-bound (mirrors + // vizor's _ensureHotkey). A bound round without the stored hotkey + // keeps failing with the load error instead of silently generating a + // mismatched key. + if (!(plan?.hotkeyBound ?? false)) { + await _ensureVotingHotkey(); + } // The voting pages never pass a lightwalletd URL — use the app's // configured one for the fresh prepare (the fork needs it to fetch // the snapshot anchor tree state). @@ -1728,6 +1736,18 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// Ensures a voting hotkey exists for this wallet. The caller must only + /// invoke this when the round is not yet hotkey-bound: creating a new key + /// for a bound round would mismatch the on-chain delegation. + Future _ensureVotingHotkey() async { + final c = coinContext.coin; + try { + await votingHotkeyGet(c: c); + } on AnyhowException { + await votingHotkeyCreate(c: c); + } + } + /// Polls the vote chain until the tx is included in a block (HTTP 200 with /// a positive `height`), returning the parsed confirmation. Future _pollTxConfirmation({ From 80a073bc815354e856acc6947be67c7b264a0ccc Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 08:52:39 +0800 Subject: [PATCH 078/189] fix: make delegation confirmation real and recoverable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fresh voting flow could show 'Delegation confirmed' without an actual on-chain confirmation, and stale local setup state made the build step permanently refuse to proceed. Fixes: - delegation_build_submission and voting_commit_with_progress: the FRB stream binding drops the returned future (unawaited), so Rust errors surfaced as uncatchable 'Unhandled Exception'. Deliver errors through the sink (decoded as AnyhowException) instead of the dropped future. - _buildDelegation: run the build with empty pczt_bytes (the fork's software path — the build re-runs setup internally with fresh PCZT randomness, so a separate delegationSetup call always produced a conflicting sighash). Retry once after resetting unsigned setup state when the stored sighash is stale from a previous run. - _runDelegation: after delegationConfirm, read back the bundle phase from the session and require 'confirmed' with a tx hash before returning true — the done label cannot be claimed on un-backed state. - voting_status: the done label no longer falls back to 'Delegation confirmed' (that claimed success for stale done states); it renders the honest doneLabel. - new FRB voting_reset_session_state (fork reset_voting_session_state) for the stale-setup recovery. - Cargo.toml: patch zcash_voting to the local clone carrying the SQL alias fixes (voting_votes referenced as 'votes' in clear_stale_share_delegations and record_vote_submission). --- Cargo.lock | 3 - Cargo.toml | 6 ++ lib/pages/voting_status.dart | 2 +- lib/src/rust/api/sapling.dart | 7 ++- lib/src/rust/api/voting.dart | 10 ++++ lib/src/rust/frb_generated.dart | 58 ++++++++++++++----- lib/store.dart | 85 ++++++++++++++++++++++------ lib/store.g.dart | 4 +- rust/src/api/voting.rs | 98 +++++++++++++++++++++++++++------ rust/src/frb_generated.rs | 71 +++++++++++++++++++----- 10 files changed, 277 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cde1998f1..ee7269a6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13211,7 +13211,6 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "anyhow", "ff", @@ -13227,7 +13226,6 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "base64 0.22.1", "ff", @@ -14416,7 +14414,6 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=54e6c72ceae7ef4fd27129cf1e5484df5048f0a7#54e6c72ceae7ef4fd27129cf1e5484df5048f0a7" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index cf6b0bc46..f817bec3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,3 +50,9 @@ halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = " halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev = "9b408e712f8a2db8ca0b006846b310c6fd994941" } +# Local fork fixes not yet on the pinned rev: queries.rs referenced the +# voting_votes table as `votes` without an alias, breaking ballot-intent +# writes and vote submission recording. See ~/projects/zcash_voting. +[patch."https://github.com/hhanh00/zcash_voting.git"] +zcash_voting = { path = "/Users/hanh/projects/zcash_voting/zcash_voting" } + diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index 78599b835..07455c974 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -88,7 +88,7 @@ class VotingStatusPageState extends ConsumerState { case "shares": return "Submitting shares"; case "done": - return job.doneLabel ?? "Delegation confirmed"; + return job.doneLabel ?? "Submission complete"; case "error": return "Submission failed"; default: diff --git a/lib/src/rust/api/sapling.dart b/lib/src/rust/api/sapling.dart index dfc524efd..72388e983 100644 --- a/lib/src/rust/api/sapling.dart +++ b/lib/src/rust/api/sapling.dart @@ -8,7 +8,10 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `download_and_verify`, `resolve_params_dir`, `set_sapling_params_dir` -/// Check whether Sapling parameters are already on disk. +/// Check whether Sapling parameters are available. +/// +/// With `bundled-sapling-params` they are compiled into the binary and always +/// considered available. Otherwise checks whether they are on disk. SaplingParamsStatus checkSaplingParams() => RustLib.instance.api.crateApiSaplingCheckSaplingParams(); @@ -16,6 +19,8 @@ SaplingParamsStatus checkSaplingParams() => /// /// Verifies file size and Blake2b hash upon download. /// Safe to call even if they are already downloaded (no-op if valid). +/// With `bundled-sapling-params` the parameters are compiled into the binary +/// and this is a no-op. Future downloadSaplingParams() => RustLib.instance.api.crateApiSaplingDownloadSaplingParams(); diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index ec5aa2951..e5f4e84cb 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -472,6 +472,16 @@ Future votingRecoveryClear({required String roundId, required Coin c}) => RustLib.instance.api .crateApiVotingVotingRecoveryClear(roundId: roundId, c: c); +/// Resets process-local vote-tree cache and clears unsigned delegation setup +/// fields for a round (the fork's recovery when a restart after +/// `build_governance_pczt` persisted `pczt_sighash` makes re-setup refuse to +/// overwrite it). Submitted bundles, imported capabilities, and bundles with +/// persisted Keystone signatures are preserved. +Future votingResetSessionState( + {required String roundId, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingResetSessionState(roundId: roundId, c: c); + /// Returns the persisted ballot intents for a round, sorted by proposal id. Future> votingBallotIntents( {required String roundId, required Coin c}) => diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index f6339f485..2734ff377 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -440572071; + int get rustContentHash => 1940546024; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -786,6 +786,9 @@ abstract class RustLibApi extends BaseApi { Future crateApiVotingVotingRecoveryClear( {required String roundId, required Coin c}); + Future crateApiVotingVotingResetSessionState( + {required String roundId, required Coin c}); + Future crateApiVotingVotingRoundParamsJson( {required String source, required String roundId, @@ -7245,6 +7248,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["roundId", "c"], ); + @override + Future crateApiVotingVotingResetSessionState( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 213, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingResetSessionStateConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingResetSessionStateConstMeta => + const TaskConstMeta( + debugName: "voting_reset_session_state", + argNames: ["roundId", "c"], + ); + @override Future crateApiVotingVotingRoundParamsJson( {required String source, @@ -7264,7 +7296,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(nullifierImtRoot, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 213, port: port_); + funcId: 214, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7305,7 +7337,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 214, port: port_); + funcId: 215, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_info, @@ -7342,7 +7374,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 215, port: port_); + funcId: 216, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7387,7 +7419,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 216, port: port_); + funcId: 217, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7430,7 +7462,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 217, port: port_); + funcId: 218, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7470,7 +7502,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 218, port: port_); + funcId: 219, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7526,7 +7558,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + funcId: 220, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7572,7 +7604,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + funcId: 221, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7612,7 +7644,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7658,7 +7690,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7692,7 +7724,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + funcId: 224, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -7726,7 +7758,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 224, port: port_); + funcId: 225, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, diff --git a/lib/store.dart b/lib/store.dart index 93df43ed3..a6b1421ac 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1601,33 +1601,17 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { eligibleWeightZatoshi: prepared.eligibleWeightZatoshi, ); - final setup = await delegationSetup( - roundId: roundId, - bundleIndex: bundleIndex, - c: c, - ); - state = state.copyWith(stage: "proving"); final pir = await _resolvePirConfig( pirServerUrl: pirServerUrl, pirLayout: pirLayout, ); - final stream = delegationBuildSubmission( + await _buildDelegation( roundId: roundId, bundleIndex: bundleIndex, - pcztBytes: setup.pcztBytes, pirLayout: pir.$2, pirServerUrl: pir.$1, - c: c, ); - await for (final event in stream) { - switch (event) { - case VotingDelegationProgress_ProofProgress(:final progress): - state = state.copyWith(progress: progress); - default: - break; - } - } // The FRB boundary drops the build result when a StreamSink is present, // so the wire body comes from the prop persisted by the build. @@ -1698,6 +1682,22 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); state = state.copyWith(txHash: txHash, confirmHeight: conf.height); await ref.read(votingSessionProvider(roundId).notifier).refresh(); + // The done state must be backed by the fork's recorded confirmation: + // verify the bundle reads back as confirmed (tx hash + VAN leaf) before + // claiming success — a stale or partial state must not show + // "Delegation confirmed". + final verified = await ref.read(votingSessionProvider(roundId).future); + final status = verified.plan?.delegationStatuses + .where((s) => s.bundleIndex == bundleIndex) + .firstOrNull; + if (status == null || + status.phase != "confirmed" || + (status.txHash ?? "").isEmpty) { + throw AnyhowException( + "Delegation confirmation was not recorded for " + "round $roundId bundle $bundleIndex", + ); + } return true; } @@ -1748,6 +1748,57 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// Runs the delegation build/prove stream with the fork's software path: + /// the build re-runs `setup` internally (sampling fresh PCZT randomness), + /// so the app must NOT call `delegationSetup` separately and must pass + /// empty `pcztBytes` (skips the sighash consistency check). A restart + /// after a partial run leaves a stored sighash that the internal setup + /// refuses to overwrite — reset the unsigned setup and retry once + /// (mirrors vizor's keystone-stale-setup recovery). + Future _buildDelegation({ + required String roundId, + required int bundleIndex, + required VotingPirLayout? pirLayout, + required String pirServerUrl, + }) async { + final c = coinContext.coin; + debugPrint( + "Voting: delegation build starting for round $roundId bundle " + "$bundleIndex (no separate setup, empty pczt bytes)", + ); + for (var attempt = 0; attempt < 2; attempt++) { + try { + final stream = delegationBuildSubmission( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: const [], + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c, + ); + await for (final event in stream) { + switch (event) { + case VotingDelegationProgress_ProofProgress(:final progress): + state = state.copyWith(progress: progress); + default: + break; + } + } + return; + } on AnyhowException catch (e) { + if (!e.message.toLowerCase().contains("refusing to overwrite")) { + rethrow; + } + if (attempt == 1) rethrow; + debugPrint( + "Voting: stale delegation setup during build for round $roundId " + "bundle $bundleIndex; resetting and retrying", + ); + await votingResetSessionState(roundId: roundId, c: c); + } + } + } + /// Polls the vote chain until the tx is included in a block (HTTP 200 with /// a positive `height`), returning the parsed confirmation. Future _pollTxConfirmation({ diff --git a/lib/store.g.dart b/lib/store.g.dart index f5d315ba4..4f08e81fd 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1463,7 +1463,7 @@ final class VotingSessionProvider } } -String _$votingSessionHash() => r'74d90be6f0517caae693468712cabce9319f0584'; +String _$votingSessionHash() => r'194096c377208865fd439826f7355d88d99e93ff'; /// Per-round voting session. `build()` is the recovery-first triple load; /// `refresh()` re-runs it after an action mutates the voting DB. @@ -1748,7 +1748,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'ea5e767799c528ecce54ebc14d41c9ac85c64db7'; + r'6447bed624023babc55b25ef6c72b5bd58052f20'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index a624e47b5..d171aff58 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -616,20 +616,52 @@ pub async fn delegation_build_submission( let prepared = voting::load_prepared_bundle(&wallet_id, &round_id, bundle_index)?; let seed = voting::account_seed(&mut connection, account).await?; - let progress = DelegationProgressBridge::new(move |p| { - let _ = sink.add(p.into()); + let progress = DelegationProgressBridge::new({ + let sink_for_progress = sink.clone(); + move |p| { + let _ = sink_for_progress.add(p.into()); + } }); - let (submission, wire_json) = voting::prove_and_submit_delegation_with_progress( - c.get_pool()?, - &wallet_id, - &prepared, - &seed, - pczt_bytes, - pir_layout.to_fork(), - &pir_server_url, - &progress, - ) - .await?; + let (submission, wire_json) = + match voting::prove_and_submit_delegation_with_progress( + c.get_pool()?, + &wallet_id, + &prepared, + &seed, + pczt_bytes, + pir_layout.to_fork(), + &pir_server_url, + &progress, + ) + .await + { + Ok(v) => v, + Err(e) => { + // The FRB stream binding runs the call with `unawaited` and + // discards the returned future, so a plain `Err` would surface + // as an unhandled exception the app can never catch. Deliver + // the error through the sink (decoded as AnyhowException on + // the Dart stream) and return a benign Ok — the binding + // discards this value anyway. + let _ = sink.add_error(e); + return Ok(VotingDelegationBuild { + submission: VotingDelegationSubmission { + proof: Vec::new(), + rk: Vec::new(), + nf_signed: Vec::new(), + cmx_new: Vec::new(), + gov_comm: Vec::new(), + gov_nullifiers: Vec::new(), + alpha: Vec::new(), + vote_round_id: String::new(), + spend_auth_sig: Vec::new(), + sighash: Vec::new(), + tx1_effects: Vec::new(), + }, + wire_json: String::new(), + }); + } + }; // The FRB boundary drops this return value (StreamSink params take over), // so persist the wire body for `delegation_wire_json` to pick up. This also // makes a crash between proving and broadcasting resumable without @@ -793,10 +825,13 @@ pub async fn voting_commit_with_progress( voting::vote_van_witness(c.get_pool()?, &wallet_id, &round_id, bundle_index, &vote_node_url) .await?; - let stages = VoteCommitStageBridge::new(move |s| { - let _ = sink.add(s.into()); + let stages = VoteCommitStageBridge::new({ + let sink_for_stages = sink.clone(); + move |s| { + let _ = sink_for_stages.add(s.into()); + } }); - let commitments = voting::commit_votes_with_progress( + let commitments = match voting::commit_votes_with_progress( c.get_pool()?, &wallet_id, &round_id, @@ -806,7 +841,20 @@ pub async fn voting_commit_with_progress( &hotkey, &stages, ) - .await?; + .await + { + Ok(v) => v, + Err(e) => { + // Same FRB stream footgun as delegation_build_submission: the + // binding drops the returned future, so deliver the error via the + // sink and return a benign Ok (the value is discarded anyway). + let _ = sink.add_error(e); + return Ok(VotingVoteCommitments { + bundle_index, + commitments: Vec::new(), + }); + } + }; Ok(commitments.into()) } @@ -1955,6 +2003,22 @@ pub async fn voting_recovery_clear(round_id: &str, c: &Coin) -> Result<()> { Ok(()) } +/// Resets process-local vote-tree cache and clears unsigned delegation setup +/// fields for a round (the fork's recovery when a restart after +/// `build_governance_pczt` persisted `pczt_sighash` makes re-setup refuse to +/// overwrite it). Submitted bundles, imported capabilities, and bundles with +/// persisted Keystone signatures are preserved. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_reset_session_state(round_id: &str, c: &Coin) -> Result<()> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + zcash_voting::precompute::reset_voting_session_state(&db, &round_id).await?; + Ok(()) +} + /// Returns the persisted ballot intents for a round, sorted by proposal id. #[cfg_attr(feature = "flutter", frb)] pub async fn voting_ballot_intents(round_id: &str, c: &Coin) -> Result> { diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index bc1f9471c..fe4f71b3f 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -440572071; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1940546024; // Section: executor @@ -8429,6 +8429,45 @@ fn wire__crate__api__voting__voting_recovery_clear_impl( }, ) } +fn wire__crate__api__voting__voting_reset_session_state_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_reset_session_state", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = ::sse_decode(&mut deserializer); + let api_c = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_reset_session_state(&api_round_id, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_round_params_json_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -12333,44 +12372,50 @@ fn pde_ffi_dispatcher_primary_impl( 212 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 213 => wire__crate__api__voting__voting_round_params_json_impl( + 213 => wire__crate__api__voting__voting_reset_session_state_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 214 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 214 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 215 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 215 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 216 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 216 => wire__crate__api__voting__voting_share_add_servers_impl( + 217 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 217 => { + 218 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 218 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 219 => { + 219 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 220 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 220 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 221 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 221 => { + 222 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 222 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 223 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 224 => { + 223 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 224 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 225 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), From c497c059354a0e82e65cd14f27cba025ba97558a Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 09:10:15 +0800 Subject: [PATCH 079/189] fix: use the async PIR client for delegation proving PirClientBlocking owns a tokio runtime and block_ons on every call, which panics inside the FRB async runtime ('cannot start a runtime from within a runtime'). Connect via the async connect_pir and let the fork's prove path (now generic over PirProofSource) fetch IMT proofs without a blocking detour. --- rust/src/voting.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rust/src/voting.rs b/rust/src/voting.rs index b232d9061..082bc6628 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -575,11 +575,15 @@ pub async fn prove_and_submit_delegation_with_progress( progress.on_progress(DelegationProgress::SigningPayload); let (sig, sighash) = sign_delegation_request(seed, request)?; - let pir_client = zcash_voting::connect_pir_blocking( + // Async PIR client: the blocking variant owns a tokio runtime and would + // panic ("cannot start a runtime from within a runtime") inside the FRB + // async runtime. The prove path is generic over PirProofSource. + let pir_client = zcash_voting::connect_pir( pir_layout, pir_server_url, Arc::new(zcash_voting::HyperTransport::new()), - )?; + ) + .await?; prepared.prove(&db, &pir_client, progress).await?; let bundle = prepared From f991e8c3279b7dca6d2fe101e88622d279424600 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu Date: Mon, 17 Aug 2026 13:35:39 +0800 Subject: [PATCH 080/189] feat: show friendly round titles and option labels in the voting UI - new votingRoundTitle provider fetches the chain round-status title (the only friendly-name source; config and local DB carry none) - polls page: Join tiles and round tiles show the title instead of the bare hex round id - ballot page: the round-name lookup now checks 'title' first, so the friendly name flows through review -> status -> confirmation - status page: shows the round name above the stage label - confirmation page: 'Your vote for has been submitted.' - review page: fetches the chain options and lists the chosen option LABEL (e.g. 'Smooth issuance curve') instead of 'Option N', falling back to indices when the fetch fails - error text on the status page is selectable for copy/paste --- lib/pages/voting_confirmation.dart | 9 ++- lib/pages/voting_polls.dart | 44 ++++++----- lib/pages/voting_proposal.dart | 4 +- lib/pages/voting_review.dart | 59 +++++++++++++++ lib/pages/voting_status.dart | 18 ++++- lib/router.dart | 5 +- lib/store.dart | 19 +++++ lib/store.g.dart | 113 ++++++++++++++++++++++++++++- 8 files changed, 246 insertions(+), 25 deletions(-) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 5e34c0de0..c6483edf8 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -8,8 +8,9 @@ import 'package:zkool/utils.dart'; /// Receipt screen shown after the submission job completes. class VotingConfirmationPage extends ConsumerStatefulWidget { final String roundId; + final String? roundName; - const VotingConfirmationPage({super.key, required this.roundId}); + const VotingConfirmationPage({super.key, required this.roundId, this.roundName}); @override ConsumerState<VotingConfirmationPage> createState() => @@ -40,7 +41,11 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> ), const SizedBox(height: 16), Text( - "Your vote for ${widget.roundId} has been submitted.", + widget.roundName != null && + widget.roundName!.isNotEmpty && + widget.roundName != widget.roundId + ? "Your vote for ${widget.roundName} has been submitted." + : "Your vote for ${widget.roundId} has been submitted.", style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index db8f6739c..9cc142c6a 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -113,23 +113,28 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { style: TextStyle(fontWeight: FontWeight.bold)), ), ...joinable.map( - (r) => ListTile( - title: Text(r.roundId), - trailing: FilledButton.tonal( - onPressed: chainUrl.isEmpty - ? null - : () => GoRouter.of(context) - .push("/voting/proposal", extra: { - "roundId": r.roundId, - "chainUrl": chainUrl, - }), - child: const Text("Join"), - ), - ), + (r) { + final title = ref.watch( + votingRoundTitleProvider(r.roundId, chainUrl), + ); + return ListTile( + title: Text(title.value ?? r.roundId), + trailing: FilledButton.tonal( + onPressed: chainUrl.isEmpty + ? null + : () => GoRouter.of(context) + .push("/voting/proposal", extra: { + "roundId": r.roundId, + "chainUrl": chainUrl, + }), + child: const Text("Join"), + ), + ); + }, ), const Divider(), ], - ...list.map((r) => _RoundTile(round: r)), + ...list.map((r) => _RoundTile(round: r, chainUrl: chainUrl)), ], ), ); @@ -141,8 +146,9 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { class _RoundTile extends ConsumerWidget { final VotingRoundInfo round; + final String chainUrl; - const _RoundTile({required this.round}); + const _RoundTile({required this.round, required this.chainUrl}); String _actionLabel(String primaryAction) { switch (primaryAction) { @@ -159,9 +165,11 @@ class _RoundTile extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final cs = Theme.of(context).colorScheme; final session = ref.watch(votingSessionProvider(round.roundId)); + final title = ref.watch(votingRoundTitleProvider(round.roundId, chainUrl)); + final roundTitle = title.value ?? round.roundId; return session.when( loading: () => ListTile( - title: Text(round.roundId), + title: Text(roundTitle), subtitle: Text("Snapshot height ${round.snapshotHeight}"), trailing: SizedBox( width: 24, @@ -170,7 +178,7 @@ class _RoundTile extends ConsumerWidget { ), ), error: (e, _) => ListTile( - title: Text(round.roundId), + title: Text(roundTitle), subtitle: Text("Snapshot height ${round.snapshotHeight}"), trailing: IconButton( icon: Icon(Icons.refresh), @@ -182,7 +190,7 @@ class _RoundTile extends ConsumerWidget { final action = state.plan?.primaryAction ?? "idle"; final label = _actionLabel(action); return ListTile( - title: Text(round.roundId), + title: Text(roundTitle), subtitle: Text( "Snapshot height ${round.snapshotHeight} • " "${round.bundleCount} bundle${round.bundleCount == 1 ? "" : "s"}", diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index 709f809d9..c4f2f8c91 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -106,7 +106,9 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { _snapshotHeight = snapshotHeight; _votingPower = await votingEligibleWeight(snapshotHeight: snapshotHeight, c: c); - _roundName = (_find(round, "round_name") ?? _find(round, "name")) + _roundName = (_find(round, "title") ?? + _find(round, "round_name") ?? + _find(round, "name")) ?.toString() ?? widget.roundId; final settings = await ref.read(appSettingsProvider.future); diff --git a/lib/pages/voting_review.dart b/lib/pages/voting_review.dart index 8737df880..bba1edad3 100644 --- a/lib/pages/voting_review.dart +++ b/lib/pages/voting_review.dart @@ -32,6 +32,9 @@ class VotingReviewPage extends ConsumerStatefulWidget { class VotingReviewPageState extends ConsumerState<VotingReviewPage> { List<Map<String, dynamic>> _drafts = []; + /// proposal id -> option ids and their labels, from the chain round status + /// (the drafts store only the choice index). + final Map<int, List<_ReviewOption>> _optionsByProposal = {}; String? _error; @override @@ -49,16 +52,65 @@ class VotingReviewPageState extends ConsumerState<VotingReviewPage> { .map((d) => d as Map<String, dynamic>) .toList(); } + await _loadOptions(); if (mounted) setState(() {}); } on AnyhowException catch (e) { if (mounted) setState(() => _error = e.message); } } + /// Best-effort: fetches the proposal options from the chain so the review + /// can show option labels instead of indices. On failure the review falls + /// back to "Option N". + Future<void> _loadOptions() async { + try { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: widget.chainUrl, + roundId: widget.roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) return; + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final proposals = round['proposals'] as List<dynamic>? ?? []; + for (final p in proposals) { + if (p is! Map) continue; + final pid = p['id']; + if (pid is! int || pid < 1) continue; + var options = (p['options'] as List<dynamic>? ?? []) + .asMap() + .entries + .map((entry) { + final o = entry.value; + if (o is! Map) return null; + final id = (o['index'] is int) ? o['index'] as int : entry.key; + final label = + (o['label'] ?? o['short_title'] ?? o['title'] ?? "Option") + .toString(); + return _ReviewOption(id, label); + }) + .whereType<_ReviewOption>() + .toList(); + if (options.isEmpty) { + // Vote-sdk default: Yes/No when options are missing. + options = const [_ReviewOption(0, "Yes"), _ReviewOption(1, "No")]; + } + _optionsByProposal[pid] = options; + } + } on AnyhowException { + // Best-effort only; _answerLabel falls back to indices. + } + } + String _answerLabel(Map<String, dynamic> draft) { + final proposalId = draft['proposal_id'] as int? ?? 0; final choice = draft['choice'] as int? ?? 0; final numOptions = draft['num_options'] as int? ?? 2; if (choice == numOptions) return "Skipped"; + for (final option in _optionsByProposal[proposalId] ?? const []) { + if (option.id == choice) return option.label; + } return "Option ${choice + 1}"; } @@ -116,3 +168,10 @@ class VotingReviewPageState extends ConsumerState<VotingReviewPage> { ); } } + +class _ReviewOption { + final int id; + final String label; + + const _ReviewOption(this.id, this.label,); +} diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index 07455c974..da4ff772f 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -131,6 +131,17 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + if (widget.roundName != null && + widget.roundName!.isNotEmpty && + widget.roundName != widget.roundId) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text( + widget.roundName!, + style: Theme.of(context).textTheme.titleMedium, + textAlign: TextAlign.center, + ), + ), Text( _stageLabel(job), style: Theme.of(context).textTheme.titleLarge, @@ -183,7 +194,7 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { ], const SizedBox(height: 24), if (job.stage == "error") ...[ - Text( + SelectableText( job.error ?? "Unknown error", style: TextStyle( color: Theme.of(context).colorScheme.error, @@ -204,7 +215,10 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { FilledButton( onPressed: () => GoRouter.of(context).pushReplacement( "/voting/confirmation", - extra: {"roundId": widget.roundId}, + extra: { + "roundId": widget.roundId, + "roundName": widget.roundName, + }, ), child: const Text("Done"), ), diff --git a/lib/router.dart b/lib/router.dart index b685bfa30..f8d5b65ff 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -178,7 +178,10 @@ GoRouter router(bool disclaimerAccepted, bool recoveryMode) => GoRouter( path: '/voting/confirmation', builder: (context, state) { final args = state.extra as Map<String, dynamic>; - return VotingConfirmationPage(roundId: args['roundId'] as String); + return VotingConfirmationPage( + roundId: args['roundId'] as String, + roundName: args['roundName'] as String?, + ); }, ), GoRoute( diff --git a/lib/store.dart b/lib/store.dart index a6b1421ac..93e2338e3 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1370,6 +1370,25 @@ Future<List<VotingRoundInfo>> votingRoundList(Ref ref) async { return await votingRounds(c: c); } +/// Friendly round title from the vote chain round status, falling back to +/// the round id. The chain's `title` field is the only friendly name source +/// (the config and the local DB carry no titles). +@riverpod +Future<String> votingRoundTitle(Ref ref, String roundId, String chainUrl) async { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: chainUrl, + roundId: roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) return roundId; + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final title = round['title']; + if (title is String && title.trim().isNotEmpty) return title; + return roundId; +} + /// Resolved and authenticated voting config for the configured source URL. /// `build()` returns the last cached resolved config without touching the /// network (so merely reading the provider never triggers a fetch); call diff --git a/lib/store.g.dart b/lib/store.g.dart index 4f08e81fd..0e17d583c 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1563,6 +1563,117 @@ final class VotingRoundListProvider extends $FunctionalProvider< String _$votingRoundListHash() => r'12d2cfda4753a04d9343e21a6637789106c3ffb5'; +/// Friendly round title from the vote chain round status, falling back to +/// the round id. The chain's `title` field is the only friendly name source +/// (the config and the local DB carry no titles). + +@ProviderFor(votingRoundTitle) +const votingRoundTitleProvider = VotingRoundTitleFamily._(); + +/// Friendly round title from the vote chain round status, falling back to +/// the round id. The chain's `title` field is the only friendly name source +/// (the config and the local DB carry no titles). + +final class VotingRoundTitleProvider + extends $FunctionalProvider<AsyncValue<String>, String, FutureOr<String>> + with $FutureModifier<String>, $FutureProvider<String> { + /// Friendly round title from the vote chain round status, falling back to + /// the round id. The chain's `title` field is the only friendly name source + /// (the config and the local DB carry no titles). + const VotingRoundTitleProvider._( + {required VotingRoundTitleFamily super.from, + required ( + String, + String, + ) + super.argument}) + : super( + retry: null, + name: r'votingRoundTitleProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingRoundTitleHash(); + + @override + String toString() { + return r'votingRoundTitleProvider' + '' + '$argument'; + } + + @$internal + @override + $FutureProviderElement<String> $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr<String> create(Ref ref) { + final argument = this.argument as ( + String, + String, + ); + return votingRoundTitle( + ref, + argument.$1, + argument.$2, + ); + } + + @override + bool operator ==(Object other) { + return other is VotingRoundTitleProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$votingRoundTitleHash() => r'2331b63b18a1e939e9bc168a386eae6a081e0edf'; + +/// Friendly round title from the vote chain round status, falling back to +/// the round id. The chain's `title` field is the only friendly name source +/// (the config and the local DB carry no titles). + +final class VotingRoundTitleFamily extends $Family + with + $FunctionalFamilyOverride< + FutureOr<String>, + ( + String, + String, + )> { + const VotingRoundTitleFamily._() + : super( + retry: null, + name: r'votingRoundTitleProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// Friendly round title from the vote chain round status, falling back to + /// the round id. The chain's `title` field is the only friendly name source + /// (the config and the local DB carry no titles). + + VotingRoundTitleProvider call( + String roundId, + String chainUrl, + ) => + VotingRoundTitleProvider._(argument: ( + roundId, + chainUrl, + ), from: this); + + @override + String toString() => r'votingRoundTitleProvider'; +} + /// Resolved and authenticated voting config for the configured source URL. /// `build()` returns the last cached resolved config without touching the /// network (so merely reading the provider never triggers a fetch); call @@ -1748,7 +1859,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'6447bed624023babc55b25ef6c72b5bd58052f20'; + r'a283728879caa8ee179da7d5bf490d4e2da6c217'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → From ab74456746657a562bd148259909bccf1400c113 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 13:35:46 +0800 Subject: [PATCH 081/189] fix: run the PIR connect inside the prove thread The hyper client was created on the FRB runtime and its connections were pooled there; the prove thread's own runtime then reused them, but the FRB runtime is parked on the thread join, so the pooled connections' I/O could never progress and PIR requests stalled until the 60s transport timeout. Connect inside the thread so all PIR traffic lives on the thread's runtime (matches vizor's shape). A probe against the stage server confirmed the cross-runtime pattern was the wedge: single- and thread-runtime PIR both complete in ~6s. Also patch pir-client from a local copy adding the missing public circuit_root getter on the async client (needed by the fork's PirProofSource impl). --- Cargo.lock | 2 -- Cargo.toml | 5 +++++ rust/src/api/voting.rs | 8 ++++--- rust/src/voting.rs | 47 ++++++++++++++++++++++++++++++------------ 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee7269a6e..c14044d89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8207,8 +8207,6 @@ dependencies = [ [[package]] name = "pir-client" version = "0.4.0-rc.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf6547ec35c8d4af154bc73d60fe2773be50f7c089e79414983d721d0dbc13db" dependencies = [ "anyhow", "ff", diff --git a/Cargo.toml b/Cargo.toml index f817bec3a..42170848c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,11 @@ halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev = "9b408e712f8a2db8ca0b006846b310c6fd994941" } +# Local patched pir-client: the async PirClient lacks a public circuit_root +# accessor (private field), which the fork's PirProofSource trait needs. +# NOTE: the fork's own [patch.crates-io] does NOT apply to this workspace — +# cargo only honors patches in the workspace root manifest. +pir-client = { path = "/Users/hanh/projects/pir-client-0.4.0-rc.7" } # Local fork fixes not yet on the pinned rev: queries.rs referenced the # voting_votes table as `votes` without an alias, breaking ballot-intent diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index d171aff58..03ce39c17 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -5,6 +5,8 @@ //! transitions follow the plan: prepare → setup → sign/prove/submit → confirm, //! then van witness → commit → payloads → record execution → confirm. +use std::sync::Arc; + use anyhow::{anyhow, Result}; use rand_core::{OsRng, RngCore}; use serde::{Deserialize, Serialize}; @@ -616,12 +618,12 @@ pub async fn delegation_build_submission( let prepared = voting::load_prepared_bundle(&wallet_id, &round_id, bundle_index)?; let seed = voting::account_seed(&mut connection, account).await?; - let progress = DelegationProgressBridge::new({ + let progress = Arc::new(DelegationProgressBridge::new({ let sink_for_progress = sink.clone(); move |p| { let _ = sink_for_progress.add(p.into()); } - }); + })); let (submission, wire_json) = match voting::prove_and_submit_delegation_with_progress( c.get_pool()?, @@ -631,7 +633,7 @@ pub async fn delegation_build_submission( pczt_bytes, pir_layout.to_fork(), &pir_server_url, - &progress, + progress.clone(), ) .await { diff --git a/rust/src/voting.rs b/rust/src/voting.rs index 082bc6628..64f8c7bdb 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -548,7 +548,7 @@ pub async fn prove_and_submit_delegation( pczt_bytes, pir_layout, pir_server_url, - &NoopProgressReporter, + Arc::new(NoopProgressReporter), ) .await } @@ -566,25 +566,46 @@ pub async fn prove_and_submit_delegation_with_progress( pczt_bytes: Vec<u8>, pir_layout: zcash_voting::config::PirLayout, pir_server_url: &str, - progress: &dyn DelegationProgressReporter, + progress: Arc<dyn DelegationProgressReporter>, ) -> Result<(DelegationSubmission, String)> { let db = open_voting_db(pool, wallet_id).await?; - let _setup = prepared.setup(&db, progress).await?; + let _setup = prepared.setup(&db, progress.as_ref()).await?; let request = prepared.signing_request(&db).await?; progress.on_progress(DelegationProgress::SigningPayload); let (sig, sighash) = sign_delegation_request(seed, request)?; - // Async PIR client: the blocking variant owns a tokio runtime and would - // panic ("cannot start a runtime from within a runtime") inside the FRB - // async runtime. The prove path is generic over PirProofSource. - let pir_client = zcash_voting::connect_pir( - pir_layout, - pir_server_url, - Arc::new(zcash_voting::HyperTransport::new()), - ) - .await?; - prepared.prove(&db, &pir_client, progress).await?; + // Halo2 delegation proving recurses deeply and overflows the FRB worker + // thread's stack; run it on a dedicated thread with a large stack (the + // same pattern zcashd uses for its proving threads). The PIR client is + // created INSIDE the thread too: its hyper connections are then owned by + // the thread's own runtime, so nothing in the PIR path depends on the + // FRB runtime (which is parked on the thread join) — a cross-runtime + // hyper pool there stalled requests until the 60s transport timeout. + let prove_db = db.clone(); + let prove_prepared = prepared.clone(); + let prove_progress = progress.clone(); + let prove_pir_url = pir_server_url.to_string(); + let join = std::thread::Builder::new() + .stack_size(512 * 1024 * 1024) + .name("delegation-prove".to_string()) + .spawn(move || -> Result<zcash_voting::delegate::DelegationProof, anyhow::Error> { + let rt = tokio::runtime::Runtime::new() + .map_err(|e| anyhow!("failed to create proving runtime: {e}"))?; + let pir_client = rt.block_on(zcash_voting::connect_pir( + pir_layout, + &prove_pir_url, + Arc::new(zcash_voting::HyperTransport::new()), + ))?; + Ok(rt.block_on(prove_prepared.prove( + &prove_db, + &pir_client, + prove_progress.as_ref(), + ))?) + }) + .map_err(|e| anyhow!("failed to spawn delegation proof thread: {e}"))?; + join.join() + .map_err(|e| anyhow!("delegation proof thread panicked: {e:?}"))??; let bundle = prepared .signed_bundle(&db, pczt_bytes, PreparedSigner::signature(sig, sighash)) From 57357ef871f8865712c77bc7b8611d84fc626158 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 14:51:45 +0800 Subject: [PATCH 082/189] fix: parse the chain's string block heights; prove with voting-circuits 0.10.0 The vote chain reports tx confirmation heights as JSON strings ("7163319"), so parseVoteChainTxConfirmation rejected every confirmed tx and the confirmation poll timed out even though the delegation was accepted on-chain (leaf_index recorded). Accept numeric strings. Also point the voting-circuits patch at the local 0.10.0 clone with the ZSA-orchard shim (matching the chain's verifier), replacing the stale 0.9.0-rc.3 git rev that made the chain reject every delegation proof. Add rust/examples/vk_probe.rs to compare circuit/proof fingerprints against the fork's standalone build. --- Cargo.lock | 3 +-- Cargo.toml | 5 ++++- lib/services/votechain_confirmation.dart | 9 ++++++++- rust/examples/vk_probe.rs | 13 +++++++++++++ test/services/votechain_confirmation_test.dart | 16 ++++++++++++++++ 5 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 rust/examples/vk_probe.rs diff --git a/Cargo.lock b/Cargo.lock index c14044d89..7acb35598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13237,8 +13237,7 @@ dependencies = [ [[package]] name = "voting-circuits" -version = "0.9.0-rc.3" -source = "git+https://github.com/hhanh00/voting-circuits.git?rev=9b408e712f8a2db8ca0b006846b310c6fd994941#9b408e712f8a2db8ca0b006846b310c6fd994941" +version = "0.10.0" dependencies = [ "blake2b_simd", "ff", diff --git a/Cargo.toml b/Cargo.toml index 42170848c..bb64a93e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,10 @@ zcash_spec = { git = "https://github.com/zcash-shielded-assets/zcash_spec", rev halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } -voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev = "9b408e712f8a2db8ca0b006846b310c6fd994941" } +# Local voting-circuits: 0.10.0 release source + the ZSA-orchard note API +# shim (from_parts asset arg), matching the chain's verifier. See +# ~/projects/voting-circuits (branch feat/zsa-orchard-0.10). +voting-circuits = { path = "/Users/hanh/projects/voting-circuits" } # Local patched pir-client: the async PirClient lacks a public circuit_root # accessor (private field), which the fork's PirProofSource trait needs. # NOTE: the fork's own [patch.crates-io] does NOT apply to this workspace — diff --git a/lib/services/votechain_confirmation.dart b/lib/services/votechain_confirmation.dart index 135ec411d..ec32e7344 100644 --- a/lib/services/votechain_confirmation.dart +++ b/lib/services/votechain_confirmation.dart @@ -28,7 +28,14 @@ VoteChainTxConfirmation? parseVoteChainTxConfirmation(String body) { } if (decoded is! Map<String, dynamic>) return null; final rawHeight = decoded['height']; - final height = rawHeight is int ? rawHeight : (rawHeight is num ? rawHeight.toInt() : 0); + // The chain reports height as a JSON string ("7163319"), sometimes a number. + final height = rawHeight is int + ? rawHeight + : rawHeight is num + ? rawHeight.toInt() + : rawHeight is String + ? int.tryParse(rawHeight) ?? 0 + : 0; if (height <= 0) return null; return VoteChainTxConfirmation( eventsJson: jsonEncode(decoded['events'] ?? const []), diff --git a/rust/examples/vk_probe.rs b/rust/examples/vk_probe.rs new file mode 100644 index 000000000..587bacd67 --- /dev/null +++ b/rust/examples/vk_probe.rs @@ -0,0 +1,13 @@ +//! Prints the delegation circuit fingerprint and deterministic proof +//! fingerprints under the APP's patched deps. Compare with the same probes +//! run from the fork workspace (crates.io deps). +fn main() { + println!( + "delegation circuit fingerprint: {}", + zcash_voting::zkp1::delegation_circuit_fingerprint() + ); + let (len, proof_hex, pi_hex) = zcash_voting::zkp1::delegation_proof_probe(); + println!("delegation proof size: {len} bytes"); + println!("delegation proof sha256[..16]: {proof_hex}"); + println!("public inputs sha256[..8]: {pi_hex}"); +} diff --git a/test/services/votechain_confirmation_test.dart b/test/services/votechain_confirmation_test.dart index ace1a1e64..a13af4989 100644 --- a/test/services/votechain_confirmation_test.dart +++ b/test/services/votechain_confirmation_test.dart @@ -47,6 +47,22 @@ void main() { expect(conf!.height, 12); }); + test('string height is accepted (the chain reports heights as strings)', () { + final conf = parseVoteChainTxConfirmation( + '{"height": "7163319", "events": [{"type": "delegate_vote"}]}', + ); + expect(conf, isNotNull); + expect(conf!.height, 7163319); + expect(conf.eventsJson, contains('delegate_vote')); + }); + + test('non-numeric string height is not a confirmation', () { + expect( + parseVoteChainTxConfirmation('{"height": "abc", "events": []}'), + isNull, + ); + }); + test('malformed JSON is not a confirmation', () { expect(parseVoteChainTxConfirmation('not json'), isNull); }); From 7e2a4d657a87cc9513e22fd5a3e8026b0891cf7c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 16:08:20 +0800 Subject: [PATCH 083/189] fix: cast one proposal at a time so the vote VAN chains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vote circuit derives each cast-vote's VAN from a proposal-authority mask that clears one bit per submission (load_zkp2_inputs drops proposals whose vote has a recorded tx_hash). The port committed ALL drafts in one batch, so every proposal used the bundle's VAN and proposals after the first were rejected by the chain ('nullifier already spent'). Restructure _runVotes to mirror vizor's per-draft build loop: cast one proposal, submit + confirm it, then cast the next — each subsequent commitment sees the previous submission and derives the chained VAN. Extract the submit/confirm sequence into _submitVote, reused by the cast path and the resume submit_vote path. --- lib/store.dart | 139 +++++++++++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/lib/store.dart b/lib/store.dart index 93e2338e3..bf10cb132 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1916,18 +1916,35 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final castSteps = steps.where((s) => s.kind == "cast_vote").toList(); - if (castSteps.isNotEmpty) { + for (final step in castSteps) { if (commitDraftsJson == null || commitDraftsJson.isEmpty) { throw AnyhowException( "No draft ballot saved for round $roundId; " "open the ballot and review first", ); } + // Cast ONE proposal at a time and submit it before the next cast: + // the fork derives the next VAN from the submission state (the + // proposal-authority mask clears per recorded tx_hash), so the VAN + // chaining only works when builds interleave with submissions + // (mirrors vizor's per-draft build loop). + final drafts = jsonDecode(commitDraftsJson) as List<dynamic>; + final draft = drafts + .where( + (d) => (d as Map<String, dynamic>)['proposal_id'] == + step.proposalId, + ) + .firstOrNull; + if (draft == null) { + throw AnyhowException( + "No draft for proposal ${step.proposalId} in round $roundId", + ); + } state = state.copyWith(stage: "voting", progress: 0); final stream = votingCommitWithProgress( roundId: roundId, bundleIndex: bundleIndex, - draftsJson: commitDraftsJson, + draftsJson: jsonEncode([draft]), voteNodeUrl: voteNodeUrl, c: c, ); @@ -1939,63 +1956,21 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { break; } } - didWork = true; - } - - for (final step in steps.where((s) => s.kind == "submit_vote")) { - state = state.copyWith(stage: "voting", progress: 0); - final wireJson = await votingVoteWireJson( - roundId: roundId, + await _submitVote( bundleIndex: bundleIndex, proposalId: step.proposalId, - c: c, + chainUrl: chainUrl, ); - final res = await votechainSubmitVote( - baseUrl: chainUrl, - submissionJson: wireJson, - c: c, - ); - if (res.statusCode == 422) { - throw AnyhowException( - "Vote rejected by the vote chain: ${res.body}", - ); - } - if (res.statusCode < 200 || res.statusCode >= 300) { - throw AnyhowException( - "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", - ); - } - final result = jsonDecode(res.body) as Map<String, dynamic>; - final txHash = result['tx_hash'] as String? ?? ""; - final code = result['code'] as int? ?? -1; - if (code != 0 || txHash.isEmpty) { - throw AnyhowException( - "Vote chain rejected the vote: ${result['log'] ?? res.body}", - ); - } + didWork = true; + } - await votingMarkVoteSubmitted( - roundId: roundId, + for (final step in steps.where((s) => s.kind == "submit_vote")) { + await _submitVote( bundleIndex: bundleIndex, proposalId: step.proposalId, - txHash: txHash, - c: c, - ); - state = state.copyWith(stage: "confirming"); - final conf = - await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); - await votingConfirm( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: step.proposalId, - txHash: txHash, - eventsJson: conf.eventsJson, - c: c, + chainUrl: chainUrl, ); didWork = true; - if (state.txHash == null) { - state = state.copyWith(txHash: txHash, confirmHeight: conf.height); - } } for (final step in steps.where((s) => s.kind == "poll_vote")) { @@ -2031,6 +2006,68 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { return didWork; } + /// Broadcasts one committed vote and confirms it: rebuild the wire from + /// the persisted commitment, submit to the vote chain, record the tx hash, + /// poll until included in a block, and record the confirmation. + Future<void> _submitVote({ + required int bundleIndex, + required int proposalId, + required String chainUrl, + }) async { + final c = coinContext.coin; + state = state.copyWith(stage: "voting", progress: 0); + final wireJson = await votingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, + ); + final res = await votechainSubmitVote( + baseUrl: chainUrl, + submissionJson: wireJson, + c: c, + ); + if (res.statusCode == 422) { + throw AnyhowException( + "Vote rejected by the vote chain: ${res.body}", + ); + } + if (res.statusCode < 200 || res.statusCode >= 300) { + throw AnyhowException( + "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final result = jsonDecode(res.body) as Map<String, dynamic>; + final txHash = result['tx_hash'] as String? ?? ""; + final code = result['code'] as int? ?? -1; + if (code != 0 || txHash.isEmpty) { + throw AnyhowException( + "Vote chain rejected the vote: ${result['log'] ?? res.body}", + ); + } + + await votingMarkVoteSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + c: c, + ); + state = state.copyWith(stage: "confirming"); + final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); + await votingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + eventsJson: conf.eventsJson, + c: c, + ); + if (state.txHash == null) { + state = state.copyWith(txHash: txHash, confirmHeight: conf.height); + } + } + /// Converts UI drafts to the fork's DraftVote JSON for the commit step: /// drops skipped choices (validation rejects choice == num_options) and /// fills the fields the fork requires with no serde defaults. Returns null From 4ead4da1cd1d08b7eb768605659277d444627bf2 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 16:09:46 +0800 Subject: [PATCH 084/189] fix: fall back to the configured vote servers for helper shares MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The voting flow never passes shareServerUrls, so _submitShares planned against zero servers and the round stayed on 'Resume' forever with pending submit_shares steps. The vote chain servers double as helper servers — mirror vizor's context.config.voteServers: when no explicit share server list is provided, use the resolved config's vote server URLs. --- lib/store.dart | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/store.dart b/lib/store.dart index bf10cb132..da1d83ca0 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1517,10 +1517,14 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { chainUrl: chainUrl, voteNodeUrl: voteNodeUrl, ); + // The vote chain servers double as helper (share) servers; the voting + // flow never passes shareServerUrls, so fall back to the configured + // vote servers (mirrors vizor's context.config.voteServers). + final shareUrls = await _effectiveShareServerUrls(shareServerUrls); final shared = await _submitShares( ceremonyStart: ceremonyStart, voteEnd: voteEnd, - shareServerUrls: shareServerUrls, + shareServerUrls: shareUrls, singleShare: singleShare, ); final doneLabel = delegated @@ -1744,6 +1748,21 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// The vote chain servers double as helper (share) servers. The voting + /// flow never passes `shareServerUrls`, so fall back to the configured + /// vote servers — mirrors vizor's `context.config.voteServers`. + Future<List<String>> _effectiveShareServerUrls( + List<String> shareServerUrls, + ) async { + if (shareServerUrls.isNotEmpty) return shareServerUrls; + try { + final config = await ref.read(votingConfigProvider.future); + return config?.voteServers.map((s) => s.url).toList() ?? const []; + } on Exception { + return const []; + } + } + /// Returns the app-configured lightwalletd URL (settings `lwd`) — the /// voting pages never pass one. Empty when unavailable; the fork then /// errors with a clear message. From 1129f34b931379054906df293b6565081f60c8de Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 16:12:51 +0800 Subject: [PATCH 085/189] fix: honest done label when only time-scheduled steps remain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A run that performs no work can still have pending plan steps — the helper shares are scheduled near the vote window, so 'All steps already confirmed' was a misnomer while submit_shares steps remained. Derive the label from the plan: pending share steps -> 'Waiting for the share window', other pending steps -> 'Waiting for the next step', empty plan -> 'All steps already confirmed'. --- lib/store.dart | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/store.dart b/lib/store.dart index da1d83ca0..9ec8a573a 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1527,13 +1527,16 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { shareServerUrls: shareUrls, singleShare: singleShare, ); - final doneLabel = delegated - ? "Delegation confirmed" - : voted - ? "Votes submitted" - : shared - ? "Shares submitted" - : "All steps already confirmed"; + final String doneLabel; + if (delegated) { + doneLabel = "Delegation confirmed"; + } else if (voted) { + doneLabel = "Votes submitted"; + } else if (shared) { + doneLabel = "Shares submitted"; + } else { + doneLabel = await _remainingLabel(); + } state = state.copyWith(stage: "done", progress: 1, doneLabel: doneLabel); ref.read(votingSubmissionGuardProvider.notifier).setActive(false); } on Exception catch (e) { @@ -1748,6 +1751,18 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// Honest done label when a run performed no work: the plan may still have + /// pending steps (e.g. helper shares scheduled near the vote window) even + /// though nothing was due this run. + Future<String> _remainingLabel() async { + final session = await ref.read(votingSessionProvider(roundId).future); + final pending = session.plan?.nextSteps ?? const <VotingNextStep>[]; + if (pending.isEmpty) return "All steps already confirmed"; + const shareKinds = {"submit_shares", "confirm_share"}; + final allShares = pending.every((s) => shareKinds.contains(s.kind)); + return allShares ? "Waiting for the share window" : "Waiting for the next step"; + } + /// The vote chain servers double as helper (share) servers. The voting /// flow never passes `shareServerUrls`, so fall back to the configured /// vote servers — mirrors vizor's `context.config.voteServers`. From 5db3025a8e5558f043e0652268e64aaae21b1af3 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 16:19:19 +0800 Subject: [PATCH 086/189] feat: show per-vote on-chain evidence on the done and confirmation screens The evidence block surfaced only the delegation tx; the confirmed votes were verifiable in the DB and on the chain but invisible in the UI. Show each confirmed vote's tx hash and vote-tree position (from the session recovery) on the status screen's done state and the confirmation page, selectable for copy/paste. --- lib/pages/voting_confirmation.dart | 20 ++++++++++++++++++++ lib/pages/voting_status.dart | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index c6483edf8..120da5e04 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart'; +import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; @@ -24,6 +25,15 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> if (pinlock.value ?? false) return PinLock(); final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); + // Confirmed vote txs (per proposal), shown as on-chain evidence. + final confirmedVotes = (ref + .watch(votingSessionProvider(widget.roundId)) + .value + ?.recovery + ?.votes ?? + const <VotingVoteRecovery>[]) + .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) + .toList(); return Scaffold( appBar: AppBar(title: const Text("Vote submitted")), @@ -58,6 +68,16 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> textAlign: TextAlign.center, ), ), + for (final v in confirmedVotes) + Padding( + padding: const EdgeInsets.only(top: 8), + child: SelectableText( + "Proposal ${v.proposalId}: ${v.txHash} · " + "tree ${v.vcTreePosition}", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall, + ), + ), const SizedBox(height: 24), FilledButton( onPressed: () => GoRouter.of(context).go("/voting"), diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index da4ff772f..c86b6f245 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -103,6 +103,15 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); final running = job.stage != "done" && job.stage != "error"; + // Confirmed vote txs (per proposal), shown as evidence on the done state. + final confirmedVotes = (ref + .watch(votingSessionProvider(widget.roundId)) + .value + ?.recovery + ?.votes ?? + const <VotingVoteRecovery>[]) + .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) + .toList(); return PopScope( canPop: !running, @@ -192,6 +201,16 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { ), ), ], + for (final v in confirmedVotes) + Padding( + padding: const EdgeInsets.only(top: 4), + child: SelectableText( + "Proposal ${v.proposalId}: ${v.txHash} · " + "tree ${v.vcTreePosition}", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodySmall, + ), + ), const SizedBox(height: 24), if (job.stage == "error") ...[ SelectableText( From ab4c990c24b97c9eccae1c34e61bf10bb3341880 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 16:24:10 +0800 Subject: [PATCH 087/189] chore: pin dependency patches to pushed git revs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the machine-local path patches with the pushed branches so the build is reproducible anywhere: - zcash_voting: dependency rev 54e6c72 -> aa5338f1 (feat/sqlx-storage: SQL alias fixes, voting-circuits 0.10.0 pin, PirProofSource, witness pruning, prove stacks); the patch section is removed — a patch keyed by its own git URL must point at a different source, so the rev lives in the dependency spec itself - voting-circuits: git rev 4403369 (feat/zsa-orchard-0.10: 0.10.0 release source + ZSA-orchard note API shim) - pir-client: git rev b704640 (feat/async-circuit-root-getter on hhanh00/vote-nullifier-pir: public circuit_root accessor for the async client) --- Cargo.lock | 5 +++++ Cargo.toml | 20 +++++++------------- rust/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7acb35598..5d6f9d026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8207,6 +8207,7 @@ dependencies = [ [[package]] name = "pir-client" version = "0.4.0-rc.7" +source = "git+https://github.com/hhanh00/vote-nullifier-pir.git?rev=b704640df339a98330a5b8e4582144fde67d0b0c#b704640df339a98330a5b8e4582144fde67d0b0c" dependencies = [ "anyhow", "ff", @@ -13209,6 +13210,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" dependencies = [ "anyhow", "ff", @@ -13224,6 +13226,7 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" dependencies = [ "base64 0.22.1", "ff", @@ -13238,6 +13241,7 @@ dependencies = [ [[package]] name = "voting-circuits" version = "0.10.0" +source = "git+https://github.com/hhanh00/voting-circuits.git?rev=44033690874bc8b92cf015426d785b0b2e107035#44033690874bc8b92cf015426d785b0b2e107035" dependencies = [ "blake2b_simd", "ff", @@ -14411,6 +14415,7 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index bb64a93e3..b92c19a89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,19 +48,13 @@ zcash_spec = { git = "https://github.com/zcash-shielded-assets/zcash_spec", rev halo2_gadgets = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_proofs = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } halo2_poseidon = { git = "https://github.com/zcash-shielded-assets/halo2", rev = "dcdbd1df2b30fd8d709c1a7c4ad9c4e091789d00" } -# Local voting-circuits: 0.10.0 release source + the ZSA-orchard note API -# shim (from_parts asset arg), matching the chain's verifier. See -# ~/projects/voting-circuits (branch feat/zsa-orchard-0.10). -voting-circuits = { path = "/Users/hanh/projects/voting-circuits" } -# Local patched pir-client: the async PirClient lacks a public circuit_root +# 0.10.0 release source + the ZSA-orchard note API shim (from_parts asset +# arg), matching the chain's verifier. Branch feat/zsa-orchard-0.10. +voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev = "44033690874bc8b92cf015426d785b0b2e107035" } +# Patched pir-client: the async PirClient lacks a public circuit_root # accessor (private field), which the fork's PirProofSource trait needs. -# NOTE: the fork's own [patch.crates-io] does NOT apply to this workspace — -# cargo only honors patches in the workspace root manifest. -pir-client = { path = "/Users/hanh/projects/pir-client-0.4.0-rc.7" } +# Branch feat/async-circuit-root-getter. NOTE: patches only apply from the +# workspace root manifest. +pir-client = { git = "https://github.com/hhanh00/vote-nullifier-pir.git", rev = "b704640df339a98330a5b8e4582144fde67d0b0c" } -# Local fork fixes not yet on the pinned rev: queries.rs referenced the -# voting_votes table as `votes` without an alias, breaking ballot-intent -# writes and vote submission recording. See ~/projects/zcash_voting. -[patch."https://github.com/hhanh00/zcash_voting.git"] -zcash_voting = { path = "/Users/hanh/projects/zcash_voting/zcash_voting" } diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f51cd5fa1..d905b4284 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,7 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } -zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "54e6c72ceae7ef4fd27129cf1e5484df5048f0a7", features = ["zsa-orchard"] } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "aa5338f112a47626cd0fa79ca25cdf544c918b28", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" From 52f3c868aee603afae7148a1f5adaebeaec44068 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 19:31:29 +0800 Subject: [PATCH 088/189] feat: show proposal title and selection in the ballot evidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The done and confirmation screens listed 'Proposal N: <tx> · tree N'. Add a votingRoundProposals provider (chain round status: id, title, option id -> label) and render each confirmed vote as '<title> — <option label>' above its tx hash and tree position. The confirmation page now receives chainUrl to fetch the proposals. --- lib/pages/voting_confirmation.dart | 27 ++++++- lib/pages/voting_status.dart | 20 ++++- lib/router.dart | 1 + lib/store.dart | 56 ++++++++++++++ lib/store.g.dart | 114 ++++++++++++++++++++++++++++- 5 files changed, 212 insertions(+), 6 deletions(-) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 120da5e04..84ba407fd 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -10,8 +10,14 @@ import 'package:zkool/utils.dart'; class VotingConfirmationPage extends ConsumerStatefulWidget { final String roundId; final String? roundName; + final String chainUrl; - const VotingConfirmationPage({super.key, required this.roundId, this.roundName}); + const VotingConfirmationPage({ + super.key, + required this.roundId, + this.roundName, + this.chainUrl = "", + }); @override ConsumerState<VotingConfirmationPage> createState() => @@ -34,6 +40,22 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> const <VotingVoteRecovery>[]) .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) .toList(); + // Human-readable ballot evidence: proposal titles and option labels. + final proposals = (ref + .watch(votingRoundProposalsProvider( + widget.roundId, + widget.chainUrl, + )) + .value ?? + const <VotingProposalInfo>[]) + .asMap(); + + String voteLabel(VotingVoteRecovery v) { + final proposal = proposals[v.proposalId]; + final title = proposal?.title ?? "Proposal ${v.proposalId}"; + final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice + 1}"; + return "$title — $choice"; + } return Scaffold( appBar: AppBar(title: const Text("Vote submitted")), @@ -72,8 +94,7 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> Padding( padding: const EdgeInsets.only(top: 8), child: SelectableText( - "Proposal ${v.proposalId}: ${v.txHash} · " - "tree ${v.vcTreePosition}", + "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}", textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall, ), diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index c86b6f245..91a811357 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -112,6 +112,22 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { const <VotingVoteRecovery>[]) .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) .toList(); + // Human-readable ballot evidence: proposal titles and option labels. + final proposals = (ref + .watch(votingRoundProposalsProvider( + widget.roundId, + widget.chainUrl, + )) + .value ?? + const <VotingProposalInfo>[]) + .asMap(); + + String voteLabel(VotingVoteRecovery v) { + final proposal = proposals[v.proposalId]; + final title = proposal?.title ?? "Proposal ${v.proposalId}"; + final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice + 1}"; + return "$title — $choice"; + } return PopScope( canPop: !running, @@ -205,8 +221,7 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { Padding( padding: const EdgeInsets.only(top: 4), child: SelectableText( - "Proposal ${v.proposalId}: ${v.txHash} · " - "tree ${v.vcTreePosition}", + "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}", textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall, ), @@ -237,6 +252,7 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { extra: { "roundId": widget.roundId, "roundName": widget.roundName, + "chainUrl": widget.chainUrl, }, ), child: const Text("Done"), diff --git a/lib/router.dart b/lib/router.dart index f8d5b65ff..189d1e8a2 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -181,6 +181,7 @@ GoRouter router(bool disclaimerAccepted, bool recoveryMode) => GoRouter( return VotingConfirmationPage( roundId: args['roundId'] as String, roundName: args['roundName'] as String?, + chainUrl: args['chainUrl'] as String? ?? "", ); }, ), diff --git a/lib/store.dart b/lib/store.dart index 9ec8a573a..73ee24ee5 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1389,6 +1389,62 @@ Future<String> votingRoundTitle(Ref ref, String roundId, String chainUrl) async return roundId; } +/// One round proposal with its option labels, from the vote chain round +/// status — used to render human-readable ballot evidence. +class VotingProposalInfo { + final int id; + final String title; + final Map<int, String> optionLabels; + + const VotingProposalInfo({ + required this.id, + required this.title, + required this.optionLabels, + }); +} + +/// Parsed proposals (id, title, option id → label) for a round, from the +/// chain round status. Empty when the fetch fails. +@riverpod +Future<List<VotingProposalInfo>> votingRoundProposals( + Ref ref, + String roundId, + String chainUrl, +) async { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: chainUrl, + roundId: roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) return const []; + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final proposals = round['proposals'] as List<dynamic>? ?? []; + final result = <VotingProposalInfo>[]; + for (final p in proposals) { + if (p is! Map) continue; + final pid = p['id']; + if (pid is! int || pid < 1) continue; + final title = (p['title'] ?? "Proposal $pid").toString(); + var options = <int, String>{}; + final opts = p['options'] as List<dynamic>? ?? []; + for (final entry in opts.asMap().entries) { + final o = entry.value; + if (o is! Map) continue; + final id = (o['index'] is int) ? o['index'] as int : entry.key; + options[id] = + (o['label'] ?? o['short_title'] ?? o['title'] ?? "Option").toString(); + } + if (options.isEmpty) { + // Vote-sdk default: Yes/No when options are missing. + options = const {0: "Yes", 1: "No"}; + } + result.add(VotingProposalInfo(id: pid, title: title, optionLabels: options)); + } + return result; +} + /// Resolved and authenticated voting config for the configured source URL. /// `build()` returns the last cached resolved config without touching the /// network (so merely reading the provider never triggers a fetch); call diff --git a/lib/store.g.dart b/lib/store.g.dart index 0e17d583c..86020e2b1 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1674,6 +1674,118 @@ final class VotingRoundTitleFamily extends $Family String toString() => r'votingRoundTitleProvider'; } +/// Parsed proposals (id, title, option id → label) for a round, from the +/// chain round status. Empty when the fetch fails. + +@ProviderFor(votingRoundProposals) +const votingRoundProposalsProvider = VotingRoundProposalsFamily._(); + +/// Parsed proposals (id, title, option id → label) for a round, from the +/// chain round status. Empty when the fetch fails. + +final class VotingRoundProposalsProvider extends $FunctionalProvider< + AsyncValue<List<VotingProposalInfo>>, + List<VotingProposalInfo>, + FutureOr<List<VotingProposalInfo>>> + with + $FutureModifier<List<VotingProposalInfo>>, + $FutureProvider<List<VotingProposalInfo>> { + /// Parsed proposals (id, title, option id → label) for a round, from the + /// chain round status. Empty when the fetch fails. + const VotingRoundProposalsProvider._( + {required VotingRoundProposalsFamily super.from, + required ( + String, + String, + ) + super.argument}) + : super( + retry: null, + name: r'votingRoundProposalsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingRoundProposalsHash(); + + @override + String toString() { + return r'votingRoundProposalsProvider' + '' + '$argument'; + } + + @$internal + @override + $FutureProviderElement<List<VotingProposalInfo>> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr<List<VotingProposalInfo>> create(Ref ref) { + final argument = this.argument as ( + String, + String, + ); + return votingRoundProposals( + ref, + argument.$1, + argument.$2, + ); + } + + @override + bool operator ==(Object other) { + return other is VotingRoundProposalsProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$votingRoundProposalsHash() => + r'f8e7d46668f5f221a85e0eb62b9c7ec2462a5a6e'; + +/// Parsed proposals (id, title, option id → label) for a round, from the +/// chain round status. Empty when the fetch fails. + +final class VotingRoundProposalsFamily extends $Family + with + $FunctionalFamilyOverride< + FutureOr<List<VotingProposalInfo>>, + ( + String, + String, + )> { + const VotingRoundProposalsFamily._() + : super( + retry: null, + name: r'votingRoundProposalsProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// Parsed proposals (id, title, option id → label) for a round, from the + /// chain round status. Empty when the fetch fails. + + VotingRoundProposalsProvider call( + String roundId, + String chainUrl, + ) => + VotingRoundProposalsProvider._(argument: ( + roundId, + chainUrl, + ), from: this); + + @override + String toString() => r'votingRoundProposalsProvider'; +} + /// Resolved and authenticated voting config for the configured source URL. /// `build()` returns the last cached resolved config without touching the /// network (so merely reading the provider never triggers a fetch); call @@ -1859,7 +1971,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'a283728879caa8ee179da7d5bf490d4e2da6c217'; + r'916ea9b36272623d969a1f8b7bb9a61e95d5f56c'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → From 4fcaa220f80391e38f907df6d259e610f8de2462 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 19:43:48 +0800 Subject: [PATCH 089/189] fix: render option labels with vote-sdk ids, not 1-based positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ballot evidence fell back to 'Option ${choice + 1}', which showed choice 1 (Oppose, option id 1) as 'Option 2' — off by one against the vote-sdk's 0-based option ids. Fall back to the option id itself; the proposal label ('Oppose') still renders once the round proposals fetch resolves. --- lib/pages/voting_confirmation.dart | 4 +++- lib/pages/voting_status.dart | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 84ba407fd..6be80c004 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -53,7 +53,9 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> String voteLabel(VotingVoteRecovery v) { final proposal = proposals[v.proposalId]; final title = proposal?.title ?? "Proposal ${v.proposalId}"; - final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice + 1}"; + // Option ids are the vote-sdk `index` values (omitted = 0 for the + // first); never render 1-based list positions. + final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice}"; return "$title — $choice"; } diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index 91a811357..d8895a4c7 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -125,7 +125,9 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { String voteLabel(VotingVoteRecovery v) { final proposal = proposals[v.proposalId]; final title = proposal?.title ?? "Proposal ${v.proposalId}"; - final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice + 1}"; + // Option ids are the vote-sdk `index` values (omitted = 0 for the + // first); never render 1-based list positions. + final choice = proposal?.optionLabels[v.choice] ?? "Option ${v.choice}"; return "$title — $choice"; } From 8811c975ed46328637908cff4187de62a58e2029 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 19:45:20 +0800 Subject: [PATCH 090/189] fix: key ballot evidence proposals by id, not list position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The proposal lookup used asMap(), which keys by list index — so a single-proposal round (proposal id 1) fell back to 'Option N' and multi-proposal rounds looked up off by one (proposal 1's vote paired with proposal 2's title). Key the map by p.id. --- lib/pages/voting_confirmation.dart | 21 ++++++++++++--------- lib/pages/voting_status.dart | 21 ++++++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 6be80c004..e5057f396 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -40,15 +40,18 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> const <VotingVoteRecovery>[]) .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) .toList(); - // Human-readable ballot evidence: proposal titles and option labels. - final proposals = (ref - .watch(votingRoundProposalsProvider( - widget.roundId, - widget.chainUrl, - )) - .value ?? - const <VotingProposalInfo>[]) - .asMap(); + // Human-readable ballot evidence: proposal titles and option labels, + // keyed by proposal id (not list position). + final proposals = { + for (final p in (ref + .watch(votingRoundProposalsProvider( + widget.roundId, + widget.chainUrl, + )) + .value ?? + const <VotingProposalInfo>[])) + p.id: p, + }; String voteLabel(VotingVoteRecovery v) { final proposal = proposals[v.proposalId]; diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index d8895a4c7..f71cba68f 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -112,15 +112,18 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { const <VotingVoteRecovery>[]) .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) .toList(); - // Human-readable ballot evidence: proposal titles and option labels. - final proposals = (ref - .watch(votingRoundProposalsProvider( - widget.roundId, - widget.chainUrl, - )) - .value ?? - const <VotingProposalInfo>[]) - .asMap(); + // Human-readable ballot evidence: proposal titles and option labels, + // keyed by proposal id (not list position). + final proposals = { + for (final p in (ref + .watch(votingRoundProposalsProvider( + widget.roundId, + widget.chainUrl, + )) + .value ?? + const <VotingProposalInfo>[])) + p.id: p, + }; String voteLabel(VotingVoteRecovery v) { final proposal = proposals[v.proposalId]; From 87c6be3d23c1624b20a5766eb702764cd3f0aff7 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 19:59:07 +0800 Subject: [PATCH 091/189] fix: resolve share-window timing from the chain round status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The voting pages never pass ceremonyStart/voteEnd (both push sites omit them), so the status page got ceremonyStart=0 and voteEnd=null and the share plan could never schedule — the round stayed on 'Waiting for the share window' even after the window opened. Resolve both from the chain round status (ceremony_phase_start / vote_end_time) inside the job when they are missing. --- lib/store.dart | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/store.dart b/lib/store.dart index 73ee24ee5..d0e5d3e09 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1577,9 +1577,20 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { // flow never passes shareServerUrls, so fall back to the configured // vote servers (mirrors vizor's context.config.voteServers). final shareUrls = await _effectiveShareServerUrls(shareServerUrls); + // The voting pages never pass ceremonyStart/voteEnd either — resolve + // them from the chain round status so the share plan can schedule. + var effectiveCeremony = ceremonyStart; + var effectiveVoteEnd = voteEnd; + if (effectiveCeremony == 0 || effectiveVoteEnd == null) { + final timing = await _roundShareTiming(chainUrl: chainUrl); + if (timing != null) { + effectiveCeremony = timing.ceremonyStart; + effectiveVoteEnd = timing.voteEnd; + } + } final shared = await _submitShares( - ceremonyStart: ceremonyStart, - voteEnd: voteEnd, + ceremonyStart: effectiveCeremony, + voteEnd: effectiveVoteEnd, shareServerUrls: shareUrls, singleShare: singleShare, ); @@ -1819,6 +1830,28 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { return allShares ? "Waiting for the share window" : "Waiting for the next step"; } + /// Resolves the round's ceremony start / vote end from the chain round + /// status when the flow didn't provide them (the voting pages never pass + /// them, and the share plan needs both to schedule submissions). Returns + /// null when the fetch fails or the fields are missing. + Future<({int ceremonyStart, int voteEnd})?> _roundShareTiming({ + required String chainUrl, + }) async { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: chainUrl, + roundId: roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) return null; + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final ceremony = round['ceremony_phase_start']; + final end = round['vote_end_time']; + if (ceremony is! int || end is! int) return null; + return (ceremonyStart: ceremony, voteEnd: end); + } + /// The vote chain servers double as helper (share) servers. The voting /// flow never passes `shareServerUrls`, so fall back to the configured /// vote servers — mirrors vizor's `context.config.voteServers`. From c61dd21e4371058e0b4c9a4414849b2ccab925af Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 20:07:02 +0800 Subject: [PATCH 092/189] fix: submit helper shares from the confirmed votes' payloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _submitShares paired the share plan against the unconfirmed share delegation rows — but those rows only exist after a submission records them, so the first submission could never start and the round stayed on 'Waiting for the share window' forever. Mirror vizor's commitment-driven submission: new FRBs enumerate the confirmed votes' share payloads (voting_share_payloads) and plan submissions by count with policy-sized CSPRNG entropy (voting_share_plans, mirroring planShareSubmissions). The job submits each payload with its planned submitAt and records the delegation rows; the background tracker polls the helpers until confirmation. --- lib/src/rust/api/voting.dart | 49 ++++++++- lib/src/rust/frb_generated.dart | 186 ++++++++++++++++++++++++++++++-- lib/store.dart | 81 +++++++++----- rust/src/api/voting.rs | 101 +++++++++++++++++ rust/src/frb_generated.rs | 181 +++++++++++++++++++++++++++++-- 5 files changed, 549 insertions(+), 49 deletions(-) diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index e5f4e84cb..b528202b9 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -11,7 +11,7 @@ part 'voting.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `config_switch_kind_string`, `fork_network_string`, `from_resolved`, `prepare_bundle`, `to_fork`, `votechain_proxy` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `VotingShareDelivery` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` /// Creates and persists a fresh app-owned voting hotkey (hex stored secret). Future<String> votingHotkeyCreate({required Coin c}) => @@ -311,9 +311,33 @@ Future<int> votingSyncTree( RustLib.instance.api.crateApiVotingVotingSyncTree( roundId: roundId, voteNodeUrl: voteNodeUrl, c: c); -/// Computes the share tracking plan for a round: summary counts, next poll -/// delay, last-moment flag, and freshly planned submissions (with local -/// entropy) for the unconfirmed shares. +/// Enumerates the share payloads of the round's confirmed votes — the +/// first-pass submission source. +Future<List<VotingShareSubmissionPayload>> votingSharePayloads( + {required String roundId, required Coin c}) => + RustLib.instance.api + .crateApiVotingVotingSharePayloads(roundId: roundId, c: c); + +/// Count-based share submission plans (submitAt + target servers per share), +/// mirroring vizor's `planShareSubmissions`: policy-sized CSPRNG entropy +/// drawn per call, timing from the round's ceremony start / vote end. +Future<List<VotingSharePlanItem>> votingSharePlans( + {required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingSharePlans( + shareCount: shareCount, + serverUrls: serverUrls, + now: now, + voteEnd: voteEnd, + ceremonyStart: ceremonyStart, + singleShare: singleShare, + c: c); + Future<VotingSharePlan> votingSharePlan( {required String roundId, required BigInt now, @@ -861,6 +885,23 @@ sealed class VotingSharePlanItem with _$VotingSharePlanItem { }) = _VotingSharePlanItem; } +/// Computes the share tracking plan for a round: summary counts, next poll +/// delay, last-moment flag, and freshly planned submissions (with local +/// entropy) for the unconfirmed shares. +/// One share of a confirmed vote pending helper submission. First-pass +/// submission must enumerate from the confirmed votes' recovery bundles — +/// the `voting_share_delegations` rows only exist after a submission +/// records them. +@freezed +sealed class VotingShareSubmissionPayload with _$VotingShareSubmissionPayload { + const factory VotingShareSubmissionPayload({ + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + }) = _VotingShareSubmissionPayload; +} + /// Share tracking summary, one-to-one with the fork's `ShareTrackingSummary`. @freezed sealed class VotingShareTrackingSummary with _$VotingShareTrackingSummary { diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 2734ff377..45ccf458f 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 1940546024; + int get rustContentHash => 1724058360; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -822,6 +822,9 @@ abstract class RustLibApi extends BaseApi { required int shareIndex, required Coin c}); + Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads( + {required String roundId, required Coin c}); + Future<VotingSharePlan> crateApiVotingVotingSharePlan( {required String roundId, required BigInt now, @@ -831,6 +834,15 @@ abstract class RustLibApi extends BaseApi { required bool singleShare, required Coin c}); + Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans( + {required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c}); + Future<void> crateApiVotingVotingShareRecord( {required String roundId, required int bundleIndex, @@ -7481,6 +7493,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["roundId", "bundleIndex", "proposalId", "shareIndex", "c"], ); + @override + Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads( + {required String roundId, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 219, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_share_submission_payload, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingSharePayloadsConstMeta, + argValues: [roundId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingSharePayloadsConstMeta => + const TaskConstMeta( + debugName: "voting_share_payloads", + argNames: ["roundId", "c"], + ); + @override Future<VotingSharePlan> crateApiVotingVotingSharePlan( {required String roundId, @@ -7502,7 +7543,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + funcId: 220, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7537,6 +7578,62 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ], ); + @override + Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans( + {required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(shareCount, serializer); + sse_encode_list_String(serverUrls, serializer); + sse_encode_u_64(now, serializer); + sse_encode_u_64(voteEnd, serializer); + sse_encode_u_64(ceremonyStart, serializer); + sse_encode_bool(singleShare, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 221, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_share_plan_item, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingSharePlansConstMeta, + argValues: [ + shareCount, + serverUrls, + now, + voteEnd, + ceremonyStart, + singleShare, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingSharePlansConstMeta => + const TaskConstMeta( + debugName: "voting_share_plans", + argNames: [ + "shareCount", + "serverUrls", + "now", + "voteEnd", + "ceremonyStart", + "singleShare", + "c" + ], + ); + @override Future<void> crateApiVotingVotingShareRecord( {required String roundId, @@ -7558,7 +7655,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7604,7 +7701,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7644,7 +7741,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + funcId: 224, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7690,7 +7787,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + funcId: 225, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7724,7 +7821,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 224, port: port_); + funcId: 226, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -7758,7 +7855,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 225, port: port_); + funcId: 227, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -8710,6 +8807,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { .toList(); } + @protected + List<VotingShareSubmissionPayload> + dco_decode_list_voting_share_submission_payload(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List<dynamic>) + .map(dco_decode_voting_share_submission_payload) + .toList(); + } + @protected List<VotingShareWorkflow> dco_decode_list_voting_share_workflow(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -9936,6 +10042,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List<dynamic>; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return VotingShareSubmissionPayload( + bundleIndex: dco_decode_u_32(arr[0]), + proposalId: dco_decode_u_32(arr[1]), + shareIndex: dco_decode_u_32(arr[2]), + vcTreePosition: dco_decode_opt_box_autoadd_u_64(arr[3]), + ); + } + @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( dynamic raw) { @@ -11255,6 +11376,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List<VotingShareSubmissionPayload> + sse_decode_list_voting_share_submission_payload( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = <VotingShareSubmissionPayload>[]; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_share_submission_payload(deserializer)); + } + return ans_; + } + @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( SseDeserializer deserializer) { @@ -12633,6 +12768,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { targetServers: var_targetServers); } + @protected + VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_bundleIndex = sse_decode_u_32(deserializer); + var var_proposalId = sse_decode_u_32(deserializer); + var var_shareIndex = sse_decode_u_32(deserializer); + var var_vcTreePosition = sse_decode_opt_box_autoadd_u_64(deserializer); + return VotingShareSubmissionPayload( + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + vcTreePosition: var_vcTreePosition); + } + @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( SseDeserializer deserializer) { @@ -13911,6 +14061,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_share_submission_payload( + List<VotingShareSubmissionPayload> self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_share_submission_payload(item, serializer); + } + } + @protected void sse_encode_list_voting_share_workflow( List<VotingShareWorkflow> self, SseSerializer serializer) { @@ -14922,6 +15082,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(self.targetServers, serializer); } + @protected + void sse_encode_voting_share_submission_payload( + VotingShareSubmissionPayload self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self.bundleIndex, serializer); + sse_encode_u_32(self.proposalId, serializer); + sse_encode_u_32(self.shareIndex, serializer); + sse_encode_opt_box_autoadd_u_64(self.vcTreePosition, serializer); + } + @protected void sse_encode_voting_share_tracking_summary( VotingShareTrackingSummary self, SseSerializer serializer) { diff --git a/lib/store.dart b/lib/store.dart index d0e5d3e09..6a0b39ead 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -2191,6 +2191,23 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } + /// Delay until the next planned share submission (min positive + /// submitAt − now), capped at an hour; 60s when nothing is pending. + int _shareTrackingDelaySeconds(List<VotingSharePlanItem> plans, int now) { + final nowBig = BigInt.from(now); + var minDelta = BigInt.zero; + var found = false; + for (final p in plans) { + final delta = p.submitAt - nowBig; + if (delta > BigInt.zero && (!found || delta < minDelta)) { + minDelta = delta; + found = true; + } + } + if (!found) return 60; + return minDelta > BigInt.from(3600) ? 3600 : minDelta.toInt(); + } + /// Converts UI drafts to the fork's DraftVote JSON for the commit step: /// drops skipped choices (validation rejects choice == num_options) and /// fills the fields the fork requires with no serde defaults. Returns null @@ -2225,33 +2242,41 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final c = coinContext.coin; state = state.copyWith(stage: "shares"); var submitted = false; + final voteEndValue = voteEnd; + if (voteEndValue == null || shareServerUrls.isEmpty) { + return false; + } final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final sharePlan = await votingSharePlan( - roundId: roundId, + // First-pass source: the confirmed votes' share payloads — the share + // delegation rows only exist after a submission records them, so the + // old unconfirmed-row pairing could never start (mirrors vizor's + // commitment-driven share submission). + final payloads = await votingSharePayloads(roundId: roundId, c: c); + if (payloads.isEmpty) return false; + final plans = await votingSharePlans( + shareCount: payloads.length, + serverUrls: shareServerUrls, now: BigInt.from(now), + voteEnd: BigInt.from(voteEndValue), ceremonyStart: BigInt.from(ceremonyStart), - voteEnd: voteEnd == null ? null : BigInt.from(voteEnd), - serverUrls: shareServerUrls, singleShare: singleShare, c: c, ); - final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); - final count = min(sharePlan.submissions.length, unconfirmed.length); - for (var i = 0; i < count; i++) { - final item = sharePlan.submissions[i]; - final share = unconfirmed[i]; + for (var i = 0; i < payloads.length && i < plans.length; i++) { + final payload = payloads[i]; + final plan = plans[i]; final wireJson = await votingShareWireJson( roundId: roundId, - bundleIndex: share.bundleIndex, - proposalId: share.proposalId, - shareIndex: share.shareIndex, - vcTreePosition: null, - submitAt: item.submitAt, + bundleIndex: payload.bundleIndex, + proposalId: payload.proposalId, + shareIndex: payload.shareIndex, + vcTreePosition: payload.vcTreePosition, + submitAt: plan.submitAt, c: c, ); final body = jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); - for (final server in item.targetServers) { + for (final server in plan.targetServers) { final res = await votechainSubmitShare( serverUrl: server, payloadJson: body, @@ -2266,26 +2291,24 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } await votingShareRecord( roundId: roundId, - bundleIndex: share.bundleIndex, - proposalId: share.proposalId, - shareIndex: share.shareIndex, - sentToUrls: item.targetServers, - submitAt: item.submitAt, + bundleIndex: payload.bundleIndex, + proposalId: payload.proposalId, + shareIndex: payload.shareIndex, + sentToUrls: plan.targetServers, + submitAt: plan.submitAt, c: c, ); submitted = true; } // Background tracking until every share confirms (or the vote window ends). - if (voteEnd != null && sharePlan.nextTrackingDelaySecs != null) { - _scheduleShareTracking( - delaySeconds: sharePlan.nextTrackingDelaySecs!.toInt(), - ceremonyStart: ceremonyStart, - voteEnd: voteEnd, - shareServerUrls: shareServerUrls, - singleShare: singleShare, - ); - } + _scheduleShareTracking( + delaySeconds: _shareTrackingDelaySeconds(plans, now), + ceremonyStart: ceremonyStart, + voteEnd: voteEndValue, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); return submitted; } diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 03ce39c17..03745d72a 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -1052,6 +1052,107 @@ pub async fn voting_sync_tree( /// delay, last-moment flag, and freshly planned submissions (with local /// entropy) for the unconfirmed shares. #[cfg_attr(feature = "flutter", frb)] +/// One share of a confirmed vote pending helper submission. First-pass +/// submission must enumerate from the confirmed votes' recovery bundles — +/// the `voting_share_delegations` rows only exist after a submission +/// records them. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingShareSubmissionPayload { + pub bundle_index: u32, + pub proposal_id: u32, + pub share_index: u32, + pub vc_tree_position: Option<u64>, +} + +/// Enumerates the share payloads of the round's confirmed votes — the +/// first-pass submission source. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_payloads( + round_id: &str, + c: &Coin, +) -> Result<Vec<VotingShareSubmissionPayload>> { + let account = c.account; + let round_id = round_id.to_string(); + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let snapshot = zcash_voting::recovery::round_snapshot(&db, &round_id).await?; + let mut payloads = Vec::new(); + for vote in snapshot.votes { + if vote.phase != zcash_voting::phases::VotePhase::Confirmed { + continue; + } + let Some(bundle) = + zcash_voting::vote::recovery_bundle(&db, &round_id, vote.bundle_index, vote.proposal_id) + .await? + else { + continue; + }; + for payload in zcash_voting::share::recover_payloads(&bundle)? { + payloads.push(VotingShareSubmissionPayload { + bundle_index: vote.bundle_index, + proposal_id: vote.proposal_id, + share_index: payload.enc_share.share_index, + vc_tree_position: vote.vc_tree_position.map(|p| p as u64), + }); + } + } + Ok(payloads) +} + +/// Count-based share submission plans (submitAt + target servers per share), +/// mirroring vizor's `planShareSubmissions`: policy-sized CSPRNG entropy +/// drawn per call, timing from the round's ceremony start / vote end. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_share_plans( + share_count: u32, + server_urls: Vec<String>, + now: u64, + vote_end: u64, + ceremony_start: u64, + single_share: bool, + c: &Coin, +) -> Result<Vec<VotingSharePlanItem>> { + let buffer = + zcash_voting::share_policy::last_moment_buffer_seconds(ceremony_start, vote_end); + let share_count = share_count as usize; + let required = zcash_voting::share_policy::share_submission_random_bytes_required( + share_count, + server_urls.len(), + now, + vote_end, + buffer, + single_share, + ); + let mut submit_at_random_bytes = vec![0u8; required.submit_at_random_bytes]; + let mut server_random_bytes = vec![0u8; required.server_random_bytes]; + OsRng + .try_fill_bytes(&mut submit_at_random_bytes) + .map_err(|e| anyhow!("failed to draw submit_at entropy: {e}"))?; + OsRng + .try_fill_bytes(&mut server_random_bytes) + .map_err(|e| anyhow!("failed to draw share-server entropy: {e}"))?; + let plans = zcash_voting::share_policy::plan_share_submissions( + share_count, + &server_urls, + now, + vote_end, + buffer, + single_share, + &submit_at_random_bytes, + &server_random_bytes, + )?; + Ok(plans + .into_iter() + .map(|p| VotingSharePlanItem { + submit_at: p.submit_at, + target_count: p.target_count, + target_servers: p.target_servers, + }) + .collect()) +} + pub async fn voting_share_plan( round_id: &str, now: u64, diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index fe4f71b3f..6bb8fe1a4 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1940546024; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1724058360; // Section: executor @@ -8698,6 +8698,45 @@ fn wire__crate__api__voting__voting_share_confirm_impl( }, ) } +fn wire__crate__api__voting__voting_share_payloads_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_payloads", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_share_payloads(&api_round_id, &api_c) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_share_plan_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -8749,6 +8788,57 @@ fn wire__crate__api__voting__voting_share_plan_impl( }, ) } +fn wire__crate__api__voting__voting_share_plans_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_share_plans", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_share_count = <u32>::sse_decode(&mut deserializer); + let api_server_urls = <Vec<String>>::sse_decode(&mut deserializer); + let api_now = <u64>::sse_decode(&mut deserializer); + let api_vote_end = <u64>::sse_decode(&mut deserializer); + let api_ceremony_start = <u64>::sse_decode(&mut deserializer); + let api_single_share = <bool>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_share_plans( + api_share_count, + api_server_urls, + api_now, + api_vote_end, + api_ceremony_start, + api_single_share, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_share_record_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -10141,6 +10231,18 @@ impl SseDecode for Vec<crate::api::voting::VotingSharePlanItem> { } } +impl SseDecode for Vec<crate::api::voting::VotingShareSubmissionPayload> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = <i32>::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(<crate::api::voting::VotingShareSubmissionPayload>::sse_decode(deserializer)); + } + return ans_; + } +} + impl SseDecode for Vec<crate::api::voting::VotingShareWorkflow> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -11706,6 +11808,22 @@ impl SseDecode for crate::api::voting::VotingSharePlanItem { } } +impl SseDecode for crate::api::voting::VotingShareSubmissionPayload { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_bundleIndex = <u32>::sse_decode(deserializer); + let mut var_proposalId = <u32>::sse_decode(deserializer); + let mut var_shareIndex = <u32>::sse_decode(deserializer); + let mut var_vcTreePosition = <Option<u64>>::sse_decode(deserializer); + return crate::api::voting::VotingShareSubmissionPayload { + bundle_index: var_bundleIndex, + proposal_id: var_proposalId, + share_index: var_shareIndex, + vc_tree_position: var_vcTreePosition, + }; + } +} + impl SseDecode for crate::api::voting::VotingShareTrackingSummary { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -12400,22 +12518,26 @@ fn pde_ffi_dispatcher_primary_impl( 218 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 219 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 220 => { + 219 => { + wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) + } + 220 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 221 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 222 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 221 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 223 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 222 => { + 224 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 223 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 224 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 225 => { + 225 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 226 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 227 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -14366,6 +14488,29 @@ impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingSharePlanItem> } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingShareSubmissionPayload { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.bundle_index.into_into_dart().into_dart(), + self.proposal_id.into_into_dart().into_dart(), + self.share_index.into_into_dart().into_dart(), + self.vc_tree_position.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingShareSubmissionPayload +{ +} +impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingShareSubmissionPayload> + for crate::api::voting::VotingShareSubmissionPayload +{ + fn into_into_dart(self) -> crate::api::voting::VotingShareSubmissionPayload { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingShareTrackingSummary { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -15505,6 +15650,16 @@ impl SseEncode for Vec<crate::api::voting::VotingSharePlanItem> { } } +impl SseEncode for Vec<crate::api::voting::VotingShareSubmissionPayload> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + <i32>::sse_encode(self.len() as _, serializer); + for item in self { + <crate::api::voting::VotingShareSubmissionPayload>::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec<crate::api::voting::VotingShareWorkflow> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -16610,6 +16765,16 @@ impl SseEncode for crate::api::voting::VotingSharePlanItem { } } +impl SseEncode for crate::api::voting::VotingShareSubmissionPayload { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + <u32>::sse_encode(self.bundle_index, serializer); + <u32>::sse_encode(self.proposal_id, serializer); + <u32>::sse_encode(self.share_index, serializer); + <Option<u64>>::sse_encode(self.vc_tree_position, serializer); + } +} + impl SseEncode for crate::api::voting::VotingShareTrackingSummary { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { From 0054892b60ccdb92d8c1c8d2086cb8e0bd1b15fe Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 20:07:10 +0800 Subject: [PATCH 093/189] chore: regenerate FRB bindings for the share payload/plan FRBs --- lib/src/rust/api/voting.freezed.dart | 363 +++++++++++++++++++++++++++ lib/src/rust/frb_generated.io.dart | 25 ++ lib/src/rust/frb_generated.web.dart | 25 ++ lib/store.g.dart | 2 +- 4 files changed, 414 insertions(+), 1 deletion(-) diff --git a/lib/src/rust/api/voting.freezed.dart b/lib/src/rust/api/voting.freezed.dart index 626558658..62833a0e5 100644 --- a/lib/src/rust/api/voting.freezed.dart +++ b/lib/src/rust/api/voting.freezed.dart @@ -10168,6 +10168,369 @@ class __$VotingSharePlanItemCopyWithImpl<$Res> } } +/// @nodoc +mixin _$VotingShareSubmissionPayload { + int get bundleIndex; + int get proposalId; + int get shareIndex; + BigInt? get vcTreePosition; + + /// Create a copy of VotingShareSubmissionPayload + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingShareSubmissionPayloadCopyWith<VotingShareSubmissionPayload> + get copyWith => _$VotingShareSubmissionPayloadCopyWithImpl< + VotingShareSubmissionPayload>( + this as VotingShareSubmissionPayload, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingShareSubmissionPayload && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition)); + } + + @override + int get hashCode => Object.hash( + runtimeType, bundleIndex, proposalId, shareIndex, vcTreePosition); + + @override + String toString() { + return 'VotingShareSubmissionPayload(bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, vcTreePosition: $vcTreePosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingShareSubmissionPayloadCopyWith<$Res> { + factory $VotingShareSubmissionPayloadCopyWith( + VotingShareSubmissionPayload value, + $Res Function(VotingShareSubmissionPayload) _then) = + _$VotingShareSubmissionPayloadCopyWithImpl; + @useResult + $Res call( + {int bundleIndex, + int proposalId, + int shareIndex, + BigInt? vcTreePosition}); +} + +/// @nodoc +class _$VotingShareSubmissionPayloadCopyWithImpl<$Res> + implements $VotingShareSubmissionPayloadCopyWith<$Res> { + _$VotingShareSubmissionPayloadCopyWithImpl(this._self, this._then); + + final VotingShareSubmissionPayload _self; + final $Res Function(VotingShareSubmissionPayload) _then; + + /// Create a copy of VotingShareSubmissionPayload + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? vcTreePosition = freezed, + }) { + return _then(_self.copyWith( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + vcTreePosition: freezed == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt?, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingShareSubmissionPayload]. +extension VotingShareSubmissionPayloadPatterns on VotingShareSubmissionPayload { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap<TResult extends Object?>( + TResult Function(_VotingShareSubmissionPayload value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map<TResult extends Object?>( + TResult Function(_VotingShareSubmissionPayload value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull<TResult extends Object?>( + TResult? Function(_VotingShareSubmissionPayload value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen<TResult extends Object?>( + TResult Function(int bundleIndex, int proposalId, int shareIndex, + BigInt? vcTreePosition)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload() when $default != null: + return $default(_that.bundleIndex, _that.proposalId, _that.shareIndex, + _that.vcTreePosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when<TResult extends Object?>( + TResult Function(int bundleIndex, int proposalId, int shareIndex, + BigInt? vcTreePosition) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload(): + return $default(_that.bundleIndex, _that.proposalId, _that.shareIndex, + _that.vcTreePosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull<TResult extends Object?>( + TResult? Function(int bundleIndex, int proposalId, int shareIndex, + BigInt? vcTreePosition)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingShareSubmissionPayload() when $default != null: + return $default(_that.bundleIndex, _that.proposalId, _that.shareIndex, + _that.vcTreePosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingShareSubmissionPayload implements VotingShareSubmissionPayload { + const _VotingShareSubmissionPayload( + {required this.bundleIndex, + required this.proposalId, + required this.shareIndex, + this.vcTreePosition}); + + @override + final int bundleIndex; + @override + final int proposalId; + @override + final int shareIndex; + @override + final BigInt? vcTreePosition; + + /// Create a copy of VotingShareSubmissionPayload + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingShareSubmissionPayloadCopyWith<_VotingShareSubmissionPayload> + get copyWith => __$VotingShareSubmissionPayloadCopyWithImpl< + _VotingShareSubmissionPayload>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingShareSubmissionPayload && + (identical(other.bundleIndex, bundleIndex) || + other.bundleIndex == bundleIndex) && + (identical(other.proposalId, proposalId) || + other.proposalId == proposalId) && + (identical(other.shareIndex, shareIndex) || + other.shareIndex == shareIndex) && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition)); + } + + @override + int get hashCode => Object.hash( + runtimeType, bundleIndex, proposalId, shareIndex, vcTreePosition); + + @override + String toString() { + return 'VotingShareSubmissionPayload(bundleIndex: $bundleIndex, proposalId: $proposalId, shareIndex: $shareIndex, vcTreePosition: $vcTreePosition)'; + } +} + +/// @nodoc +abstract mixin class _$VotingShareSubmissionPayloadCopyWith<$Res> + implements $VotingShareSubmissionPayloadCopyWith<$Res> { + factory _$VotingShareSubmissionPayloadCopyWith( + _VotingShareSubmissionPayload value, + $Res Function(_VotingShareSubmissionPayload) _then) = + __$VotingShareSubmissionPayloadCopyWithImpl; + @override + @useResult + $Res call( + {int bundleIndex, + int proposalId, + int shareIndex, + BigInt? vcTreePosition}); +} + +/// @nodoc +class __$VotingShareSubmissionPayloadCopyWithImpl<$Res> + implements _$VotingShareSubmissionPayloadCopyWith<$Res> { + __$VotingShareSubmissionPayloadCopyWithImpl(this._self, this._then); + + final _VotingShareSubmissionPayload _self; + final $Res Function(_VotingShareSubmissionPayload) _then; + + /// Create a copy of VotingShareSubmissionPayload + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? bundleIndex = null, + Object? proposalId = null, + Object? shareIndex = null, + Object? vcTreePosition = freezed, + }) { + return _then(_VotingShareSubmissionPayload( + bundleIndex: null == bundleIndex + ? _self.bundleIndex + : bundleIndex // ignore: cast_nullable_to_non_nullable + as int, + proposalId: null == proposalId + ? _self.proposalId + : proposalId // ignore: cast_nullable_to_non_nullable + as int, + shareIndex: null == shareIndex + ? _self.shareIndex + : shareIndex // ignore: cast_nullable_to_non_nullable + as int, + vcTreePosition: freezed == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt?, + )); + } +} + /// @nodoc mixin _$VotingShareTrackingSummary { BigInt get total; diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 1a4f93cc6..2a40e3ec5 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -434,6 +434,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingSharePlanItem> dco_decode_list_voting_share_plan_item(dynamic raw); + @protected + List<VotingShareSubmissionPayload> + dco_decode_list_voting_share_submission_payload(dynamic raw); + @protected List<VotingShareWorkflow> dco_decode_list_voting_share_workflow(dynamic raw); @@ -720,6 +724,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingSharePlanItem dco_decode_voting_share_plan_item(dynamic raw); + @protected + VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( + dynamic raw); + @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( dynamic raw); @@ -1155,6 +1163,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { List<VotingSharePlanItem> sse_decode_list_voting_share_plan_item( SseDeserializer deserializer); + @protected + List<VotingShareSubmissionPayload> + sse_decode_list_voting_share_submission_payload( + SseDeserializer deserializer); + @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( SseDeserializer deserializer); @@ -1466,6 +1479,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSharePlanItem sse_decode_voting_share_plan_item( SseDeserializer deserializer); + @protected + VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( + SseDeserializer deserializer); + @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( SseDeserializer deserializer); @@ -1928,6 +1945,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_list_voting_share_plan_item( List<VotingSharePlanItem> self, SseSerializer serializer); + @protected + void sse_encode_list_voting_share_submission_payload( + List<VotingShareSubmissionPayload> self, SseSerializer serializer); + @protected void sse_encode_list_voting_share_workflow( List<VotingShareWorkflow> self, SseSerializer serializer); @@ -2252,6 +2273,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_share_plan_item( VotingSharePlanItem self, SseSerializer serializer); + @protected + void sse_encode_voting_share_submission_payload( + VotingShareSubmissionPayload self, SseSerializer serializer); + @protected void sse_encode_voting_share_tracking_summary( VotingShareTrackingSummary self, SseSerializer serializer); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 04b4a467a..a0429792e 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -436,6 +436,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingSharePlanItem> dco_decode_list_voting_share_plan_item(dynamic raw); + @protected + List<VotingShareSubmissionPayload> + dco_decode_list_voting_share_submission_payload(dynamic raw); + @protected List<VotingShareWorkflow> dco_decode_list_voting_share_workflow(dynamic raw); @@ -722,6 +726,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingSharePlanItem dco_decode_voting_share_plan_item(dynamic raw); + @protected + VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( + dynamic raw); + @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( dynamic raw); @@ -1157,6 +1165,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { List<VotingSharePlanItem> sse_decode_list_voting_share_plan_item( SseDeserializer deserializer); + @protected + List<VotingShareSubmissionPayload> + sse_decode_list_voting_share_submission_payload( + SseDeserializer deserializer); + @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( SseDeserializer deserializer); @@ -1468,6 +1481,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSharePlanItem sse_decode_voting_share_plan_item( SseDeserializer deserializer); + @protected + VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( + SseDeserializer deserializer); + @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( SseDeserializer deserializer); @@ -1930,6 +1947,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_list_voting_share_plan_item( List<VotingSharePlanItem> self, SseSerializer serializer); + @protected + void sse_encode_list_voting_share_submission_payload( + List<VotingShareSubmissionPayload> self, SseSerializer serializer); + @protected void sse_encode_list_voting_share_workflow( List<VotingShareWorkflow> self, SseSerializer serializer); @@ -2254,6 +2275,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_share_plan_item( VotingSharePlanItem self, SseSerializer serializer); + @protected + void sse_encode_voting_share_submission_payload( + VotingShareSubmissionPayload self, SseSerializer serializer); + @protected void sse_encode_voting_share_tracking_summary( VotingShareTrackingSummary self, SseSerializer serializer); diff --git a/lib/store.g.dart b/lib/store.g.dart index 86020e2b1..e31b93c4b 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1971,7 +1971,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'916ea9b36272623d969a1f8b7bb9a61e95d5f56c'; + r'eeef388d321875ba8c2035e67ba5ad5ae7e7bfa7'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → From dfd5db0fe9151f0bf0b0ae394b8108e75138fd33 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 21:23:56 +0800 Subject: [PATCH 094/189] fix: parse vote-sdk tally entries per-entry decision and amount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit decisionOf/amountOf looked up the decision/amount keys on the top-level tally body instead of each tally entry, so every entry parsed as decision 0 with a null amount and the results page showed 'No tally data for this round'. Read the keys from the entry itself, and skip entries without a decision key — the vote-sdk emits an aggregate total row alongside the per-decision rows, which would otherwise double-count. --- lib/pages/voting_results.dart | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart index 2fa625b18..50be841f0 100644 --- a/lib/pages/voting_results.dart +++ b/lib/pages/voting_results.dart @@ -111,12 +111,39 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { ? v : num.tryParse(v?.toString() ?? ""); - int decisionOf(Object? v) => toInt(value(["vote_decision", "voteDecision", "decision", "choice", "index", "option", "option_id", "optionId"])) ?? 0; + const decisionKeys = [ + "vote_decision", + "voteDecision", + "decision", + "choice", + "index", + "option", + "option_id", + "optionId", + ]; + const amountKeys = ["total_value", "totalValue", "amount", "votes", "value"]; - num? amountOf(Object? v) => toNum(value(["total_value", "totalValue", "amount", "votes", "value"])); + int decisionOf(Object? v) { + if (v is! Map) return 0; + for (final k in decisionKeys) { + if (v.containsKey(k)) return toInt(v[k]) ?? 0; + } + return 0; + } + + num? amountOf(Object? v) { + if (v is! Map) return null; + for (final k in amountKeys) { + if (v.containsKey(k)) return toNum(v[k]); + } + return null; + } void addDirect(Object? object, int proposalId) { if (object is! Map) return; + // A tally entry without a decision key is the aggregate total row — + // skip it so per-option amounts don't double-count. + if (!object.keys.any((k) => decisionKeys.contains(k))) return; final d = decisionOf(object); final a = amountOf(object); if (a != null) { From e15bafc82998a9d16f52d1c365b20eee535a19bf Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 21:28:22 +0800 Subject: [PATCH 095/189] feat: show proposal titles and option labels in the tally results The results page rendered 'Proposal N' and 1-based 'Option N+1' (the same off-by-one as the ballot evidence). Render the proposal title and the option label for each tally entry, keyed by the vote-sdk decision ids. --- lib/pages/voting_results.dart | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart index 50be841f0..b8e7f7055 100644 --- a/lib/pages/voting_results.dart +++ b/lib/pages/voting_results.dart @@ -197,6 +197,16 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { final pinlock = ref.watch(lifecycleProvider); if (pinlock.value ?? false) return PinLock(); + // Proposal titles and option labels, keyed by proposal id (not list + // position) — decision ids are the vote-sdk option ids. + final proposalsAsync = ref.watch( + votingRoundProposalsProvider(widget.roundId, widget.chainUrl), + ); + final proposals = { + for (final p in (proposalsAsync.value ?? const <VotingProposalInfo>[])) + p.id: p, + }; + return Scaffold( appBar: AppBar(title: Text("${widget.roundId} results")), body: _error != null @@ -218,13 +228,14 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { final winner = tally.entries.reduce( (a, b) => a.value >= b.value ? a : b, ); + final proposal = proposals[pid]; return Card( child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text("Proposal $pid", + Text(proposal?.title ?? "Proposal $pid", style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 8), ...tally.entries.map((e) { @@ -239,7 +250,8 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { SizedBox( width: 80, child: Text( - "Option ${e.key + 1}", + proposal?.optionLabels[e.key] ?? + "Option ${e.key}", style: TextStyle( fontWeight: winning ? FontWeight.bold From 7b97c6a62b13da3f819f98303865610429205444 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 21:31:47 +0800 Subject: [PATCH 096/189] fix: tally entries without a decision key are decision 0, not a total The vote-sdk emits one tally row per decision, with decision 0 omitting the vote_decision field (the default). The previous 'skip the aggregate total row' logic dropped decision 0 entirely, so a 50/50 round rendered as 100% on the other option. --- lib/pages/voting_results.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart index b8e7f7055..4dd95de63 100644 --- a/lib/pages/voting_results.dart +++ b/lib/pages/voting_results.dart @@ -141,9 +141,9 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { void addDirect(Object? object, int proposalId) { if (object is! Map) return; - // A tally entry without a decision key is the aggregate total row — - // skip it so per-option amounts don't double-count. - if (!object.keys.any((k) => decisionKeys.contains(k))) return; + // The vote-sdk emits one row per decision; decision 0 omits the + // decision key (the default), so a missing key maps to 0 — it is NOT + // an aggregate total row. final d = decisionOf(object); final a = amountOf(object); if (a != null) { From fb449a8651db5e9fd901893274666900fb16ee2b Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 21:33:35 +0800 Subject: [PATCH 097/189] feat: results page title shows the round title --- lib/pages/voting_results.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart index 4dd95de63..1029fdc7f 100644 --- a/lib/pages/voting_results.dart +++ b/lib/pages/voting_results.dart @@ -207,8 +207,13 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { p.id: p, }; + final roundTitle = (ref + .watch(votingRoundTitleProvider(widget.roundId, widget.chainUrl)) + .value ?? + widget.roundId); + return Scaffold( - appBar: AppBar(title: Text("${widget.roundId} results")), + appBar: AppBar(title: Text(roundTitle)), body: _error != null ? Center(child: Text(_error!)) : _tallies.isEmpty From ca013ad6d649a4458b022b61495e78e6863acff9 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 21:44:26 +0800 Subject: [PATCH 098/189] fix: don't re-send recorded shares; refresh status after tracking - voting_share_payloads now excludes shares already recorded in voting_share_delegations, so a resume no longer re-submits the same shares (it was duplicating submissions to the helpers). - _submitShares arms the background tracker even when all shares are already recorded, so confirmations still get polled after a restart. - _trackShares refreshes the voting session after each tick, so the round tile flips from 'Resume' to 'View results' once every share confirms instead of showing stale status. - the remaining label distinguishes pending share submissions from pending share confirmations. --- lib/store.dart | 32 ++++++++++++++++++++++++++++---- rust/src/api/voting.rs | 15 +++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/store.dart b/lib/store.dart index 6a0b39ead..15d46be97 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1825,9 +1825,15 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { final session = await ref.read(votingSessionProvider(roundId).future); final pending = session.plan?.nextSteps ?? const <VotingNextStep>[]; if (pending.isEmpty) return "All steps already confirmed"; - const shareKinds = {"submit_shares", "confirm_share"}; - final allShares = pending.every((s) => shareKinds.contains(s.kind)); - return allShares ? "Waiting for the share window" : "Waiting for the next step"; + const shareSubmitKinds = {"submit_shares"}; + const shareConfirmKinds = {"confirm_share"}; + if (pending.every((s) => shareSubmitKinds.contains(s.kind))) { + return "Waiting for the share window"; + } + if (pending.every((s) => shareConfirmKinds.contains(s.kind))) { + return "Waiting for share confirmations"; + } + return "Waiting for the next step"; } /// Resolves the round's ceremony start / vote end from the chain round @@ -2252,7 +2258,22 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { // old unconfirmed-row pairing could never start (mirrors vizor's // commitment-driven share submission). final payloads = await votingSharePayloads(roundId: roundId, c: c); - if (payloads.isEmpty) return false; + if (payloads.isEmpty) { + // All shares already recorded — a resume must not re-send them, but + // the tracker still needs to run to poll the helpers for + // confirmations. + final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); + if (unconfirmed.isNotEmpty) { + _scheduleShareTracking( + delaySeconds: 60, + ceremonyStart: ceremonyStart, + voteEnd: voteEndValue, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + } + return false; + } final plans = await votingSharePlans( shareCount: payloads.length, serverUrls: shareServerUrls, @@ -2427,5 +2448,8 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { singleShare: singleShare, ); } + // Reflect the confirmations in the plan so the round tile and status + // screens update ("Resume" -> "View results" once every share confirms). + await ref.read(votingSessionProvider(roundId).notifier).refresh(); } } diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 03745d72a..974cd23bf 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -1078,6 +1078,12 @@ pub async fn voting_share_payloads( let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; let snapshot = zcash_voting::recovery::round_snapshot(&db, &round_id).await?; + let recorded: std::collections::BTreeSet<(u32, u32, u32)> = db + .share_phases(&round_id) + .await? + .into_iter() + .map(|(b, p, s, _)| (b, p, s)) + .collect(); let mut payloads = Vec::new(); for vote in snapshot.votes { if vote.phase != zcash_voting::phases::VotePhase::Confirmed { @@ -1090,6 +1096,15 @@ pub async fn voting_share_payloads( continue; }; for payload in zcash_voting::share::recover_payloads(&bundle)? { + // Skip shares already recorded — a resume must not re-send them + // (the tracking loop polls the helpers for their confirmations). + if recorded.contains(&( + vote.bundle_index, + vote.proposal_id, + payload.enc_share.share_index, + )) { + continue; + } payloads.push(VotingShareSubmissionPayload { bundle_index: vote.bundle_index, proposal_id: vote.proposal_id, From 8404323d6bd23bf18f0191827f2cc743bdf391e3 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 17 Aug 2026 22:42:41 +0800 Subject: [PATCH 099/189] feat: gate voting round actions on chain status; zero tally for voteless closed rounds Round tiles now derive their affordance from the chain round status plus the resume plan: tallying/closed rounds show "View results" (a tally exists), active rounds with pending recovery (incl. unconfirmed helper shares) show "Resume" to the status page, active rounds with the wallet done show "Review" to the vote receipt, and the "Open rounds" section only offers Join for rounds the chain reports as active. The results page renders a closed round with no recorded votes as a zero-filled ballot instead of an empty screen. --- lib/pages/voting_polls.dart | 92 +++++++++++++++---- lib/pages/voting_results.dart | 166 ++++++++++++++++++---------------- lib/store.dart | 40 ++++++++ lib/store.g.dart | 118 +++++++++++++++++++++++- 4 files changed, 321 insertions(+), 95 deletions(-) diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index 9cc142c6a..ac527b076 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -11,9 +11,17 @@ import 'package:zkool/utils.dart'; import 'package:zkool/widgets/error_display.dart'; /// Round list for shielded voting (ZIP 262). Each row derives its action -/// label from the fork's resume plan (`primary_action`), so a restart shows -/// the correct "Resume"/"Start"/"View results" affordance without any Dart -/// session state. +/// label from the fork's resume plan (`primary_action`) plus the chain round +/// status, so a restart shows the correct affordance without any Dart session +/// state: +/// +/// - chain tallying/closed → "View results" (a tally exists). +/// - chain active, plan has recovery work (incl. shares sent but unconfirmed) +/// → "Resume" → status page, which re-arms share tracking. +/// - chain active, wallet done → "Review" → vote receipt (no tally yet). +/// - otherwise → "Start voting". +/// +/// An unresolved chain status falls back to the plan-only rule. class VotingPollsPage extends ConsumerStatefulWidget { const VotingPollsPage({super.key}); @@ -91,16 +99,26 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { data: (list) { final configRounds = config.value?.rounds ?? const <VotingConfigRound>[]; final localIds = list.map((r) => r.roundId).toSet(); + final chainUrl = (config.value != null && + config.value!.voteServers.isNotEmpty) + ? config.value!.voteServers.first.url + : ""; + // Only rounds the chain reports as active are joinable: a closed + // or tallying round has no open voting window, so it is not + // offered. An unresolved status (fetch in flight or failed) keeps + // the round visible rather than hiding it. final joinable = configRounds .where((r) => !localIds.contains(r.roundId)) + .where((r) { + final status = ref + .watch(votingRoundStatusProvider(r.roundId, chainUrl)) + .value; + return status == null || status == "active"; + }) .toList(); if (list.isEmpty && joinable.isEmpty) { return const Center(child: Text("No voting rounds")); } - final chainUrl = (config.value != null && - config.value!.voteServers.isNotEmpty) - ? config.value!.voteServers.first.url - : ""; return RefreshIndicator( onRefresh: () async => ref.invalidate(votingRoundListProvider), @@ -150,12 +168,15 @@ class _RoundTile extends ConsumerWidget { const _RoundTile({required this.round, required this.chainUrl}); - String _actionLabel(String primaryAction) { + String _actionLabel(String primaryAction, {bool pendingRecovery = false}) { switch (primaryAction) { case "delegate" || "vote" || "submit_shares": return "Resume"; case "done": - return "View results"; + // "done" with recovery steps still pending (e.g. helper shares sent + // but not confirmed) is not finished — keep "Resume" so the status + // page, which re-arms share tracking, stays reachable. + return pendingRecovery ? "Resume" : "View results"; default: return "Start voting"; } @@ -187,8 +208,27 @@ class _RoundTile extends ConsumerWidget { ), ), data: (state) { - final action = state.plan?.primaryAction ?? "idle"; - final label = _actionLabel(action); + final plan = state.plan; + final action = plan?.primaryAction ?? "idle"; + final pending = plan?.pendingRecovery ?? false; + // The chain round status decides whether results exist: an active + // round has no published tally, so the tile must not offer + // "View results" even when the wallet's part is done — the plan only + // picks between "Resume" (work pending) and "Review" (done). An + // unresolved chain status (fetch failed / no chain URL) falls back + // to the plan-only rule. + final chainStatus = ref + .watch(votingRoundStatusProvider(round.roundId, chainUrl)) + .value; + final chainDone = chainStatus == "tallying" || chainStatus == "closed"; + final planDone = action == "done" && !pending; + final done = chainDone || (chainStatus == null && planDone); + final review = action == "done" && !done && chainStatus != null; + final label = done + ? "View results" + : review + ? "Review" + : _actionLabel(action, pendingRecovery: pending); return ListTile( title: Text(roundTitle), subtitle: Text( @@ -196,10 +236,17 @@ class _RoundTile extends ConsumerWidget { "${round.bundleCount} bundle${round.bundleCount == 1 ? "" : "s"}", ), trailing: FilledButton.tonal( - onPressed: () => _openStatus(context, ref, action), + onPressed: () => _openStatus( + context, + ref, + action, + done: done, + review: review, + roundName: roundTitle, + ), child: Text(label), ), - selected: action != "idle" && action != "done", + selected: pending && !done, selectedTileColor: cs.primaryContainer.withValues(alpha: 0.3), ); }, @@ -209,8 +256,11 @@ class _RoundTile extends ConsumerWidget { Future<void> _openStatus( BuildContext context, WidgetRef ref, - String action, - ) async { + String action, { + required bool done, + required bool review, + String? roundName, + }) async { final c = coinContext.coin; final configValue = ref.read(votingConfigProvider).value; final chainUrl = (configValue != null && configValue.voteServers.isNotEmpty) @@ -225,7 +275,7 @@ class _RoundTile extends ConsumerWidget { return; } if (!context.mounted) return; - if (action == "done") { + if (done) { await GoRouter.of(context).push("/voting/results", extra: { "roundId": round.roundId, "chainUrl": chainUrl, @@ -240,6 +290,16 @@ class _RoundTile extends ConsumerWidget { }); return; } + if (review) { + // Wallet done but the round is still open on the chain: show the + // vote receipt, not the (not-yet-published) tally. + await GoRouter.of(context).push("/voting/confirmation", extra: { + "roundId": round.roundId, + "roundName": roundName, + "chainUrl": chainUrl, + }); + return; + } final settings = await ref.read(appSettingsProvider.future); await GoRouter.of(context).push("/voting/status", extra: { "roundId": round.roundId, diff --git a/lib/pages/voting_results.dart b/lib/pages/voting_results.dart index 1029fdc7f..474f1ee41 100644 --- a/lib/pages/voting_results.dart +++ b/lib/pages/voting_results.dart @@ -29,6 +29,7 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { Timer? _pollTimer; String? _error; bool _tallying = false; + bool _zeroFilled = false; Map<int, Map<int, num>> _tallies = {}; // proposal id -> option id -> amount @override @@ -47,11 +48,7 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { try { final c = coinContext.coin; final session = await ref.read(votingSessionProvider(widget.roundId).future); - final intents = session.intents - .map((i) => i.proposalId) - .toSet() - .toList() - ..sort(); + final intents = session.intents.map((i) => i.proposalId).toSet().toList()..sort(); final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); if (drafts != null && drafts.isNotEmpty) { for (final d in jsonDecode(drafts) as List<dynamic>) { @@ -76,10 +73,21 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { ); } final body = jsonDecode(res.body) as Map<String, dynamic>; - final status = ((body['status'] ?? body['phase'] ?? "") as String) - .toLowerCase(); + final status = ((body['status'] ?? body['phase'] ?? "") as String).toLowerCase(); _tallying = status == "2" || status == "tallying" || status == "pending"; _tallies = _parseTally(body, intents); + if (_tallies.isEmpty) { + // A closed round with no recorded votes still shows its ballot at + // zero rather than an empty screen. + final roundStatus = await ref.read(votingRoundStatusProvider(widget.roundId, widget.chainUrl).future); + if (roundStatus == "closed") { + final proposals = await ref.read(votingRoundProposalsProvider(widget.roundId, widget.chainUrl).future); + _zeroFilled = true; + _tallies = { + for (final p in proposals) p.id: {for (final o in p.optionLabels.keys) o: 0}, + }; + } + } if (mounted) setState(() {}); if (_tallying) _schedulePoll(); } on AnyhowException catch (e) { @@ -107,9 +115,7 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { ? v.toInt() : int.tryParse(v?.toString() ?? ""); - num? toNum(Object? v) => v is num - ? v - : num.tryParse(v?.toString() ?? ""); + num? toNum(Object? v) => v is num ? v : num.tryParse(v?.toString() ?? ""); const decisionKeys = [ "vote_decision", @@ -203,14 +209,10 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { votingRoundProposalsProvider(widget.roundId, widget.chainUrl), ); final proposals = { - for (final p in (proposalsAsync.value ?? const <VotingProposalInfo>[])) - p.id: p, + for (final p in (proposalsAsync.value ?? const <VotingProposalInfo>[])) p.id: p, }; - final roundTitle = (ref - .watch(votingRoundTitleProvider(widget.roundId, widget.chainUrl)) - .value ?? - widget.roundId); + final roundTitle = (ref.watch(votingRoundTitleProvider(widget.roundId, widget.chainUrl)).value ?? widget.roundId); return Scaffold( appBar: AppBar(title: Text(roundTitle)), @@ -219,73 +221,81 @@ class VotingResultsPageState extends ConsumerState<VotingResultsPage> { : _tallies.isEmpty ? Center( child: Text( - _tallying - ? "Results pending..." - : "No tally data for this round", + _tallying ? "Results pending..." : "No tally data for this round", ), ) - : ListView.builder( - itemCount: _tallies.length, - itemBuilder: (context, i) { - final pid = _tallies.keys.elementAt(i); - final tally = _tallies[pid]!; - final total = tally.values.fold<num>(0, (a, b) => a + b); - final winner = tally.entries.reduce( - (a, b) => a.value >= b.value ? a : b, - ); - final proposal = proposals[pid]; - return Card( - child: Padding( + : Column( + children: [ + if (_zeroFilled) + Padding( padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text(proposal?.title ?? "Proposal $pid", - style: Theme.of(context).textTheme.titleMedium), - const SizedBox(height: 8), - ...tally.entries.map((e) { - final fraction = total == 0 - ? 0.0 - : e.value / total; - final winning = e.key == winner.key; - return Padding( - padding: const EdgeInsets.symmetric(vertical: 2), - child: Row( - children: [ - SizedBox( - width: 80, - child: Text( - proposal?.optionLabels[e.key] ?? - "Option ${e.key}", - style: TextStyle( - fontWeight: winning - ? FontWeight.bold - : FontWeight.normal, - ), - ), - ), - Expanded( - child: LinearProgressIndicator( - value: fraction.clamp(0.0, 1.0), - minHeight: 8, - ), - ), - SizedBox( - width: 90, - child: Text( - "${(fraction * 100).toStringAsFixed(1)}%", - textAlign: TextAlign.end, - ), - ), - ], - ), - ); - }), - ], + child: Text( + "No votes were recorded for this round", + style: TextStyle( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), - ); - }, + Expanded( + child: ListView.builder( + itemCount: _tallies.length, + itemBuilder: (context, i) { + final pid = _tallies.keys.elementAt(i); + final tally = _tallies[pid]!; + final total = tally.values.fold<num>(0, (a, b) => a + b); + final winner = tally.entries.reduce( + (a, b) => a.value >= b.value ? a : b, + ); + final proposal = proposals[pid]; + return Card( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(proposal?.title ?? "Proposal $pid", style: Theme.of(context).textTheme.titleMedium), + const SizedBox(height: 8), + ...tally.entries.map((e) { + final fraction = total == 0 ? 0.0 : e.value / total; + final winning = e.key == winner.key; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + children: [ + SizedBox( + width: 80, + child: Text( + proposal?.optionLabels[e.key] ?? "Option ${e.key}", + style: TextStyle( + fontWeight: winning ? FontWeight.bold : FontWeight.normal, + ), + ), + ), + Expanded( + child: LinearProgressIndicator( + value: fraction.clamp(0.0, 1.0), + minHeight: 8, + ), + ), + SizedBox( + width: 90, + child: Text( + "${(fraction * 100).toStringAsFixed(1)}%", + textAlign: TextAlign.end, + ), + ), + ], + ), + ); + }), + ], + ), + ), + ); + }, + ), + ), + ], ), ); } diff --git a/lib/store.dart b/lib/store.dart index 15d46be97..a3d6a56e5 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1389,6 +1389,46 @@ Future<String> votingRoundTitle(Ref ref, String roundId, String chainUrl) async return roundId; } +/// Normalized chain round status ("active" / "tallying" / "closed") from the +/// vote chain round status, or null when unresolved (non-2xx or absent). +/// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string +/// forms. Only "tallying"/"closed" rounds have a published tally. +@riverpod +Future<String?> votingRoundStatus(Ref ref, String roundId, String chainUrl) async { + final c = coinContext.coin; + final res = await votechainRoundStatus( + baseUrl: chainUrl, + roundId: roundId, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) return null; + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final status = round['status']; + if (status is int) { + return switch (status) { + 2 => "tallying", + 3 => "closed", + _ => "active", + }; + } + if (status is String) { + final s = status.trim().toLowerCase(); + if (s == '2' || s.contains('tally') || s == 'pending') return "tallying"; + if (s == '3' || + s.contains('closed') || + s.contains('complete') || + s.contains('done') || + s.contains('ended') || + s.contains('final') || + s.contains('result')) { + return "closed"; + } + return "active"; + } + return null; +} + /// One round proposal with its option labels, from the vote chain round /// status — used to render human-readable ballot evidence. class VotingProposalInfo { diff --git a/lib/store.g.dart b/lib/store.g.dart index e31b93c4b..75fe121cd 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1674,6 +1674,122 @@ final class VotingRoundTitleFamily extends $Family String toString() => r'votingRoundTitleProvider'; } +/// Normalized chain round status ("active" / "tallying" / "closed") from the +/// vote chain round status, or null when unresolved (non-2xx or absent). +/// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string +/// forms. Only "tallying"/"closed" rounds have a published tally. + +@ProviderFor(votingRoundStatus) +const votingRoundStatusProvider = VotingRoundStatusFamily._(); + +/// Normalized chain round status ("active" / "tallying" / "closed") from the +/// vote chain round status, or null when unresolved (non-2xx or absent). +/// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string +/// forms. Only "tallying"/"closed" rounds have a published tally. + +final class VotingRoundStatusProvider + extends $FunctionalProvider<AsyncValue<String?>, String?, FutureOr<String?>> + with $FutureModifier<String?>, $FutureProvider<String?> { + /// Normalized chain round status ("active" / "tallying" / "closed") from the + /// vote chain round status, or null when unresolved (non-2xx or absent). + /// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string + /// forms. Only "tallying"/"closed" rounds have a published tally. + const VotingRoundStatusProvider._( + {required VotingRoundStatusFamily super.from, + required ( + String, + String, + ) + super.argument}) + : super( + retry: null, + name: r'votingRoundStatusProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingRoundStatusHash(); + + @override + String toString() { + return r'votingRoundStatusProvider' + '' + '$argument'; + } + + @$internal + @override + $FutureProviderElement<String?> $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr<String?> create(Ref ref) { + final argument = this.argument as ( + String, + String, + ); + return votingRoundStatus( + ref, + argument.$1, + argument.$2, + ); + } + + @override + bool operator ==(Object other) { + return other is VotingRoundStatusProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$votingRoundStatusHash() => r'4c74a550b6b3e70e3b66eccd55b4dc5ce240dac0'; + +/// Normalized chain round status ("active" / "tallying" / "closed") from the +/// vote chain round status, or null when unresolved (non-2xx or absent). +/// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string +/// forms. Only "tallying"/"closed" rounds have a published tally. + +final class VotingRoundStatusFamily extends $Family + with + $FunctionalFamilyOverride< + FutureOr<String?>, + ( + String, + String, + )> { + const VotingRoundStatusFamily._() + : super( + retry: null, + name: r'votingRoundStatusProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// Normalized chain round status ("active" / "tallying" / "closed") from the + /// vote chain round status, or null when unresolved (non-2xx or absent). + /// Mirrors vizor's `votingPollListStatus`: numeric 1/2/3 plus lenient string + /// forms. Only "tallying"/"closed" rounds have a published tally. + + VotingRoundStatusProvider call( + String roundId, + String chainUrl, + ) => + VotingRoundStatusProvider._(argument: ( + roundId, + chainUrl, + ), from: this); + + @override + String toString() => r'votingRoundStatusProvider'; +} + /// Parsed proposals (id, title, option id → label) for a round, from the /// chain round status. Empty when the fetch fails. @@ -1971,7 +2087,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'eeef388d321875ba8c2035e67ba5ad5ae7e7bfa7'; + r'84d1b907680edbebd5282f81e43d2d3590b991fb'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → From 3fdeea0a161776e275545f183cea12e416dbba80 Mon Sep 17 00:00:00 2001 From: bu5hm4nn <bu5hm4nn@users.noreply.github.com> Date: Tue, 18 Aug 2026 01:07:29 +0200 Subject: [PATCH 100/189] fix(ledger): transparent-only signing + NU6.3 v5 workaround for hardware wallets (#1208) * fix(ledger): skip Sapling FVK fetch for transparent-only transactions sign_transaction unconditionally fetched the Sapling full viewing key from sapling_accounts via fetch_one. Transparent-only accounts (e.g. BIP-44 Ledger accounts) have no sapling_accounts row, so this returned RowNotFound and aborted signing before the Ledger device was ever contacted, surfacing as an opaque "no rows returned" error. The FVK and derived OVK are only used inside the Sapling spend/output loops, which only iterate when the PCZT has Sapling components. Fetch the key lazily (only when stin > 0 || stout > 0) as an Option, and unwrap by reference at each use site. SpendValidatingKey is not Copy, so the proof-generation block uses ak.clone(). * fix(ledger): skip Sapling anchor fetch for transparent-only transactions After proving, sign_transaction unconditionally called pczt.sapling().anchor().expect("a Sapling bundle with spends must have an anchor"). A transparent-only transaction has no Sapling bundle, so anchor() returns None and the expect panicked: thread 'tokio-rt-worker' panicked at rust/src/ledger/builder.rs:494: a Sapling bundle with spends must have an anchor The anchor is only read inside the Sapling spends serialization loop, which never iterates for a transparent-only PCZT. Fetch it lazily (only when stin > 0) as an Option and unwrap by reference inside the loop. * fix(ledger): force v5 tx for hardware signing on NU6.3 NU6.3 (Ironwood) is active, so the Builder produces v6 transactions. Hardware wallets using the Zondax "Zcash Shielded" Ledger app can only sign v5 (ZIP-244) transactions; the app predates NU6.3 and computes a pre-NU6 sighash for a v6 tx, so the PCZT signer rejects the device signature with TransparentSign(InvalidExternalSignature). Force the Builder to emit a v5 tx for hardware accounts (hw != 0) via propose_version(TxVersion::V5), while keeping consensus_branch_id as BranchId::for_height (Nu6_3 on the current network). V5 is valid in Nu6_3 per TxVersion::valid_in_branch, and a v5 tx carrying the current Nu6_3 branch id is consensus-valid, so the tx is both signable by the device and acceptable to the network. Software accounts are unaffected and still build v6. This is expected to remain viable for the foreseeable future: the only planned transaction-version phase-out is ZIP 2003 (Draft, proposed for NU7), which disallows v4 (Sprout) transactions and explicitly keeps v5 valid. NU7 is not yet scheduled (activation height TBD), and no ZIP proposes removing v5. The workaround depends on the Zondax Ledger app remaining installed (it is unmaintained but functional); the proper long-term fix is migrating the Ledger signer to the LedgerHQ PCZT-v2 app, which supports v6/Ironwood. --------- Co-authored-by: hhanh00 <hanh425@gmail.com> --- rust/src/ledger/builder.rs | 58 +++++++++++++++++++++++++++++--------- rust/src/pay/plan.rs | 12 ++++++++ 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/rust/src/ledger/builder.rs b/rust/src/ledger/builder.rs index 56ef9c37d..e6071a0eb 100644 --- a/rust/src/ledger/builder.rs +++ b/rust/src/ledger/builder.rs @@ -68,14 +68,6 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( let coin_type = network.coin_type(); let aindex = get_account_aindex(&mut *connection, account).await?; - let (xvk,): (Vec<u8>,) = - sqlx::query_as("SELECT xvk FROM sapling_accounts WHERE account = ?1") - .bind(account) - .fetch_one(&mut *connection) - .await - .anyhow()?; - let fvk = FullViewingKey::read(&*xvk)?; - let ovk = fvk.ovk; let pczt = Pczt::parse(&package.pczt).expect("cannot parse PCZT"); @@ -94,6 +86,25 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( return Err(LedgerError::TooComplex); } + // The Sapling full viewing key is only needed when the transaction + // actually contains Sapling spends/outputs. Transparent-only accounts + // (e.g. BIP-44 Ledger accounts) have no `sapling_accounts` row, so + // fetching it unconditionally would fail with `RowNotFound` and abort + // signing before the Ledger is ever contacted. The values derived from + // it (`fvk`, `ovk`) are only referenced inside the Sapling loops below, + // which only iterate when Sapling components are present. + let fvk = if stin > 0 || stout > 0 { + let (xvk,): (Vec<u8>,) = + sqlx::query_as("SELECT xvk FROM sapling_accounts WHERE account = ?1") + .bind(account) + .fetch_one(&mut *connection) + .await + .anyhow()?; + Some(FullViewingKey::read(&*xvk)?) + } else { + None + }; + // Signing a tx with the Ledger involves several steps // Step 1. Send a InitTx instruction with inputs/outputs let _ = sink.add(SigningEvent::Progress("Init Tx".to_string())); @@ -162,6 +173,7 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( .await.anyhow()?; let diversifier = Diversifier(tiu!(diversifier)); + let fvk = fvk.as_ref().expect("fvk present for Sapling spends"); let recipient = fvk.vk.to_payment_address(diversifier).unwrap(); let mut data = vec![]; data.write_u32::<LE>(aindex)?; @@ -173,6 +185,8 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( let mut memos = vec![]; for sout in pczt.sapling().outputs().iter() { + let fvk = fvk.as_ref().expect("fvk present for Sapling outputs"); + let ovk = fvk.ovk; let recipient = sout.recipient().unwrap(); // Decrypt the memo so that we can reencrypt it with the // randomness @@ -292,6 +306,7 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( let rcm: [u8; 32] = tiu!(rcm); let rcv: [u8; 32] = tiu!(rcv); let diversifier = Diversifier(tiu!(diversifier)); + let fvk = fvk.as_ref().expect("fvk present for Sapling spends"); let recipient = fvk.vk.to_payment_address(diversifier).unwrap(); let rseed = Rseed::BeforeZip212(Fr::from_bytes(&rcm).unwrap()); let note = Note::from_parts(recipient, NoteValue::from_raw(value), rseed); @@ -317,6 +332,8 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( data: vec![], }; for (out, memo) in pczt.sapling().outputs().iter().zip(memos.iter()) { + let fvk = fvk.as_ref().expect("fvk present for Sapling outputs"); + let ovk = fvk.ovk; let _ = sink.add(SigningEvent::Progress( "Extracting output randomness".to_string(), )); @@ -414,8 +431,9 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( let pczt = if !pczt.sapling().spends().is_empty() || !pczt.sapling().outputs().is_empty() { let updater = Updater::new(pczt); + let fvk = fvk.as_ref().expect("fvk present for Sapling proofs"); let nsk = Fr::from_bytes(&nsk).unwrap(); - let pgk = ProofGenerationKey { ak: fvk.vk.ak, nsk }; + let pgk = ProofGenerationKey { ak: fvk.vk.ak.clone(), nsk }; let updater = updater .update_sapling_with(|mut u| { @@ -470,10 +488,19 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( buffers.push(data); } // Read zkproof from sapling-crypto types (pczt types don't expose it) - let anchor = pczt - .sapling() - .anchor() - .expect("a Sapling bundle with spends must have an anchor"); + // The Sapling anchor is only present when there are Sapling spends. A + // transparent-only transaction has no Sapling bundle, so `anchor()` is + // `None`; only fetch it when there are spends to serialize. + let anchor = if stin > 0 { + Some( + pczt + .sapling() + .anchor() + .expect("a Sapling bundle with spends must have an anchor"), + ) + } else { + None + }; // Use update_sapling_with to access sapling-crypto Spend/Output which have full // getters including zkproof() let mut proof_bufs: Vec<Vec<u8>> = vec![]; @@ -485,7 +512,10 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( for sin in bundle.spends() { let mut data = vec![]; data.write_all(&sin.cv().to_bytes()).unwrap(); - data.write_all(&anchor).unwrap(); + data.write_all( + anchor.as_ref().expect("anchor present for Sapling spends"), + ) + .unwrap(); data.write_all(sin.nullifier().as_ref()).unwrap(); let rk_bytes: [u8; 32] = VerificationKeyBytes::from(*sin.rk()).into(); data.write_all(&rk_bytes).unwrap(); diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 9302b174e..dd967084d 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -31,6 +31,7 @@ use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; use zcash_note_encryption::Domain; use zcash_primitives::transaction::{ builder::{BuildConfig, Builder, BundlePadding}, + TxVersion, fees::zip317::FeeRule, }; use zcash_proofs::prover::LocalTxProver; @@ -697,6 +698,17 @@ pub async fn plan_transaction( }; let mut builder = Builder::new(network, BlockHeight::from_u32(target_height), build_config); + // Hardware (Ledger) wallets only support v5 (ZIP-244) transaction signing. + // The Zondax "Zcash Shielded" app predates NU6.3 and cannot sign v6/Ironwood + // transactions, so force a v5 tx while keeping consensus_branch_id = Nu6_3 + // (V5 is valid in Nu6_3 per TxVersion::valid_in_branch). A v5 tx carrying the + // current Nu6_3 branch id is valid on the network. + if hw != 0 { + builder + .propose_version::<()>(TxVersion::V5) + .map_err(|e| anyhow!("failed to force v5 for hardware signing: {e:?}"))?; + } + let es = es.to_auth_path(&SaplingHasher::default()); let eo = eo.to_auth_path(&OrchardHasher::default()); let ei = ei.to_auth_path(&OrchardHasher::default()); From f46f65061eed1762d9814dd96e27f90aa963f3f9 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 08:13:25 +0800 Subject: [PATCH 101/189] =?UTF-8?q?fix:=20support=20flutter=203.47=20(intl?= =?UTF-8?q?=200.20.3);=20fixed=206.2.0=20rename=20scale=E2=86=92decimalDig?= =?UTF-8?q?its?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flutter_localizations in Flutter 3.47 requires intl ^0.20.3. fixed <6.2.0 pins intl <=0.20.2, so pub resolution failed entirely. Bump fixed to ^6.2.0 (first version supporting intl 0.20.3) and update the four call sites that used the renamed scale: parameter (decimalDigits: has identical semantics). --- analysis_options.yaml | 9 +++++++++ lib/utils.dart | 8 ++++---- pubspec.lock | 32 ++++++++++++++++---------------- pubspec.yaml | 2 +- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 3f066968d..8900b6e5c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -30,3 +30,12 @@ linter: formatter: page_width: 160 +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** diff --git a/lib/utils.dart b/lib/utils.dart index 6c092d53c..1a4ad4bf8 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -66,13 +66,13 @@ String doubleToString(double v, {required int decimals}) { } String zatToString(BigInt zat) { - final z = Fixed.fromBigInt(zat, scale: 8); + final z = Fixed.fromBigInt(zat, decimalDigits: 8); final s = zatFormatter.format(z.toDecimal()); return s; } String zatToShortString(BigInt zat) { - final z = Fixed.fromBigInt(zat, scale: 8); + final z = Fixed.fromBigInt(zat, decimalDigits: 8); final s = zatShortFormatter.format(z.toDecimal()); return s; } @@ -114,7 +114,7 @@ Widget zatToText(BigInt zat, {String prefix = "", TextStyle? style, Function()? Fixed stringToDecimal(String s, {int? scale}) { try { - return Fixed.parse(s, scale: scale, invertSeparator: invertSeparator); + return Fixed.parse(s, decimalDigits: scale, invertSeparator: invertSeparator); } on RangeError { throw FormatException('Invalid decimal: $s'); } @@ -122,7 +122,7 @@ Fixed stringToDecimal(String s, {int? scale}) { BigInt stringToZat(String s) { try { - final z = Fixed.parse(s, scale: 8, invertSeparator: invertSeparator); + final z = Fixed.parse(s, decimalDigits: 8, invertSeparator: invertSeparator); return z.minorUnits; } on RangeError { throw FormatException('Invalid amount: $s'); diff --git a/pubspec.lock b/pubspec.lock index c74e0035a..5a7fbd589 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -429,10 +429,10 @@ packages: dependency: "direct main" description: name: fixed - sha256: "9b67adeef364271501738a7ab452f45f3207b69a7d8d5692eaa22d038757b035" + sha256: d1acef34c8ef195b50228e3b7ec80c24f843ab1bfb1636041b922a62e10123aa url: "https://pub.dev" source: hosted - version: "5.3.4" + version: "6.2.0" fixnum: dependency: transitive description: @@ -882,10 +882,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867" url: "https://pub.dev" source: hosted - version: "0.20.2" + version: "0.20.3" io: dependency: transitive description: @@ -1002,10 +1002,10 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.20" material_color_utilities: dependency: transitive description: @@ -1026,10 +1026,10 @@ packages: dependency: transitive description: name: meta - sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" mime: dependency: transitive description: @@ -1486,26 +1486,26 @@ packages: dependency: transitive description: name: test - sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20" + sha256: ca578dc12bb8b2f40b67b7d3bd2fac4f31c01a6ff7130a14e2597b919934507f url: "https://pub.dev" source: hosted - version: "1.31.0" + version: "1.31.1" test_api: dependency: transitive description: name: test_api - sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.12" test_core: dependency: transitive description: name: test_core - sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34" + sha256: d2e98ec12998368dc59ddd47ab709f2cd55acd6b66dc7db764455a44082f4bc5 url: "https://pub.dev" source: hosted - version: "0.6.17" + version: "0.6.18" toastification: dependency: "direct main" description: @@ -1630,10 +1630,10 @@ packages: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.2" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4bc532416..0be60410f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,7 +44,7 @@ dependencies: flutter_svg: ^2.0.10+1 - fixed: ^5.3.3 + fixed: ^6.2.0 decimal: ^3.2.1 intl: ^0.20.2 From c791f7f80e8ca1b5c3647dcc6d7120d4ab5e3b7e Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 08:15:42 +0800 Subject: [PATCH 102/189] fix: pass one connection through voting DB reads; stop pool stalls on voting page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every voting read call acquired get_connection() for the wallet-id lookup and then let VotingDb acquire again internally for migrations and queries — 2 connections held per call, so the 4 concurrent per-tile session loads oversubscribed the 5-connection pool and self-stalled: holders blocked on their 2nd acquire wait out the 30s acquire timeout, leaving the round tiles spinning for minutes. zcash_voting (rev faa06af4) now threads a caller-provided &mut SqliteConnection through the read path (rounds, ballot_intents, resume_plan, round_snapshot and all their helpers, including the previously-missed delegation_statuses, recovered_*_work_from_steps, vote_has_recovery_bundle, get_commitment_bundle, get_unconfirmed_delegations, share::{list,unconfirmed}). zkool's wrappers acquire once and pass it down — one pool connection per FRB call (verified with a standalone probe: full 4-round session load in ~13ms vs 30s timeouts). --- Cargo.lock | 6 ++--- rust/Cargo.toml | 2 +- rust/src/api/voting.rs | 54 +++++++++++++++++++++--------------------- rust/src/voting.rs | 39 ++++++++++++++++++++---------- 4 files changed, 58 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d6f9d026..aca9a4d79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13210,7 +13210,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" dependencies = [ "anyhow", "ff", @@ -13226,7 +13226,7 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" dependencies = [ "base64 0.22.1", "ff", @@ -14415,7 +14415,7 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=aa5338f112a47626cd0fa79ca25cdf544c918b28#aa5338f112a47626cd0fa79ca25cdf544c918b28" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d905b4284..5080d5e82 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,7 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } -zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "aa5338f112a47626cd0fa79ca25cdf544c918b28", features = ["zsa-orchard"] } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "faa06af424d284bf98a1a2687b65e6b1bf312ab1", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 974cd23bf..aba881927 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -502,7 +502,7 @@ pub async fn delegation_setup( let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; let setup = prepared.setup(&db, &NoopProgressReporter).await?; Ok(setup.into()) @@ -714,7 +714,7 @@ pub async fn delegation_mark_submitted( let tx_hash = tx_hash.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; db.mark_delegation_submitted(&round_id, bundle_index, &tx_hash) .await?; Ok(()) @@ -731,8 +731,8 @@ pub async fn delegation_tx_hash( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - Ok(db.get_delegation_tx_hash(&round_id, bundle_index).await?) + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + Ok(db.get_delegation_tx_hash(&mut *connection, &round_id, bundle_index).await?) } // --------------------------------------------------------------------------- @@ -760,7 +760,7 @@ pub async fn voting_set_ballot_intent( }; let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; db.set_ballot_intent(&round_id, proposal_id, decision, num_options) .await?; Ok(()) @@ -897,7 +897,7 @@ pub async fn voting_mark_vote_submitted( let tx_hash = tx_hash.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; db.mark_vote_submitted(&round_id, bundle_index, proposal_id, &tx_hash) .await?; Ok(()) @@ -924,7 +924,7 @@ pub async fn voting_share_record( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; zcash_voting::share::record( &db, &round_id, @@ -948,8 +948,8 @@ pub async fn voting_share_unconfirmed( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - Ok(zcash_voting::share::unconfirmed(&db, &round_id) + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + Ok(zcash_voting::share::unconfirmed(&db, &mut *connection, &round_id) .await? .into_iter() .map(Into::into) @@ -969,7 +969,7 @@ pub async fn voting_share_confirm( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; zcash_voting::share::confirm(&db, &round_id, bundle_index, proposal_id, share_index).await?; Ok(()) } @@ -988,7 +988,7 @@ pub async fn voting_share_add_servers( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; zcash_voting::share::add_sent_servers( &db, &round_id, @@ -1044,7 +1044,7 @@ pub async fn voting_sync_tree( let vote_node_url = vote_node_url.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; Ok(zcash_voting::precompute::sync_vote_tree(&db, &round_id, &vote_node_url).await?) } @@ -1076,10 +1076,10 @@ pub async fn voting_share_payloads( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let snapshot = zcash_voting::recovery::round_snapshot(&db, &round_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let snapshot = zcash_voting::recovery::round_snapshot(&db, &mut *connection, &round_id).await?; let recorded: std::collections::BTreeSet<(u32, u32, u32)> = db - .share_phases(&round_id) + .share_phases(&mut *connection, &round_id) .await? .into_iter() .map(|(b, p, s, _)| (b, p, s)) @@ -1181,8 +1181,8 @@ pub async fn voting_share_plan( let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let shares = zcash_voting::share::unconfirmed(&db, &round_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let shares = zcash_voting::share::unconfirmed(&db, &mut *connection, &round_id).await?; let policy = ShareTimingPolicy::default(); let summary = zcash_voting::share_policy::summarize_share_tracking( @@ -2077,8 +2077,8 @@ pub async fn voting_rounds(c: &Coin) -> Result<Vec<VotingRoundInfo>> { let account = c.account; let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let rounds = db.rounds().await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let rounds = db.rounds(&mut *connection).await?; Ok(rounds.into_iter().map(Into::into).collect()) } @@ -2091,8 +2091,8 @@ pub async fn voting_plan(round_id: &str, proposal_ids: Vec<u32>, c: &Coin) -> Re let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let plan = zcash_voting::session::resume_plan(&db, &round_id, &proposal_ids).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let plan = zcash_voting::session::resume_plan(&db, &mut *connection, &round_id, &proposal_ids).await?; Ok(plan.into()) } @@ -2103,8 +2103,8 @@ pub async fn voting_recovery(round_id: &str, c: &Coin) -> Result<VotingRoundReco let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let snapshot = zcash_voting::recovery::round_snapshot(&db, &round_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let snapshot = zcash_voting::recovery::round_snapshot(&db, &mut *connection, &round_id).await?; Ok(snapshot.into()) } @@ -2116,7 +2116,7 @@ pub async fn voting_recovery_clear(round_id: &str, c: &Coin) -> Result<()> { let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; zcash_voting::recovery::clear(&db, &round_id).await?; Ok(()) } @@ -2132,7 +2132,7 @@ pub async fn voting_reset_session_state(round_id: &str, c: &Coin) -> Result<()> let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; zcash_voting::precompute::reset_voting_session_state(&db, &round_id).await?; Ok(()) } @@ -2144,8 +2144,8 @@ pub async fn voting_ballot_intents(round_id: &str, c: &Coin) -> Result<Vec<Votin let round_id = round_id.to_string(); let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let db = voting::open_voting_db(c.get_pool()?, &wallet_id).await?; - let intents = db.ballot_intents(&round_id).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let intents = db.ballot_intents(&mut *connection, &round_id).await?; Ok(intents.into_iter().map(Into::into).collect()) } diff --git a/rust/src/voting.rs b/rust/src/voting.rs index 64f8c7bdb..2baee1583 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -56,8 +56,12 @@ pub fn voting_network(network: &WalletNetwork) -> Result<VotingNetwork> { /// /// Migrations are additive and idempotent; all voting state is scoped to /// `wallet_id` (the hex-encoded ZIP-32 seed fingerprint). -pub async fn open_voting_db(pool: SqlitePool, wallet_id: &str) -> Result<VotingDb> { - let db = VotingDb::from_pool(pool).await?; +pub async fn open_voting_db( + pool: SqlitePool, + conn: &mut SqliteConnection, + wallet_id: &str, +) -> Result<VotingDb> { + let db = VotingDb::from_pool(pool, conn).await?; db.set_wallet_id(wallet_id); Ok(db) } @@ -478,7 +482,8 @@ pub async fn prepare_delegation_bundle( bundle_index: u32, bundle_policy: BundlePolicy, ) -> Result<PreparedDelegationBundle> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; Ok(zcash_voting::delegate::prepare_delegation_bundle_with_inputs( &db, PrepareDelegationBundleWithInputsParams { @@ -568,7 +573,8 @@ pub async fn prove_and_submit_delegation_with_progress( pir_server_url: &str, progress: Arc<dyn DelegationProgressReporter>, ) -> Result<(DelegationSubmission, String)> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let _setup = prepared.setup(&db, progress.as_ref()).await?; let request = prepared.signing_request(&db).await?; @@ -627,7 +633,8 @@ pub async fn confirm_delegation( tx_hash: &str, events: &[TxEvent], ) -> Result<DelegationConfirmation> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; Ok(confirm_delegation_submission(&db, round_id, bundle_index, tx_hash, events).await?) } @@ -641,7 +648,8 @@ pub async fn confirm_vote( tx_hash: &str, events: &[TxEvent], ) -> Result<VoteConfirmation> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; Ok(confirm_vote_submission(&db, round_id, bundle_index, proposal_id, tx_hash, events).await?) } @@ -655,7 +663,8 @@ pub async fn vote_van_witness( bundle_index: u32, vote_node_url: &str, ) -> Result<VanWitness> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let anchor_height = zcash_voting::prelude::sync_vote_tree(&db, round_id, vote_node_url).await?; Ok(zcash_voting::prelude::van_witness(&db, round_id, bundle_index, anchor_height).await?) } @@ -696,7 +705,8 @@ pub async fn commit_votes_with_progress( hotkey: &VotingHotkey, stages: &dyn VoteCommitStageReporter, ) -> Result<SignedVoteCommitments> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; Ok(zcash_voting::prelude::commit_batch( &db, round_id, @@ -718,7 +728,8 @@ pub async fn vote_payloads( bundle_index: u32, proposal_id: u32, ) -> Result<(VoteSubmission, Vec<SharePayload>)> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; Ok(( committed.submission(&db).await?, @@ -734,7 +745,8 @@ pub async fn vote_wire_json( bundle_index: u32, proposal_id: u32, ) -> Result<String> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; let signed = committed.signed_commitment(&db).await?; Ok(zcash_voting::wire::VoteCommitmentWire::try_from(&signed)?.to_json()?) @@ -752,9 +764,11 @@ pub async fn share_wire_json( vc_tree_position: Option<u64>, submit_at: u64, ) -> Result<String> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let bundle = zcash_voting::recovery::recoverable_commitment_bundle( &db, + &mut conn, round_id, bundle_index, proposal_id, @@ -786,7 +800,8 @@ pub async fn record_vote_execution( vc_tree_position: u64, shares: &[(u32, Vec<String>, u64, bool)], ) -> Result<()> { - let db = open_voting_db(pool, wallet_id).await?; + let mut conn = pool.acquire().await?; + let db = open_voting_db(pool, &mut conn, wallet_id).await?; let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; committed.record_submission(&db, vote_tx_hash).await?; committed.record_vc_position(&db, vc_tree_position).await?; From ca86e2cf6e8393349b270d3a1b0ffebded7f012e Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 08:19:41 +0800 Subject: [PATCH 103/189] feat: ballot page AppBar shows the round title The page already fetches the round title from the chain round status for the submission flow; show it in the AppBar (falling back to the round id) instead of always displaying the raw round id hash. --- lib/pages/voting_proposal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index c4f2f8c91..ae23b9ebc 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -233,7 +233,7 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { ); return Scaffold( - appBar: AppBar(title: Text(widget.roundId)), + appBar: AppBar(title: Text(_roundName ?? widget.roundId)), body: _error != null ? Center(child: Text(_error!)) : _proposals.isEmpty From f056f5024947fbac96bde464139d5fbae79f967c Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 09:51:31 +0800 Subject: [PATCH 104/189] fix: batch-load voting sessions on one pool connection; keep the pool free during delegation - voting_sessions: new FRB that loads every round's plan/recovery/intents in one Rust call holding a single connection (per-round loads needed one connection per round and stalled the 5-slot pool with many rounds). The round list reads sessions from the shared batch provider. - delegation prepare/build/setup/sign: scope the wallet connection around the short DB phases instead of holding it across the lightwalletd fetch, PCZT build, and PIR proving (a later internal acquire queued behind the held connection and timed out at 30s). - get_connection logs slow acquires with pool size/idle counts. - the round list invalidates when a submission job finishes, so a round leaves the Join list and shows its real status without a manual refresh. --- lib/pages/voting_polls.dart | 23 +- lib/src/rust/api/voting.dart | 21 +- lib/src/rust/api/voting.freezed.dart | 407 +++++++++++++++++++++++++++ lib/src/rust/frb_generated.dart | 126 ++++++++- lib/src/rust/frb_generated.io.dart | 22 ++ lib/src/rust/frb_generated.web.dart | 22 ++ lib/store.dart | 27 ++ lib/store.g.dart | 51 +++- rust/src/api/coin.rs | 13 +- rust/src/api/voting.rs | 148 +++++++--- rust/src/frb_generated.rs | 139 ++++++++- rust/src/voting.rs | 12 +- 12 files changed, 935 insertions(+), 76 deletions(-) diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index ac527b076..f8add16f9 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -185,10 +185,12 @@ class _RoundTile extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final cs = Theme.of(context).colorScheme; - final session = ref.watch(votingSessionProvider(round.roundId)); + // All tiles share one batch load (a single pool connection); the tile + // reads its round's session from the shared map. + final sessions = ref.watch(votingSessionsAllProvider); final title = ref.watch(votingRoundTitleProvider(round.roundId, chainUrl)); final roundTitle = title.value ?? round.roundId; - return session.when( + return sessions.when( loading: () => ListTile( title: Text(roundTitle), subtitle: Text("Snapshot height ${round.snapshotHeight}"), @@ -203,11 +205,22 @@ class _RoundTile extends ConsumerWidget { subtitle: Text("Snapshot height ${round.snapshotHeight}"), trailing: IconButton( icon: Icon(Icons.refresh), - onPressed: () => - ref.invalidate(votingSessionProvider(round.roundId)), + onPressed: () => ref.invalidate(votingSessionsAllProvider), ), ), - data: (state) { + data: (map) { + final state = map[round.roundId]; + if (state == null) { + return ListTile( + title: Text(roundTitle), + subtitle: Text("Snapshot height ${round.snapshotHeight}"), + trailing: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(strokeWidth: 2), + ), + ); + } final plan = state.plan; final action = plan?.primaryAction ?? "idle"; final pending = plan?.pendingRecovery ?? false; diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index b528202b9..e6f699391 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -11,7 +11,7 @@ part 'voting.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `config_switch_kind_string`, `fork_network_string`, `from_resolved`, `prepare_bundle`, `to_fork`, `votechain_proxy` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `VotingShareDelivery` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` /// Creates and persists a fresh app-owned voting hotkey (hex stored secret). Future<String> votingHotkeyCreate({required Coin c}) => @@ -512,6 +512,13 @@ Future<List<VotingBallotIntent>> votingBallotIntents( RustLib.instance.api .crateApiVotingVotingBallotIntents(roundId: roundId, c: c); +/// Loads sessions for many rounds in a single Rust call that holds ONE pool +/// connection (the per-round entry points above would need one connection per +/// round and stall the pool once the page has many rounds). +Future<List<VotingRoundSession>> votingSessions( + {required List<String> roundIds, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingSessions(roundIds: roundIds, c: c); + /// Lists rounds from the vote server (`{ "rounds": [...] }`). Future<VotingChainResponse> votechainListRounds( {required String baseUrl, required Coin c}) => @@ -824,6 +831,18 @@ sealed class VotingRoundRecovery with _$VotingRoundRecovery { }) = _VotingRoundRecovery; } +/// One round's full session state: resume plan, recovery snapshot, and +/// ballot intents — loaded together under a single pool connection. +@freezed +sealed class VotingRoundSession with _$VotingRoundSession { + const factory VotingRoundSession({ + required String roundId, + required VotingRoundPlan plan, + required VotingRoundRecovery recovery, + required List<VotingBallotIntent> intents, + }) = _VotingRoundSession; +} + /// Endpoint advertised by a voting service config. @freezed sealed class VotingServiceEndpoint with _$VotingServiceEndpoint { diff --git a/lib/src/rust/api/voting.freezed.dart b/lib/src/rust/api/voting.freezed.dart index 62833a0e5..e37783f8a 100644 --- a/lib/src/rust/api/voting.freezed.dart +++ b/lib/src/rust/api/voting.freezed.dart @@ -8067,6 +8067,413 @@ class __$VotingRoundRecoveryCopyWithImpl<$Res> } } +/// @nodoc +mixin _$VotingRoundSession { + String get roundId; + VotingRoundPlan get plan; + VotingRoundRecovery get recovery; + List<VotingBallotIntent> get intents; + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingRoundSessionCopyWith<VotingRoundSession> get copyWith => + _$VotingRoundSessionCopyWithImpl<VotingRoundSession>( + this as VotingRoundSession, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingRoundSession && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.plan, plan) || other.plan == plan) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && + const DeepCollectionEquality().equals(other.intents, intents)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, plan, recovery, + const DeepCollectionEquality().hash(intents)); + + @override + String toString() { + return 'VotingRoundSession(roundId: $roundId, plan: $plan, recovery: $recovery, intents: $intents)'; + } +} + +/// @nodoc +abstract mixin class $VotingRoundSessionCopyWith<$Res> { + factory $VotingRoundSessionCopyWith( + VotingRoundSession value, $Res Function(VotingRoundSession) _then) = + _$VotingRoundSessionCopyWithImpl; + @useResult + $Res call( + {String roundId, + VotingRoundPlan plan, + VotingRoundRecovery recovery, + List<VotingBallotIntent> intents}); + + $VotingRoundPlanCopyWith<$Res> get plan; + $VotingRoundRecoveryCopyWith<$Res> get recovery; +} + +/// @nodoc +class _$VotingRoundSessionCopyWithImpl<$Res> + implements $VotingRoundSessionCopyWith<$Res> { + _$VotingRoundSessionCopyWithImpl(this._self, this._then); + + final VotingRoundSession _self; + final $Res Function(VotingRoundSession) _then; + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? roundId = null, + Object? plan = null, + Object? recovery = null, + Object? intents = null, + }) { + return _then(_self.copyWith( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + plan: null == plan + ? _self.plan + : plan // ignore: cast_nullable_to_non_nullable + as VotingRoundPlan, + recovery: null == recovery + ? _self.recovery + : recovery // ignore: cast_nullable_to_non_nullable + as VotingRoundRecovery, + intents: null == intents + ? _self.intents + : intents // ignore: cast_nullable_to_non_nullable + as List<VotingBallotIntent>, + )); + } + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundPlanCopyWith<$Res> get plan { + return $VotingRoundPlanCopyWith<$Res>(_self.plan, (value) { + return _then(_self.copyWith(plan: value)); + }); + } + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundRecoveryCopyWith<$Res> get recovery { + return $VotingRoundRecoveryCopyWith<$Res>(_self.recovery, (value) { + return _then(_self.copyWith(recovery: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [VotingRoundSession]. +extension VotingRoundSessionPatterns on VotingRoundSession { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap<TResult extends Object?>( + TResult Function(_VotingRoundSession value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundSession() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map<TResult extends Object?>( + TResult Function(_VotingRoundSession value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundSession(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull<TResult extends Object?>( + TResult? Function(_VotingRoundSession value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundSession() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen<TResult extends Object?>( + TResult Function(String roundId, VotingRoundPlan plan, + VotingRoundRecovery recovery, List<VotingBallotIntent> intents)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingRoundSession() when $default != null: + return $default( + _that.roundId, _that.plan, _that.recovery, _that.intents); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when<TResult extends Object?>( + TResult Function(String roundId, VotingRoundPlan plan, + VotingRoundRecovery recovery, List<VotingBallotIntent> intents) + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundSession(): + return $default( + _that.roundId, _that.plan, _that.recovery, _that.intents); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull<TResult extends Object?>( + TResult? Function(String roundId, VotingRoundPlan plan, + VotingRoundRecovery recovery, List<VotingBallotIntent> intents)? + $default, + ) { + final _that = this; + switch (_that) { + case _VotingRoundSession() when $default != null: + return $default( + _that.roundId, _that.plan, _that.recovery, _that.intents); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingRoundSession implements VotingRoundSession { + const _VotingRoundSession( + {required this.roundId, + required this.plan, + required this.recovery, + required final List<VotingBallotIntent> intents}) + : _intents = intents; + + @override + final String roundId; + @override + final VotingRoundPlan plan; + @override + final VotingRoundRecovery recovery; + final List<VotingBallotIntent> _intents; + @override + List<VotingBallotIntent> get intents { + if (_intents is EqualUnmodifiableListView) return _intents; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_intents); + } + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingRoundSessionCopyWith<_VotingRoundSession> get copyWith => + __$VotingRoundSessionCopyWithImpl<_VotingRoundSession>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingRoundSession && + (identical(other.roundId, roundId) || other.roundId == roundId) && + (identical(other.plan, plan) || other.plan == plan) && + (identical(other.recovery, recovery) || + other.recovery == recovery) && + const DeepCollectionEquality().equals(other._intents, _intents)); + } + + @override + int get hashCode => Object.hash(runtimeType, roundId, plan, recovery, + const DeepCollectionEquality().hash(_intents)); + + @override + String toString() { + return 'VotingRoundSession(roundId: $roundId, plan: $plan, recovery: $recovery, intents: $intents)'; + } +} + +/// @nodoc +abstract mixin class _$VotingRoundSessionCopyWith<$Res> + implements $VotingRoundSessionCopyWith<$Res> { + factory _$VotingRoundSessionCopyWith( + _VotingRoundSession value, $Res Function(_VotingRoundSession) _then) = + __$VotingRoundSessionCopyWithImpl; + @override + @useResult + $Res call( + {String roundId, + VotingRoundPlan plan, + VotingRoundRecovery recovery, + List<VotingBallotIntent> intents}); + + @override + $VotingRoundPlanCopyWith<$Res> get plan; + @override + $VotingRoundRecoveryCopyWith<$Res> get recovery; +} + +/// @nodoc +class __$VotingRoundSessionCopyWithImpl<$Res> + implements _$VotingRoundSessionCopyWith<$Res> { + __$VotingRoundSessionCopyWithImpl(this._self, this._then); + + final _VotingRoundSession _self; + final $Res Function(_VotingRoundSession) _then; + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? roundId = null, + Object? plan = null, + Object? recovery = null, + Object? intents = null, + }) { + return _then(_VotingRoundSession( + roundId: null == roundId + ? _self.roundId + : roundId // ignore: cast_nullable_to_non_nullable + as String, + plan: null == plan + ? _self.plan + : plan // ignore: cast_nullable_to_non_nullable + as VotingRoundPlan, + recovery: null == recovery + ? _self.recovery + : recovery // ignore: cast_nullable_to_non_nullable + as VotingRoundRecovery, + intents: null == intents + ? _self._intents + : intents // ignore: cast_nullable_to_non_nullable + as List<VotingBallotIntent>, + )); + } + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundPlanCopyWith<$Res> get plan { + return $VotingRoundPlanCopyWith<$Res>(_self.plan, (value) { + return _then(_self.copyWith(plan: value)); + }); + } + + /// Create a copy of VotingRoundSession + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $VotingRoundRecoveryCopyWith<$Res> get recovery { + return $VotingRoundRecoveryCopyWith<$Res>(_self.recovery, (value) { + return _then(_self.copyWith(recovery: value)); + }); + } +} + /// @nodoc mixin _$VotingServiceEndpoint { String get url; diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 45ccf458f..938a406e5 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 1724058360; + int get rustContentHash => -1211184662; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -799,6 +799,9 @@ abstract class RustLibApi extends BaseApi { Future<List<VotingRoundInfo>> crateApiVotingVotingRounds({required Coin c}); + Future<List<VotingRoundSession>> crateApiVotingVotingSessions( + {required List<String> roundIds, required Coin c}); + Future<void> crateApiVotingVotingSetBallotIntent( {required String roundId, required int proposalId, @@ -7367,6 +7370,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["c"], ); + @override + Future<List<VotingRoundSession>> crateApiVotingVotingSessions( + {required List<String> roundIds, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_String(roundIds, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 216, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_voting_round_session, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingSessionsConstMeta, + argValues: [roundIds, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingSessionsConstMeta => + const TaskConstMeta( + debugName: "voting_sessions", + argNames: ["roundIds", "c"], + ); + @override Future<void> crateApiVotingVotingSetBallotIntent( {required String roundId, @@ -7386,7 +7418,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 216, port: port_); + funcId: 217, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7431,7 +7463,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 217, port: port_); + funcId: 218, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7474,7 +7506,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 218, port: port_); + funcId: 219, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7503,7 +7535,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + funcId: 220, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_submission_payload, @@ -7543,7 +7575,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + funcId: 221, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7599,7 +7631,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_plan_item, @@ -7655,7 +7687,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7701,7 +7733,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + funcId: 224, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7741,7 +7773,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 224, port: port_); + funcId: 225, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7787,7 +7819,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 225, port: port_); + funcId: 226, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7821,7 +7853,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 226, port: port_); + funcId: 227, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -7855,7 +7887,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 227, port: port_); + funcId: 228, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -8774,6 +8806,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (raw as List<dynamic>).map(dco_decode_voting_round_info).toList(); } + @protected + List<VotingRoundSession> dco_decode_list_voting_round_session(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List<dynamic>).map(dco_decode_voting_round_session).toList(); + } + @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( dynamic raw) { @@ -9965,6 +10003,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingRoundSession dco_decode_voting_round_session(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List<dynamic>; + if (arr.length != 4) + throw Exception('unexpected arr length: expect 4 but see ${arr.length}'); + return VotingRoundSession( + roundId: dco_decode_String(arr[0]), + plan: dco_decode_voting_round_plan(arr[1]), + recovery: dco_decode_voting_round_recovery(arr[2]), + intents: dco_decode_list_voting_ballot_intent(arr[3]), + ); + } + @protected VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -11323,6 +11375,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List<VotingRoundSession> sse_decode_list_voting_round_session( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = <VotingRoundSession>[]; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_voting_round_session(deserializer)); + } + return ans_; + } + @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( SseDeserializer deserializer) { @@ -12683,6 +12748,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { unconfirmedShareDelegations: var_unconfirmedShareDelegations); } + @protected + VotingRoundSession sse_decode_voting_round_session( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_roundId = sse_decode_String(deserializer); + var var_plan = sse_decode_voting_round_plan(deserializer); + var var_recovery = sse_decode_voting_round_recovery(deserializer); + var var_intents = sse_decode_list_voting_ballot_intent(deserializer); + return VotingRoundSession( + roundId: var_roundId, + plan: var_plan, + recovery: var_recovery, + intents: var_intents); + } + @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( SseDeserializer deserializer) { @@ -14021,6 +14101,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_voting_round_session( + List<VotingRoundSession> self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_voting_round_session(item, serializer); + } + } + @protected void sse_encode_list_voting_service_endpoint( List<VotingServiceEndpoint> self, SseSerializer serializer) { @@ -15026,6 +15116,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { self.unconfirmedShareDelegations, serializer); } + @protected + void sse_encode_voting_round_session( + VotingRoundSession self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.roundId, serializer); + sse_encode_voting_round_plan(self.plan, serializer); + sse_encode_voting_round_recovery(self.recovery, serializer); + sse_encode_list_voting_ballot_intent(self.intents, serializer); + } + @protected void sse_encode_voting_service_endpoint( VotingServiceEndpoint self, SseSerializer serializer) { diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 2a40e3ec5..48d6103cc 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -420,6 +420,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingRoundInfo> dco_decode_list_voting_round_info(dynamic raw); + @protected + List<VotingRoundSession> dco_decode_list_voting_round_session(dynamic raw); + @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( dynamic raw); @@ -708,6 +711,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingRoundRecovery dco_decode_voting_round_recovery(dynamic raw); + @protected + VotingRoundSession dco_decode_voting_round_session(dynamic raw); + @protected VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw); @@ -1146,6 +1152,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { List<VotingRoundInfo> sse_decode_list_voting_round_info( SseDeserializer deserializer); + @protected + List<VotingRoundSession> sse_decode_list_voting_round_session( + SseDeserializer deserializer); + @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( SseDeserializer deserializer); @@ -1460,6 +1470,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingRoundRecovery sse_decode_voting_round_recovery( SseDeserializer deserializer); + @protected + VotingRoundSession sse_decode_voting_round_session( + SseDeserializer deserializer); + @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( SseDeserializer deserializer); @@ -1929,6 +1943,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_list_voting_round_info( List<VotingRoundInfo> self, SseSerializer serializer); + @protected + void sse_encode_list_voting_round_session( + List<VotingRoundSession> self, SseSerializer serializer); + @protected void sse_encode_list_voting_service_endpoint( List<VotingServiceEndpoint> self, SseSerializer serializer); @@ -2253,6 +2271,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_round_recovery( VotingRoundRecovery self, SseSerializer serializer); + @protected + void sse_encode_voting_round_session( + VotingRoundSession self, SseSerializer serializer); + @protected void sse_encode_voting_service_endpoint( VotingServiceEndpoint self, SseSerializer serializer); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index a0429792e..439dfe012 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -422,6 +422,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingRoundInfo> dco_decode_list_voting_round_info(dynamic raw); + @protected + List<VotingRoundSession> dco_decode_list_voting_round_session(dynamic raw); + @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( dynamic raw); @@ -710,6 +713,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingRoundRecovery dco_decode_voting_round_recovery(dynamic raw); + @protected + VotingRoundSession dco_decode_voting_round_session(dynamic raw); + @protected VotingServiceEndpoint dco_decode_voting_service_endpoint(dynamic raw); @@ -1148,6 +1154,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { List<VotingRoundInfo> sse_decode_list_voting_round_info( SseDeserializer deserializer); + @protected + List<VotingRoundSession> sse_decode_list_voting_round_session( + SseDeserializer deserializer); + @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( SseDeserializer deserializer); @@ -1462,6 +1472,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingRoundRecovery sse_decode_voting_round_recovery( SseDeserializer deserializer); + @protected + VotingRoundSession sse_decode_voting_round_session( + SseDeserializer deserializer); + @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( SseDeserializer deserializer); @@ -1931,6 +1945,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_list_voting_round_info( List<VotingRoundInfo> self, SseSerializer serializer); + @protected + void sse_encode_list_voting_round_session( + List<VotingRoundSession> self, SseSerializer serializer); + @protected void sse_encode_list_voting_service_endpoint( List<VotingServiceEndpoint> self, SseSerializer serializer); @@ -2255,6 +2273,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_round_recovery( VotingRoundRecovery self, SseSerializer serializer); + @protected + void sse_encode_voting_round_session( + VotingRoundSession self, SseSerializer serializer); + @protected void sse_encode_voting_service_endpoint( VotingServiceEndpoint self, SseSerializer serializer); diff --git a/lib/store.dart b/lib/store.dart index a3d6a56e5..6c636929b 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1370,6 +1370,28 @@ Future<List<VotingRoundInfo>> votingRoundList(Ref ref) async { return await votingRounds(c: c); } +/// Sessions for every locally-known round, fetched in ONE Rust call that +/// holds a single pool connection (per-round loads would need one connection +/// per round and stall the pool once the page lists many rounds). +@riverpod +Future<Map<String, VotingSessionState>> votingSessionsAll(Ref ref) async { + final rounds = await ref.watch(votingRoundListProvider.future); + if (rounds.isEmpty) return const {}; + final c = coinContext.coin; + final sessions = await votingSessions( + roundIds: rounds.map((r) => r.roundId).toList(), + c: c, + ); + return { + for (final s in sessions) + s.roundId: VotingSessionState( + plan: s.plan, + recovery: s.recovery, + intents: s.intents, + ), + }; +} + /// Friendly round title from the vote chain round status, falling back to /// the round id. The chain's `title` field is the only friendly name source /// (the config and the local DB carry no titles). @@ -1646,6 +1668,11 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } state = state.copyWith(stage: "done", progress: 1, doneLabel: doneLabel); ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + // The round is now recorded locally and its plan advanced; refresh the + // voting page so the tile leaves "Join" and shows the real status + // without a manual refresh. + ref.invalidate(votingRoundListProvider); + ref.invalidate(votingSessionProvider(roundId)); } on Exception catch (e) { state = state.copyWith(stage: "error", error: e.toString()); ref.read(votingSubmissionGuardProvider.notifier).setActive(false); diff --git a/lib/store.g.dart b/lib/store.g.dart index 75fe121cd..6ae353aa9 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -1563,6 +1563,55 @@ final class VotingRoundListProvider extends $FunctionalProvider< String _$votingRoundListHash() => r'12d2cfda4753a04d9343e21a6637789106c3ffb5'; +/// Sessions for every locally-known round, fetched in ONE Rust call that +/// holds a single pool connection (per-round loads would need one connection +/// per round and stall the pool once the page lists many rounds). + +@ProviderFor(votingSessionsAll) +const votingSessionsAllProvider = VotingSessionsAllProvider._(); + +/// Sessions for every locally-known round, fetched in ONE Rust call that +/// holds a single pool connection (per-round loads would need one connection +/// per round and stall the pool once the page lists many rounds). + +final class VotingSessionsAllProvider extends $FunctionalProvider< + AsyncValue<Map<String, VotingSessionState>>, + Map<String, VotingSessionState>, + FutureOr<Map<String, VotingSessionState>>> + with + $FutureModifier<Map<String, VotingSessionState>>, + $FutureProvider<Map<String, VotingSessionState>> { + /// Sessions for every locally-known round, fetched in ONE Rust call that + /// holds a single pool connection (per-round loads would need one connection + /// per round and stall the pool once the page lists many rounds). + const VotingSessionsAllProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'votingSessionsAllProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingSessionsAllHash(); + + @$internal + @override + $FutureProviderElement<Map<String, VotingSessionState>> $createElement( + $ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr<Map<String, VotingSessionState>> create(Ref ref) { + return votingSessionsAll(ref); + } +} + +String _$votingSessionsAllHash() => r'f5e91aa2e64beabfa71ae55bf357734a59e7e44f'; + /// Friendly round title from the vote chain round status, falling back to /// the round id. The chain's `title` field is the only friendly name source /// (the config and the local DB carry no titles). @@ -2087,7 +2136,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'84d1b907680edbebd5282f81e43d2d3590b991fb'; + r'8ab47e4d2b936d5e6c152c05f85197abb7a0d648'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 91a2e0c3b..2796c46d2 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -141,7 +141,18 @@ impl Coin { pub(crate) async fn get_connection(&self) -> Result<PoolConnection<Sqlite>> { let pool = self.get_pool()?; - pool.acquire().await.anyhow() + let start = std::time::Instant::now(); + let result = pool.acquire().await.anyhow(); + let elapsed = start.elapsed(); + if elapsed > std::time::Duration::from_secs(2) { + tracing::warn!( + "slow pool acquire took {:?} (size={}, idle={})", + elapsed, + pool.size(), + pool.num_idle() + ); + } + result } #[cfg_attr(feature = "flutter", frb)] diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index aba881927..24dcf9bf1 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -446,11 +446,12 @@ async fn prepare_bundle( let snapshot_height = u32::try_from(round_params.snapshot_height) .map_err(|_| anyhow!("snapshot height {} does not fit u32", round_params.snapshot_height))?; - let mut connection = c.get_connection().await?; let mut client = c.client().await?; - + // The lwd tree-state fetch can take a while (bounded retries); don't hold + // a pool connection across it. let lwd = voting::gather_lwd_inputs(lightwalletd_url, network, &round_params, round_name).await?; + let mut connection = c.get_connection().await?; let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; let inputs = voting::load_round_inputs( wallet_network, @@ -499,11 +500,17 @@ pub async fn delegation_setup( bundle_index: u32, c: &Coin, ) -> Result<VotingDelegationSetup> { - let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let wallet_id = { + let mut connection = c.get_connection().await?; + voting::voting_wallet_id(&mut connection, c.account).await? + }; let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; - let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let db = { + let mut connection = c.get_connection().await?; + voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await? + }; + // setup builds the PCZT (long-running); no connection is held across it. let setup = prepared.setup(&db, &NoopProgressReporter).await?; Ok(setup.into()) } @@ -520,11 +527,15 @@ pub async fn delegation_sign_and_submit( pir_server_url: &str, c: &Coin, ) -> Result<VotingDelegationSubmission> { - let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let (wallet_id, seed) = { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let seed = voting::account_seed(&mut connection, c.account).await?; + (wallet_id, seed) + }; let prepared = voting::load_prepared_bundle(&wallet_id, round_id, bundle_index)?; - let seed = voting::account_seed(&mut connection, c.account).await?; + // PIR proving runs for a while; no connection is held across it. let (submission, _wire_json) = voting::prove_and_submit_delegation( c.get_pool()?, &wallet_id, @@ -583,40 +594,46 @@ pub async fn delegation_build_submission( let account = c.account; let round_id = round_id.to_string(); let pir_server_url = pir_server_url.to_string(); - let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let pir_server_url = if pir_server_url.is_empty() { - crate::db::get_prop( - &mut connection, - &format!("voting_round_pir_url:{round_id}"), - ) - .await? - .ok_or_else(|| { - anyhow!("no saved PIR server URL for round {round_id}; pass pir_server_url once") - })? - } else { - crate::db::put_prop( - &mut connection, - &format!("voting_round_pir_url:{round_id}"), - &pir_server_url, - ) - .await?; - pir_server_url - }; - let pir_layout = match pir_layout { - Some(layout) => { - voting::save_pir_layout(&mut connection, &round_id, &layout.to_fork()).await?; - layout - } - None => voting::load_pir_layout(&mut connection, &round_id) + let (wallet_id, pir_server_url, pir_layout, seed) = { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let pir_server_url = if pir_server_url.is_empty() { + crate::db::get_prop( + &mut connection, + &format!("voting_round_pir_url:{round_id}"), + ) .await? - .map(Into::into) .ok_or_else(|| { - anyhow!("no saved PIR layout for round {round_id}; pass pir_layout once") - })?, + anyhow!("no saved PIR server URL for round {round_id}; pass pir_server_url once") + })? + } else { + crate::db::put_prop( + &mut connection, + &format!("voting_round_pir_url:{round_id}"), + &pir_server_url, + ) + .await?; + pir_server_url + }; + let pir_layout = match pir_layout { + Some(layout) => { + voting::save_pir_layout(&mut connection, &round_id, &layout.to_fork()).await?; + layout + } + None => voting::load_pir_layout(&mut connection, &round_id) + .await? + .map(Into::into) + .ok_or_else(|| { + anyhow!("no saved PIR layout for round {round_id}; pass pir_layout once") + })?, + }; + let seed = voting::account_seed(&mut connection, account).await?; + // Release the connection before setup + signing + PIR proving, which + // run for a while; don't hold a pool slot hostage during the long + // phase (a later internal acquire would queue behind it). + (wallet_id, pir_server_url, pir_layout, seed) }; let prepared = voting::load_prepared_bundle(&wallet_id, &round_id, bundle_index)?; - let seed = voting::account_seed(&mut connection, account).await?; let progress = Arc::new(DelegationProgressBridge::new({ let sink_for_progress = sink.clone(); @@ -668,6 +685,7 @@ pub async fn delegation_build_submission( // so persist the wire body for `delegation_wire_json` to pick up. This also // makes a crash between proving and broadcasting resumable without // re-proving. + let mut connection = c.get_connection().await?; crate::db::put_prop( &mut connection, &format!("voting_round_delegation_wire:{round_id}:{bundle_index}"), @@ -1645,6 +1663,17 @@ pub struct VotingBallotIntent { pub choice: Option<u32>, } +/// One round's full session state: resume plan, recovery snapshot, and +/// ballot intents — loaded together under a single pool connection. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingRoundSession { + pub round_id: String, + pub plan: VotingRoundPlan, + pub recovery: VotingRoundRecovery, + pub intents: Vec<VotingBallotIntent>, +} + /// Delegation proof/signing progress event, one-to-one with the fork's /// `DelegationProgress`. The bookend variants (`SelectingNotes`, /// `SigningPayload`, `PayloadReady`) are emitted by the host wrapper; the @@ -2149,6 +2178,49 @@ pub async fn voting_ballot_intents(round_id: &str, c: &Coin) -> Result<Vec<Votin Ok(intents.into_iter().map(Into::into).collect()) } +/// Loads sessions for many rounds in a single Rust call that holds ONE pool +/// connection (the per-round entry points above would need one connection per +/// round and stall the pool once the page has many rounds). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_sessions(round_ids: Vec<String>, c: &Coin) -> Result<Vec<VotingRoundSession>> { + let account = c.account; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let mut sessions = Vec::with_capacity(round_ids.len()); + for round_id in round_ids { + // Draft proposal ids live in wallet props; read them on the same + // connection so the plan sees open proposals (mirrors the Dart + // votingSession._draftProposalIds). + let draft_ids = match crate::db::get_prop( + &mut connection, + &format!("voting_drafts:{round_id}"), + ) + .await? + { + Some(d) if !d.is_empty() => serde_json::from_str::<Vec<serde_json::Value>>(&d) + .unwrap_or_default() + .iter() + .filter_map(|x| x.get("proposal_id").and_then(|v| v.as_u64()).map(|n| n as u32)) + .filter(|&id| id > 0) + .collect::<Vec<u32>>(), + _ => Vec::new(), + }; + let plan = zcash_voting::session::resume_plan(&db, &mut *connection, &round_id, &draft_ids) + .await?; + let recovery = + zcash_voting::recovery::round_snapshot(&db, &mut *connection, &round_id).await?; + let intents = db.ballot_intents(&mut *connection, &round_id).await?; + sessions.push(VotingRoundSession { + round_id, + plan: plan.into(), + recovery: recovery.into(), + intents: intents.into_iter().map(Into::into).collect(), + }); + } + Ok(sessions) +} + // --------------------------------------------------------------------------- // Vote-chain HTTP // --------------------------------------------------------------------------- diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 6bb8fe1a4..ec94bf459 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1724058360; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1211184662; // Section: executor @@ -8553,6 +8553,44 @@ fn wire__crate__api__voting__voting_rounds_impl( }, ) } +fn wire__crate__api__voting__voting_sessions_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_sessions", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_ids = <Vec<String>>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_sessions(api_round_ids, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_set_ballot_intent_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -10177,6 +10215,20 @@ impl SseDecode for Vec<crate::api::voting::VotingRoundInfo> { } } +impl SseDecode for Vec<crate::api::voting::VotingRoundSession> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = <i32>::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(<crate::api::voting::VotingRoundSession>::sse_decode( + deserializer, + )); + } + return ans_; + } +} + impl SseDecode for Vec<crate::api::voting::VotingServiceEndpoint> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -11713,6 +11765,23 @@ impl SseDecode for crate::api::voting::VotingRoundRecovery { } } +impl SseDecode for crate::api::voting::VotingRoundSession { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_roundId = <String>::sse_decode(deserializer); + let mut var_plan = <crate::api::voting::VotingRoundPlan>::sse_decode(deserializer); + let mut var_recovery = <crate::api::voting::VotingRoundRecovery>::sse_decode(deserializer); + let mut var_intents = + <Vec<crate::api::voting::VotingBallotIntent>>::sse_decode(deserializer); + return crate::api::voting::VotingRoundSession { + round_id: var_roundId, + plan: var_plan, + recovery: var_recovery, + intents: var_intents, + }; + } +} + impl SseDecode for crate::api::voting::VotingServiceEndpoint { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -12503,41 +12572,42 @@ fn pde_ffi_dispatcher_primary_impl( data_len, ), 215 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 216 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 216 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), + 217 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 217 => wire__crate__api__voting__voting_share_add_servers_impl( + 218 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 218 => { + 219 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 219 => { + 220 => { wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) } - 220 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 221 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), - 222 => { + 221 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 222 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 223 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 223 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 224 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 224 => { + 225 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 225 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 226 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 227 => { + 226 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 227 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 228 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -14367,6 +14437,29 @@ impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingRoundRecovery> } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingRoundSession { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.round_id.into_into_dart().into_dart(), + self.plan.into_into_dart().into_dart(), + self.recovery.into_into_dart().into_dart(), + self.intents.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingRoundSession +{ +} +impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingRoundSession> + for crate::api::voting::VotingRoundSession +{ + fn into_into_dart(self) -> crate::api::voting::VotingRoundSession { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingServiceEndpoint { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -15610,6 +15703,16 @@ impl SseEncode for Vec<crate::api::voting::VotingRoundInfo> { } } +impl SseEncode for Vec<crate::api::voting::VotingRoundSession> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + <i32>::sse_encode(self.len() as _, serializer); + for item in self { + <crate::api::voting::VotingRoundSession>::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec<crate::api::voting::VotingServiceEndpoint> { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -16706,6 +16809,16 @@ impl SseEncode for crate::api::voting::VotingRoundRecovery { } } +impl SseEncode for crate::api::voting::VotingRoundSession { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + <String>::sse_encode(self.round_id, serializer); + <crate::api::voting::VotingRoundPlan>::sse_encode(self.plan, serializer); + <crate::api::voting::VotingRoundRecovery>::sse_encode(self.recovery, serializer); + <Vec<crate::api::voting::VotingBallotIntent>>::sse_encode(self.intents, serializer); + } +} + impl SseEncode for crate::api::voting::VotingServiceEndpoint { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { diff --git a/rust/src/voting.rs b/rust/src/voting.rs index 2baee1583..63b97cfa6 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -482,8 +482,10 @@ pub async fn prepare_delegation_bundle( bundle_index: u32, bundle_policy: BundlePolicy, ) -> Result<PreparedDelegationBundle> { - let mut conn = pool.acquire().await?; - let db = open_voting_db(pool, &mut conn, wallet_id).await?; + let db = { + let mut conn = pool.acquire().await?; + open_voting_db(pool, &mut conn, wallet_id).await? + }; Ok(zcash_voting::delegate::prepare_delegation_bundle_with_inputs( &db, PrepareDelegationBundleWithInputsParams { @@ -573,8 +575,10 @@ pub async fn prove_and_submit_delegation_with_progress( pir_server_url: &str, progress: Arc<dyn DelegationProgressReporter>, ) -> Result<(DelegationSubmission, String)> { - let mut conn = pool.acquire().await?; - let db = open_voting_db(pool, &mut conn, wallet_id).await?; + let db = { + let mut conn = pool.acquire().await?; + open_voting_db(pool, &mut conn, wallet_id).await? + }; let _setup = prepared.setup(&db, progress.as_ref()).await?; let request = prepared.signing_request(&db).await?; From aca790cd1f018eb29197a692801f9feb219083cd Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 09:54:42 +0800 Subject: [PATCH 105/189] fix: build with Flutter 3.47.0 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de626546f..62206a005 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - os: windows-latest target: windows env: - FLUTTER_VERSION: 3.44.2 + FLUTTER_VERSION: 3.47.0 permissions: id-token: write attestations: write From 891ff2dc3fdfe21e6227e0b8b964e1a283c47658 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 10:30:02 +0800 Subject: [PATCH 106/189] fix: bump Kotlin to 2.2.20 for Flutter 3.47.0 Android build --- android/settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/settings.gradle b/android/settings.gradle index ea127485a..7cffcd0ee 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "com.android.application" version "8.13.0" apply false - id "org.jetbrains.kotlin.android" version "2.2.10" apply false + id "org.jetbrains.kotlin.android" version "2.2.20" apply false } include ":app" From 85442d2eb361cadfb8ee630d0bbf5ae93650d570 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 13:31:17 +0800 Subject: [PATCH 107/189] chore: update CONTRIBUTING file --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 08b18b5e8..a59db3321 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,2 +1,4 @@ Because this is a solo project, I prefer that contributors reach out and ask first before submitting any PR. + +When opening a PR from a fork, please enable “Allow edits from maintainers” so maintainers can make fixes directly to your PR. From 4728be67feef1f9b7f75d1f6059b396900101bc2 Mon Sep 17 00:00:00 2001 From: macintoshhelper <macintoshhelper@users.noreply.github.com> Date: Tue, 18 Aug 2026 18:13:15 +0400 Subject: [PATCH 108/189] add ironwood pool to diversifier index resolve/backfill (#1213) Co-authored-by: macintoshhelper <6757532+macintoshhelper@users.noreply.github.com> --- rust/src/db.rs | 6 +++--- rust/src/sync.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/src/db.rs b/rust/src/db.rs index a072d39e9..8ee3ab867 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -663,7 +663,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re // Fetch distinct accounts with unbackfilled notes let accounts: Vec<(u32,)> = sqlx::query_as( - "SELECT DISTINCT account FROM notes WHERE pool IN (1, 2) AND diversifier IS NOT NULL AND diversifier_index IS NULL", + "SELECT DISTINCT account FROM notes WHERE pool IN (1, 2, 3) AND diversifier IS NOT NULL AND diversifier_index IS NULL", ) .fetch_all(&mut *connection) .await?; @@ -691,7 +691,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re // Fetch unbackfilled notes for this account let notes: Vec<(u32, u8, u8, Vec<u8>)> = sqlx::query_as( - "SELECT id_note, pool, scope, diversifier FROM notes WHERE account = ? AND pool IN (1, 2) AND diversifier IS NOT NULL AND diversifier_index IS NULL", + "SELECT id_note, pool, scope, diversifier FROM notes WHERE account = ? AND pool IN (1, 2, 3) AND diversifier IS NOT NULL AND diversifier_index IS NULL", ) .bind(account) .fetch_all(&mut *connection) @@ -702,7 +702,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re 1 => sapling_dfvk .as_ref() .and_then(|dfvk| resolve_sapling_diversifier_index(dfvk, scope, &diversifier)), - 2 => orchard_fvk + 2 | 3 => orchard_fvk .as_ref() .and_then(|fvk| resolve_orchard_diversifier_index(fvk, scope, &diversifier)), _ => None, diff --git a/rust/src/sync.rs b/rust/src/sync.rs index 153dd92f5..49aa2cbf9 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -649,7 +649,7 @@ fn resolve_diversifier_index( 1 => cache.sapling.get(&account).and_then(|keys| { crate::db::resolve_sapling_diversifier_index(&keys.dfvk, scope, diversifier) }), - 2 => cache.orchard.get(&account).and_then(|keys| { + 2 | 3 => cache.orchard.get(&account).and_then(|keys| { crate::db::resolve_orchard_diversifier_index(&keys.fvk, scope, diversifier) }), _ => None, From f22a3162ca0ac459e842d1ee2fba1be2dacb1114 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 22:16:58 +0800 Subject: [PATCH 109/189] fix: drop redundant pool predicate from diversifier index backfill --- rust/src/db.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/src/db.rs b/rust/src/db.rs index 8ee3ab867..984eefe43 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -648,7 +648,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re // Check if any notes need backfilling let count: (i64,) = sqlx::query_as( - "SELECT COUNT(*) FROM notes WHERE pool IN (1, 2) AND diversifier IS NOT NULL AND diversifier_index IS NULL", + "SELECT COUNT(*) FROM notes WHERE diversifier IS NOT NULL AND diversifier_index IS NULL", ) .fetch_one(&mut *connection) .await?; @@ -663,7 +663,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re // Fetch distinct accounts with unbackfilled notes let accounts: Vec<(u32,)> = sqlx::query_as( - "SELECT DISTINCT account FROM notes WHERE pool IN (1, 2, 3) AND diversifier IS NOT NULL AND diversifier_index IS NULL", + "SELECT DISTINCT account FROM notes WHERE diversifier IS NOT NULL AND diversifier_index IS NULL", ) .fetch_all(&mut *connection) .await?; @@ -691,7 +691,7 @@ pub async fn backfill_diversifier_index(connection: &mut SqliteConnection) -> Re // Fetch unbackfilled notes for this account let notes: Vec<(u32, u8, u8, Vec<u8>)> = sqlx::query_as( - "SELECT id_note, pool, scope, diversifier FROM notes WHERE account = ? AND pool IN (1, 2, 3) AND diversifier IS NOT NULL AND diversifier_index IS NULL", + "SELECT id_note, pool, scope, diversifier FROM notes WHERE account = ? AND diversifier IS NOT NULL AND diversifier_index IS NULL", ) .bind(account) .fetch_all(&mut *connection) From ba14db4370bb89601f84356c3ef8ee2c6251c8e7 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 18 Aug 2026 22:37:02 +0800 Subject: [PATCH 110/189] fix: stop ref use after unmount when closing Folders page (issue 1203) --- lib/pages/folder.dart | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/pages/folder.dart b/lib/pages/folder.dart index 22dcf7e1e..55573c3db 100644 --- a/lib/pages/folder.dart +++ b/lib/pages/folder.dart @@ -13,29 +13,53 @@ class FolderPage extends ConsumerStatefulWidget { class FolderPageState extends ConsumerState<FolderPage> { late final c = coinContext.coin; + late final ProviderContainer container; + late final SelectedFolder selectedFolderNotifier; List<(Folder, bool)> folders = []; int? selectedIndex; @override void initState() { super.initState(); - Future(refresh); + // Capture these now: `ref` is unsafe to use once the widget is unmounted, + // so the disposal path must not touch it. `containerOf(listen: false)` + // avoids the inherited-widget dependency that `ref.container` creates + // (not allowed in initState). + container = ProviderScope.containerOf(context, listen: false); + selectedFolderNotifier = ref.read(selectedFolderProvider.notifier); + _load(); } @override void dispose() { - Future(refresh); + // Unselect the folder if it was deleted while the page was open. Runs on + // a later tick and never uses `ref`. + Future(() async { + final selected = container.exists(selectedFolderProvider) + ? container.read(selectedFolderProvider) + : null; + if (selected == null) return; + final foldrs = await listFolders(c: c); + refresh(foldrs, selected); + }); super.dispose(); } - Future<void> refresh() async { + // Fetches the latest folders and applies them to the page. `ref` is only + // used before the await, so this stays safe if the widget unmounts mid-load. + Future<void> _load() async { final foldrs = await ref.read(getFoldersProvider.future); - final selectedFolder = ref.read(selectedFolderProvider); + refresh(foldrs, container.read(selectedFolderProvider)); + } + + // Applies a folder list to the page. Takes everything it needs as + // parameters and never touches `ref`, so it is safe to call after unmount. + void refresh(List<Folder> foldrs, Folder? selectedFolder) { if (selectedFolder != null) { selectedIndex = foldrs.indexWhere((f) => f.id == selectedFolder.id); if (selectedIndex == -1) { selectedIndex = null; - (ref.read(selectedFolderProvider.notifier)).unselect(); + if (container.exists(selectedFolderProvider)) selectedFolderNotifier.unselect(); } } folders = foldrs.map((f) => (f, false)).toList(); @@ -86,7 +110,7 @@ class FolderPageState extends ConsumerState<FolderPage> { final folderName = await inputText(context, title: "New Folder"); if (folderName != null) { await createNewFolder(name: folderName, c: c); - await refresh(); + await _load(); } } @@ -94,7 +118,7 @@ class FolderPageState extends ConsumerState<FolderPage> { final folderName = await inputText(context, title: "Rename Folder"); if (folderName != null) { await renameFolder(id: selection.first.id, name: folderName, c: c); - await refresh(); + await _load(); } } @@ -102,7 +126,7 @@ class FolderPageState extends ConsumerState<FolderPage> { final confirmed = await confirmDialog(context, title: "Do you want to delete these folders?", message: "Accounts assigned to these folders will be kept."); if (confirmed) { await deleteFolders(ids: selection.map((f) => f.id).toList(), c: c); - await refresh(); + await _load(); ref.invalidate(getAccountsProvider); } } From f291d65246f4b5df07fbc0f6d97fb798af576089 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Wed, 19 Aug 2026 06:09:29 +0800 Subject: [PATCH 111/189] fix(voting): keep back navigation to account after vote submission Done on the vote receipt used go('/voting'), which reset the stack and left the polls page as the root with no way back to the account page. Chain proposal -> review -> status via pushReplacement and pop the confirmation page instead, so the polls page keeps its back arrow. --- lib/pages/voting_confirmation.dart | 5 ++++- lib/pages/voting_proposal.dart | 2 +- lib/pages/voting_review.dart | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index e5057f396..944e085ab 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -106,7 +106,10 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> ), const SizedBox(height: 24), FilledButton( - onPressed: () => GoRouter.of(context).go("/voting"), + // The submission flow uses pushReplacement, so the stack + // below is [account, /voting] — pop back to the polls page, + // whose back arrow still returns to the account page. + onPressed: () => GoRouter.of(context).pop(), child: const Text("Done"), ), ], diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index ae23b9ebc..bd021d06a 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -303,7 +303,7 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { const SizedBox(height: 8), FilledButton( onPressed: allAnswered - ? () => GoRouter.of(context).push("/voting/review", extra: { + ? () => GoRouter.of(context).pushReplacement("/voting/review", extra: { "roundId": widget.roundId, "chainUrl": widget.chainUrl, "roundParamsJson": _roundParamsJson, diff --git a/lib/pages/voting_review.dart b/lib/pages/voting_review.dart index bba1edad3..7b1f50338 100644 --- a/lib/pages/voting_review.dart +++ b/lib/pages/voting_review.dart @@ -151,7 +151,7 @@ class VotingReviewPageState extends ConsumerState<VotingReviewPage> { : () async { final settings = await ref.read(appSettingsProvider.future); if (!context.mounted) return; - await GoRouter.of(context).push("/voting/status", extra: { + await GoRouter.of(context).pushReplacement("/voting/status", extra: { "roundId": widget.roundId, "chainUrl": widget.chainUrl, "pirServerUrl": "", From bed813138743371f1a99ebf07f5322eeaa8ead70 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 20 Aug 2026 07:42:33 +0800 Subject: [PATCH 112/189] fix(settings): keep transport selector within screen width (FittedBox + padding) --- lib/settings.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/settings.dart b/lib/settings.dart index d3d13eeaa..5163c8e62 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -171,9 +171,12 @@ class SettingsFormState extends ConsumerState<SettingsForm> { Tooltip( message: "Network transport: connect directly, through the embedded " "Tor (Arti) client, through the Nym mixnet, or via an external proxy", - child: Row( - children: [ - SegmentedButton<int>( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: SegmentedButton<int>( segments: const [ ButtonSegment(value: 0, label: Text("Direct")), ButtonSegment(value: 1, label: Text("Tor")), @@ -183,7 +186,7 @@ class SettingsFormState extends ConsumerState<SettingsForm> { selected: {isNymServer ? 0 : settings.transport}, onSelectionChanged: isNymServer ? null : onChangedTransport, ), - ], + ), ), ), if (isNymServer) From a7b42382e8ddd59884e8a1ac8e9fe2950f6d5b51 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 20 Aug 2026 07:43:54 +0800 Subject: [PATCH 113/189] ci: bump CI Flutter version to 3.47.1 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62206a005..50bf3555f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - os: windows-latest target: windows env: - FLUTTER_VERSION: 3.47.0 + FLUTTER_VERSION: 3.47.1 permissions: id-token: write attestations: write From 1a9bc9978231e5fe1043165b76f45a7a86ae61d8 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 20 Aug 2026 09:50:40 +0800 Subject: [PATCH 114/189] fix(voting): default vote node URL to the vote chain server when unset --- lib/pages/voting_polls.dart | 6 +++++- lib/pages/voting_proposal.dart | 8 ++++++-- lib/store.dart | 7 ++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index f8add16f9..06d836d4b 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -318,7 +318,11 @@ class _RoundTile extends ConsumerWidget { "roundId": round.roundId, "chainUrl": chainUrl, "pirServerUrl": "", - "voteNodeUrl": settings.voteNodeUrl, + // An unset Vote Node URL defaults to the vote chain server: the same + // REST API serves the commitment tree the vote syncs from. + "voteNodeUrl": settings.voteNodeUrl.isNotEmpty + ? settings.voteNodeUrl + : chainUrl, }); } } diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index bd021d06a..40e8dd759 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -125,12 +125,16 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { } // Best-effort vote-tree pre-sync so the commit step doesn't wait on it. + // An unset Vote Node URL falls back to the vote chain server: the same + // REST API serves the commitment tree the sync pulls from. final settings = await ref.read(appSettingsProvider.future); - if (settings.voteNodeUrl.isNotEmpty) { + final voteNodeUrl = + settings.voteNodeUrl.isNotEmpty ? settings.voteNodeUrl : widget.chainUrl; + if (voteNodeUrl.isNotEmpty) { try { await votingSyncTree( roundId: widget.roundId, - voteNodeUrl: settings.voteNodeUrl, + voteNodeUrl: voteNodeUrl, c: c, ); } on AnyhowException catch (_) { diff --git a/lib/store.dart b/lib/store.dart index 6c636929b..b07485439 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -2048,6 +2048,11 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { required String chainUrl, required String voteNodeUrl, }) async { + // An unset Vote Node URL falls back to the vote chain's REST API: the + // chain server also serves the commitment tree the VAN witnesses sync + // from (the polls page resolves the same default for the chain). + final resolvedVoteNodeUrl = + voteNodeUrl.isNotEmpty ? voteNodeUrl : chainUrl; final c = coinContext.coin; // Durable ballot intents first (mirrors vizor's writeBallotIntents): @@ -2141,7 +2146,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { roundId: roundId, bundleIndex: bundleIndex, draftsJson: jsonEncode([draft]), - voteNodeUrl: voteNodeUrl, + voteNodeUrl: resolvedVoteNodeUrl, c: c, ); await for (final event in stream) { From e8e9f22c196ec718c675484bc9ff31d125116eb0 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 20 Aug 2026 11:47:35 +0800 Subject: [PATCH 115/189] fix(account): derive sapling address on file import and fail fast on corrupt stored addresses --- rust/src/account.rs | 20 +++++++++++++------- rust/src/api/account.rs | 2 +- rust/src/db.rs | 32 +++++++++++++++++++++++++++----- rust/src/io.rs | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/rust/src/account.rs b/rust/src/account.rs index 24de7bec7..327e36948 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -680,25 +680,31 @@ pub async fn get_account_full_address( .await?; let saddress = sqlx::query( - "SELECT sa.xvk, sa.address FROM sapling_accounts sa + "SELECT sa.xvk, sa.address, a.dindex FROM sapling_accounts sa JOIN accounts a ON sa.account = a.id_account AND sa.account = ?", ) .bind(account) - .map(|row: SqliteRow| { + .map(|row: SqliteRow| -> Result<PaymentAddress, anyhow::Error> { let xvk: Vec<u8> = row.get(0); let address: String = row.get(1); - let fvk = DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap(); + let _dindex: u32 = row.get(2); + let fvk = DiversifiableFullViewingKey::from_bytes(&xvk.try_into().map_err(|_| { + anyhow!("invalid sapling xvk length for account {account}") + })?) + .ok_or_else(|| anyhow!("invalid sapling xvk for account {account}"))?; if scope == 1 && hw == 0 { // we do not need to derive a diversified change address // since they are not exposed to the user let (_, pa) = fvk.change_address(); - pa + Ok(pa) } else { - PaymentAddress::decode(network, &address).unwrap() + PaymentAddress::decode(network, &address) + .map_err(|e| anyhow!("invalid stored sapling address for account {account}: {e}")) } }) .fetch_optional(&mut *connection) - .await?; + .await? + .transpose()?; let oaddress = sqlx::query( "SELECT a.dindex, oa.xvk FROM orchard_accounts oa @@ -1351,7 +1357,7 @@ pub async fn has_pool(connection: &mut SqliteConnection, account: u32, pool: u8) Ok(has_pool) } -fn derive_sapling_address( +pub(crate) fn derive_sapling_address( network: &Network, sxvk: &DiversifiableFullViewingKey, dindex: u32, diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index c5990a8e4..bb87032f0 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -665,7 +665,7 @@ pub async fn import_account(passphrase: &str, data: &[u8], c: &Coin) -> Result<( let mut connection = c.get_connection().await?; let decrypted = decrypt(passphrase, data)?; - crate::io::import_account(&mut connection, &decrypted).await?; + crate::io::import_account(&c.network(), &mut connection, &decrypted).await?; Ok(()) } diff --git a/rust/src/db.rs b/rust/src/db.rs index 984eefe43..2bc213e38 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -585,18 +585,32 @@ pub async fn migrate_sapling_addresses( network: &Network, connection: &mut SqliteConnection, ) -> Result<()> { + // Cover both empty and NULL addresses: older schemas left the column + // NULL, newer ones default it to ''. let accounts: Vec<(u32, u32, Vec<u8>)> = sqlx::query_as( "SELECT id_account, dindex, xvk FROM accounts a JOIN sapling_accounts s ON a.id_account = s.account - WHERE address = ''", + WHERE address IS NULL OR address = ''", ) .fetch_all(&mut *connection) .await?; for (account, dindex, xvk) in accounts { - let fvk: [u8; 128] = tiu!(xvk); - let fvk = DiversifiableFullViewingKey::from_bytes(&fvk).unwrap(); - let address = fvk.address((dindex as u64).into()).unwrap(); + // A row that cannot be backfilled must not abort the migration (or + // panic the runtime): skip it, and the lenient address readers will + // report it as missing. + let Ok(fvk) = <[u8; 128]>::try_from(xvk.as_slice()) else { + tracing::warn!("sapling xvk for account {account} is not 128 bytes; skipping backfill"); + continue; + }; + let Some(fvk) = DiversifiableFullViewingKey::from_bytes(&fvk) else { + tracing::warn!("invalid sapling xvk for account {account}; skipping backfill"); + continue; + }; + let Some(address) = fvk.address((dindex as u64).into()) else { + tracing::warn!("invalid diversifier {dindex} for account {account}; skipping backfill"); + continue; + }; let address = address.encode(network); sqlx::query("UPDATE sapling_accounts SET address = ?2 WHERE account = ?1") .bind(account) @@ -1130,7 +1144,15 @@ pub async fn select_account_sapling( }), xvk: xvk .map(|xvk| DiversifiableFullViewingKey::from_bytes(&xvk.try_into().unwrap()).unwrap()), - address: address.map(|a| PaymentAddress::decode(network, &a).unwrap()), + // A corrupt or empty stored address (e.g. rows imported before the + // address was backfilled) must not panic the runtime: surface a + // clear error instead. + address: match address { + Some(a) => Some(PaymentAddress::decode(network, &a).map_err(|e| { + anyhow!("invalid stored sapling address for account {account}: {e}") + })?), + None => None, + }, }; Ok(keys) diff --git a/rust/src/io.rs b/rust/src/io.rs index 099ab94fc..df73ba4d9 100644 --- a/rust/src/io.rs +++ b/rust/src/io.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, collections::HashMap}; use age::{scrypt::Identity, Decryptor, Encryptor}; -use anyhow::Result; +use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; use serde_with::{hex::Hex, serde_as}; use sqlx::{ @@ -12,8 +12,10 @@ use sqlx::{ }; use std::io::prelude::*; use tracing::info; +use zcash_keys::keys::sapling::{DiversifiableFullViewingKey, ExtendedSpendingKey}; use zstd::DEFAULT_COMPRESSION_LEVEL; +use crate::api::coin::Network; use crate::db::DB_VERSION; pub async fn export_account(connection: &mut SqliteConnection, account: u32) -> Result<Vec<u8>> { @@ -474,7 +476,11 @@ pub async fn export_account(connection: &mut SqliteConnection, account: u32) -> Ok(data) } -pub async fn import_account(connection: &mut SqliteConnection, data: &[u8]) -> Result<()> { +pub async fn import_account( + network: &Network, + connection: &mut SqliteConnection, + data: &[u8], +) -> Result<()> { let mut decoder = zstd::Decoder::new(data)?; let mut data = String::new(); decoder.read_to_string(&mut data)?; @@ -593,6 +599,31 @@ pub async fn import_account(connection: &mut SqliteConnection, data: &[u8]) -> R .bind(&skeys.xvk) .execute(&mut *tx) .await?; + // The backup file carries only the sapling keys; the address column + // would stay at its empty default, which select_account_sapling + // cannot decode (it panicked on it). Derive the address from the + // imported keys, mirroring new_account's seed-restore derivation. + let sxvk = match skeys.xsk.as_ref() { + Some(xsk) => ExtendedSpendingKey::from_bytes(&xsk.0) + .map_err(|_| anyhow!("invalid sapling xsk in account backup"))? + .to_diversifiable_full_viewing_key(), + None => { + let bytes: [u8; 128] = skeys + .xvk + .0 + .as_slice() + .try_into() + .map_err(|_| anyhow!("invalid sapling xvk length in account backup"))?; + DiversifiableFullViewingKey::from_bytes(&bytes) + .ok_or_else(|| anyhow!("invalid sapling xvk in account backup"))? + } + }; + let address = crate::account::derive_sapling_address(network, &sxvk, io_account.dindex); + sqlx::query("UPDATE sapling_accounts SET address = ?2 WHERE account = ?1") + .bind(new_id_account) + .bind(&address) + .execute(&mut *tx) + .await?; } info!("Importing orchard key"); if let Some(okeys) = io_account.okeys.as_ref() { From ad7ad0889b135b5fd58b3790061caa4f6827c1d7 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 22 Aug 2026 15:29:43 +0800 Subject: [PATCH 116/189] feat(voting): resumable recovery across network, server, and client failures Design review found six gaps against resumability: a server crash lost an accepted tx from the in-memory mempool with no re-broadcast path; a client crash between the broadcast response and persisting the tx hash could dead-end on a duplicate-nullifier 422; no failover across configured vote servers; transient blips killed the run with manual-only retry; share tracking was session-scoped and helper failures failed the whole job; the status page trapped the user during long polls. - votechain client: every completed HTTP response is an answer (status + body + Retry-After pass through); only transport failures are Err - VoteChainFailover service: rotates across configured servers, honors 503 Retry-After, accepts 502-with-hash envelopes, remembers the last-working server per round - bounded auto-retry with 30/60/120s backoff in the submission job; the plan-driven body is idempotent, so re-running is always safe - poll-with-rebroadcast fallback: a recorded hash that never confirms is re-broadcast with byte-identical persisted wire (the vote wire is now persisted like the delegation wire), keeping the recorded hash valid - duplicate-nullifier 422s reconcile confirmations from the commitment tree (cast-vote appends the VAN output immediately before the vote commitment, so one scan recovers both positions) - share tracking extracted into a session-independent provider re-armed on wallet open and voting-page open; helper outages no longer fail the run - voting pages: retrying stage, leave-anytime PopScope, tree-verified receipts without a tx hash - pin rustc 1.95.0 via rust-toolchain.toml (1.88 cannot compile the pinned libcrux-psq) - fork rev bumped to zkool-recovery (commitment-tree recovery APIs + standalone build repair) --- Cargo.lock | 9 +- lib/pages/splash.dart | 5 + lib/pages/voting_confirmation.dart | 11 +- lib/pages/voting_polls.dart | 18 + lib/pages/voting_status.dart | 19 +- lib/services/votechain_backoff.dart | 18 + lib/services/votechain_classify.dart | 47 + lib/services/votechain_confirmation.dart | 17 + lib/services/votechain_failover.dart | 132 +++ lib/src/rust/api/voting.dart | 86 +- lib/src/rust/api/voting.freezed.dart | 359 ++++++- lib/src/rust/frb_generated.dart | 354 ++++++- lib/src/rust/frb_generated.io.dart | 12 + lib/src/rust/frb_generated.web.dart | 12 + lib/store.dart | 962 ++++++++++++++---- lib/store.freezed.dart | 116 ++- lib/store.g.dart | 84 +- rust-toolchain.toml | 8 + rust/Cargo.toml | 8 +- rust/src/api/voting.rs | 179 +++- rust/src/frb_generated.rs | 405 +++++++- rust/src/net/votechain.rs | 154 ++- rust/src/voting.rs | 14 +- rust/tests/voting_recovery_reconcile.rs | 280 +++++ test/services/votechain_backoff_test.dart | 15 + test/services/votechain_classify_test.dart | 63 ++ .../services/votechain_confirmation_test.dart | 16 + test/services/votechain_failover_test.dart | 136 +++ 28 files changed, 3177 insertions(+), 362 deletions(-) create mode 100644 lib/services/votechain_backoff.dart create mode 100644 lib/services/votechain_classify.dart create mode 100644 lib/services/votechain_failover.dart create mode 100644 rust-toolchain.toml create mode 100644 rust/tests/voting_recovery_reconcile.rs create mode 100644 test/services/votechain_backoff_test.dart create mode 100644 test/services/votechain_classify_test.dart create mode 100644 test/services/votechain_failover_test.dart diff --git a/Cargo.lock b/Cargo.lock index aca9a4d79..d0f06cbea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9376,6 +9376,7 @@ dependencies = [ "dataloader", "ed25519-dalek", "env_logger", + "ff", "figment", "flutter_rust_bridge", "fpdec", @@ -9407,6 +9408,7 @@ dependencies = [ "nym-sdk", "nym-smolmix", "orchard", + "pasta_curves", "pczt", "prost 0.14.4", "qrcode", @@ -9441,6 +9443,7 @@ dependencies = [ "tracing-subscriber", "uuid", "vcard4", + "vote-commitment-tree", "warp", "webpki-roots 1.0.9", "x25519-dalek", @@ -13210,7 +13213,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" dependencies = [ "anyhow", "ff", @@ -13226,7 +13229,7 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" dependencies = [ "base64 0.22.1", "ff", @@ -14415,7 +14418,7 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=faa06af424d284bf98a1a2687b65e6b1bf312ab1#faa06af424d284bf98a1a2687b65e6b1bf312ab1" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/lib/pages/splash.dart b/lib/pages/splash.dart index 19f729676..342460bd4 100644 --- a/lib/pages/splash.dart +++ b/lib/pages/splash.dart @@ -106,6 +106,11 @@ class SplashPageState extends ConsumerState<SplashPage> { c = c.setTransport(transport: settings.transport); c = c.setProxy(proxy: settings.proxy); coinContext.set(coin: c); + // Re-arm helper-share tracking for rounds with pending share work, so a + // client restart resumes share delivery without visiting the voting page. + if (settings.votingConfigUrl.isNotEmpty) { + unawaited(Future(() => armShareTrackingForPendingRounds(ref))); + } final synchronizer = ref.read(synchronizerProvider.notifier); synchronizer.autoSync(); final mempool = ref.read(mempoolProvider.notifier); diff --git a/lib/pages/voting_confirmation.dart b/lib/pages/voting_confirmation.dart index 944e085ab..e8f8a7929 100644 --- a/lib/pages/voting_confirmation.dart +++ b/lib/pages/voting_confirmation.dart @@ -31,14 +31,16 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> if (pinlock.value ?? false) return PinLock(); final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); - // Confirmed vote txs (per proposal), shown as on-chain evidence. + // Confirmed vote txs (per proposal), shown as on-chain evidence. A vote + // confirmed via commitment-tree recovery has no tx hash — it still + // counts as confirmed evidence. final confirmedVotes = (ref .watch(votingSessionProvider(widget.roundId)) .value ?.recovery ?.votes ?? const <VotingVoteRecovery>[]) - .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) + .where((v) => v.phase == "confirmed") .toList(); // Human-readable ballot evidence: proposal titles and option labels, // keyed by proposal id (not list position). @@ -99,7 +101,10 @@ class VotingConfirmationPageState extends ConsumerState<VotingConfirmationPage> Padding( padding: const EdgeInsets.only(top: 8), child: SelectableText( - "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}", + v.txHash != null && v.txHash!.isNotEmpty + ? "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}" + : "${voteLabel(v)}\ntree ${v.vcTreePosition} · " + "verified in the commitment tree", textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall, ), diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index 06d836d4b..03d2707e6 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -46,6 +46,10 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { if (mounted) await showException(context, e.message); } }); + // Opening the voting page re-arms helper-share tracking for rounds with + // pending share work, so a restart resumes delivery without a manual + // status-page visit. + Future(() => armShareTrackingForPendingRounds(ref)); } /// Voting v1 supports software accounts only; the fork signs with the @@ -76,6 +80,7 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { final config = ref.watch(votingConfigProvider); final rounds = ref.watch(votingRoundListProvider); + final shareAttention = ref.watch(votingShareTrackerProvider); return Scaffold( appBar: AppBar( title: Text("Voting"), @@ -124,6 +129,19 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { ref.invalidate(votingRoundListProvider), child: ListView( children: [ + if (shareAttention) + const Padding( + padding: EdgeInsets.fromLTRB(12, 8, 12, 0), + child: Card( + child: Padding( + padding: EdgeInsets.all(12), + child: Text( + "Helper-share delivery is pending — it will retry " + "in the background while the round is open.", + ), + ), + ), + ), if (joinable.isNotEmpty) ...[ const Padding( padding: EdgeInsets.all(12), diff --git a/lib/pages/voting_status.dart b/lib/pages/voting_status.dart index f71cba68f..c489394e2 100644 --- a/lib/pages/voting_status.dart +++ b/lib/pages/voting_status.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:zkool/main.dart'; +import 'package:zkool/services/votechain_backoff.dart'; import 'package:zkool/src/rust/api/voting.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; @@ -87,6 +88,9 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { return "Casting votes"; case "shares": return "Submitting shares"; + case "retrying": + return "Retrying in ${job.retryInSeconds ?? 0}s " + "(attempt ${job.retryAttempt ?? 1} of $voteChainMaxAutoRetries)"; case "done": return job.doneLabel ?? "Submission complete"; case "error": @@ -102,15 +106,16 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { if (pinlock.value ?? false) return PinLock(); final job = ref.watch(votingSubmissionJobProvider(widget.roundId)); - final running = job.stage != "done" && job.stage != "error"; // Confirmed vote txs (per proposal), shown as evidence on the done state. + // A vote confirmed via commitment-tree recovery has no tx hash — it still + // counts as confirmed evidence. final confirmedVotes = (ref .watch(votingSessionProvider(widget.roundId)) .value ?.recovery ?.votes ?? const <VotingVoteRecovery>[]) - .where((v) => v.phase == "confirmed" && (v.txHash ?? "").isNotEmpty) + .where((v) => v.phase == "confirmed") .toList(); // Human-readable ballot evidence: proposal titles and option labels, // keyed by proposal id (not list position). @@ -135,7 +140,10 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { } return PopScope( - canPop: !running, + // All progress is durable and the resume plan re-enters any incomplete + // step on the next run, so leaving is safe in every stage except the + // two heavy ZK stages, where aborting mid-proof just wastes the work. + canPop: job.stage != "preparing" && job.stage != "proving", onPopInvokedWithResult: (didPop, _) async { if (didPop) return; if (_handlingLeave) return; @@ -226,7 +234,10 @@ class VotingStatusPageState extends ConsumerState<VotingStatusPage> { Padding( padding: const EdgeInsets.only(top: 4), child: SelectableText( - "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}", + v.txHash != null && v.txHash!.isNotEmpty + ? "${voteLabel(v)}\n${v.txHash} · tree ${v.vcTreePosition}" + : "${voteLabel(v)}\ntree ${v.vcTreePosition} · " + "verified in the commitment tree", textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall, ), diff --git a/lib/services/votechain_backoff.dart b/lib/services/votechain_backoff.dart new file mode 100644 index 000000000..6dd6c5b62 --- /dev/null +++ b/lib/services/votechain_backoff.dart @@ -0,0 +1,18 @@ +/// Delay before the next automatic retry of a transiently failed voting run. +/// +/// Deterministic (unlike the synchronizer's randomized backoff) so tests and +/// the status page can predict the retry schedule: 30 s, 60 s, then 120 s for +/// any later attempt. +Duration voteChainRetryDelay(int attempt) { + switch (attempt) { + case 1: + return const Duration(seconds: 30); + case 2: + return const Duration(seconds: 60); + default: + return const Duration(seconds: 120); + } +} + +/// Maximum automatic retries for a transiently failed voting run. +const voteChainMaxAutoRetries = 3; diff --git a/lib/services/votechain_classify.dart b/lib/services/votechain_classify.dart new file mode 100644 index 000000000..691878461 --- /dev/null +++ b/lib/services/votechain_classify.dart @@ -0,0 +1,47 @@ +import 'dart:convert'; + +/// How a 422 (or 4xx rejection body) from the vote chain should be handled. +enum ChainRejectionKind { + /// The chain rejected the submission because a nullifier it carries was + /// already spent — for a resubmission of identical wire bytes this means + /// the original transaction committed successfully (the client just never + /// learned its hash). + duplicateNullifier, + + /// Any other deterministic rejection; permanent, do not retry blindly. + other, +} + +/// Classifies a vote-chain rejection body. +/// +/// The vote-sdk surfaces duplicate nullifiers through CheckTx logs like +/// `nullifier already spent`; every other rejection is surfaced as-is. +ChainRejectionKind classifyVoteChainRejection(String body) { + final lower = body.toLowerCase(); + if (lower.contains("nullifier") && + (lower.contains("spent") || + lower.contains("spend") || + lower.contains("already"))) { + return ChainRejectionKind.duplicateNullifier; + } + return ChainRejectionKind.other; +} + +/// Extracts a tx hash from a vote-chain response body. +/// +/// Accepted forms: the `tx_hash` field of a JSON `{tx_hash, code, log}` +/// envelope, and the `tx_hash=...` fragment of the 502 +/// "broadcast outcome unknown after retries" message. +String? txHashFromVoteChainBody(String body) { + try { + final decoded = jsonDecode(body); + if (decoded is Map<String, dynamic>) { + final hash = decoded['tx_hash']; + if (hash is String && hash.isNotEmpty) return hash; + } + } on FormatException { + // Fall through to the substring form. + } + final match = RegExp(r"tx_hash=([0-9A-Fa-f]+)").firstMatch(body); + return match?.group(1); +} diff --git a/lib/services/votechain_confirmation.dart b/lib/services/votechain_confirmation.dart index ec32e7344..4f44330e7 100644 --- a/lib/services/votechain_confirmation.dart +++ b/lib/services/votechain_confirmation.dart @@ -42,3 +42,20 @@ VoteChainTxConfirmation? parseVoteChainTxConfirmation(String body) { height: height, ); } + +/// Extracts `{code, log}` from a 4xx/5xx chain response body for user-facing +/// error messages. Falls back to the raw body when it is not the +/// `{tx_hash, code, log}` envelope. +({int code, String log}) parseVoteChainRejection(String body) { + try { + final decoded = jsonDecode(body); + if (decoded is Map<String, dynamic>) { + final code = decoded['code'] is int ? decoded['code'] as int : -1; + final log = decoded['log'] is String ? decoded['log'] as String : ''; + return (code: code, log: log); + } + } on FormatException { + // Fall through to the raw-body form. + } + return (code: -1, log: body); +} diff --git a/lib/services/votechain_failover.dart b/lib/services/votechain_failover.dart new file mode 100644 index 000000000..901a25876 --- /dev/null +++ b/lib/services/votechain_failover.dart @@ -0,0 +1,132 @@ +import 'package:zkool/src/rust/api/voting.dart'; + +import 'votechain_classify.dart'; + +/// Raised when every candidate vote-chain server failed with a transport +/// error or an unresolved 5xx — a transient, retryable condition from the +/// caller's perspective. +class TransientVoteChainException implements Exception { + final String message; + + TransientVoteChainException(this.message); + + @override + String toString() => message; +} + +/// Raised when a re-broadcast was rejected because a nullifier it carries was +/// already spent on-chain: the original submission committed successfully but +/// its tx hash was never recorded locally. The caller reconciles the +/// confirmation from the commitment tree instead of failing the run. +class DuplicateNullifierOnResubmitException implements Exception { + final String message; + + DuplicateNullifierOnResubmitException(this.message); + + @override + String toString() => message; +} + +/// A per-URL vote-chain call: transport failures throw, completed HTTP +/// responses (any status) are returned as `VotingChainResponse`. +typedef VoteChainCall = Future<VotingChainResponse> Function(String baseUrl); + +/// Rotates a vote-chain call across the configured server list. +/// +/// Policy per candidate URL, in order: +/// - transport error → next candidate; +/// - 2xx / 4xx → final answer (404 "not found" and 422 "rejected" are +/// answers, not failures); +/// - 503 → honor `Retry-After` and retry the same URL up to `max503Retries` +/// times (the vote-sdk warms its verifier cache behind a 503 gate); +/// - 502 → an answer only when the body carries a tx hash (the vote-sdk's +/// "broadcast outcome unknown; tx_hash=..." envelope); otherwise next; +/// - any other 5xx → next candidate. +/// +/// The last URL that produced an answer is remembered per round and tried +/// first on the next run, so a recovered server is found without replaying +/// the outage. All candidates failing raises [TransientVoteChainException]. +class VoteChainFailover { + final List<String> allServers; + + /// Injectable sleep (tests pass a no-op). + final Future<void> Function(Duration duration) delay; + + final Map<String, String> _lastWorking = {}; + + VoteChainFailover({ + this.allServers = const [], + Future<void> Function(Duration duration)? delay, + }) : delay = delay ?? Future<void>.delayed; + + /// Runs [call] with failover across `baseUrls` (caller's preferred URL + /// first) plus [allServers]. + Future<VotingChainResponse> run({ + required List<String> baseUrls, + required String roundId, + required VoteChainCall call, + int max503Retries = 1, + }) async { + Object? lastError; + for (final url in orderedCandidates(baseUrls, roundId)) { + var retries = 0; + while (true) { + final VotingChainResponse res; + try { + res = await call(url); + } catch (e) { + lastError = e; + break; // transport failure: this server did not answer + } + final status = res.statusCode; + if (status >= 200 && status < 300) { + _lastWorking[roundId] = url; + return res; + } + if (status >= 400 && status < 500) { + // A definitive answer (404 not found, 422 rejected, 409 conflict). + _lastWorking[roundId] = url; + return res; + } + if (status == 502) { + if (txHashFromVoteChainBody(res.body) != null) { + _lastWorking[roundId] = url; + return res; + } + lastError = Exception('vote chain 502 from $url: ${res.body}'); + break; + } + if (status == 503 && retries < max503Retries) { + final wait = (res.retryAfterSecs?.toInt() ?? 2).clamp(1, 120); + await delay(Duration(seconds: wait)); + retries++; + continue; + } + lastError = Exception('vote chain HTTP $status from $url: ${res.body}'); + break; + } + } + throw TransientVoteChainException( + 'all vote chain servers failed (${orderedCandidates(baseUrls, roundId).length} tried): $lastError', + ); + } + + /// Candidate order: the round's last-working URL (when configured), the + /// caller's list, then the remaining configured servers; deduplicated. + List<String> orderedCandidates(List<String> baseUrls, String roundId) { + final ordered = <String>[]; + void add(String? url) { + if (url == null || url.isEmpty || ordered.contains(url)) return; + ordered.add(url); + } + + add(_lastWorking[roundId]); + for (final url in baseUrls) { + add(url); + } + for (final url in allServers) { + add(url); + } + return ordered; + } +} diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index e6f699391..a3cd66111 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -11,7 +11,7 @@ part 'voting.freezed.dart'; // These functions are ignored because they are not marked as `pub`: `config_switch_kind_string`, `fork_network_string`, `from_resolved`, `prepare_bundle`, `to_fork`, `votechain_proxy` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `VotingShareDelivery` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `assert_fields_are_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from`, `from` /// Creates and persists a fresh app-owned voting hotkey (hex stored secret). Future<String> votingHotkeyCreate({required Coin c}) => @@ -471,6 +471,80 @@ Future<VotingVoteConfirmation> votingConfirm( eventsJson: eventsJson, c: c); +/// Hex-encoded vote commitment leaf value for one committed vote, used to +/// locate the vote's commitment-tree leaf when the tx hash is unknown. +Future<String> votingVoteCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingVoteCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c); + +/// Hex-encoded cast-vote VAN output commitment for one committed vote (the +/// commitment-tree leaf appended immediately before the vote commitment). +Future<String> votingVoteVanCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingVoteVanCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c); + +/// Hex-encoded delegation VAN commitment (`gov_comm`) for a bundle, or `None` +/// when it was never persisted. Used to locate the delegation's tree leaf. +Future<String?> votingDelegationVanCommitmentHex( + {required String roundId, required int bundleIndex, required Coin c}) => + RustLib.instance.api.crateApiVotingVotingDelegationVanCommitmentHex( + roundId: roundId, bundleIndex: bundleIndex, c: c); + +/// Scans the round's commitment tree for a leaf matching `target_hex` and +/// returns its global position, or `None` when absent. +Future<BigInt?> votingTreeFindLeaf( + {required String roundId, + required String nodeUrl, + required String targetHex}) => + RustLib.instance.api.crateApiVotingVotingTreeFindLeaf( + roundId: roundId, nodeUrl: nodeUrl, targetHex: targetHex); + +/// Records a cast-vote confirmation whose evidence came from a +/// commitment-tree scan (no tx hash available). The vote's phase becomes +/// Confirmed so the resume plan proceeds to share submission. +Future<VotingTreeVoteConfirmation> votingRecoverConfirmVoteFromTree( + {required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRecoverConfirmVoteFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + vcTreePosition: vcTreePosition, + vanLeafPosition: vanLeafPosition, + c: c); + +/// Records a delegation confirmation recovered from a commitment-tree scan +/// (no tx hash available). The bundle's phase becomes Confirmed so voting can +/// proceed. +Future<void> votingRecoverConfirmDelegationFromTree( + {required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c}) => + RustLib.instance.api.crateApiVotingVotingRecoverConfirmDelegationFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + vanLeafPosition: vanLeafPosition, + c: c); + /// Lists rounds persisted in the voting DB for the current wallet. Future<List<VotingRoundInfo>> votingRounds({required Coin c}) => RustLib.instance.api.crateApiVotingVotingRounds(c: c); @@ -605,6 +679,7 @@ sealed class VotingChainResponse with _$VotingChainResponse { const factory VotingChainResponse({ required int statusCode, required String body, + BigInt? retryAfterSecs, }) = _VotingChainResponse; } @@ -961,6 +1036,15 @@ sealed class VotingSignedVoteCommitment with _$VotingSignedVoteCommitment { }) = _VotingSignedVoteCommitment; } +/// Confirmation evidence recovered from a commitment-tree scan. +@freezed +sealed class VotingTreeVoteConfirmation with _$VotingTreeVoteConfirmation { + const factory VotingTreeVoteConfirmation({ + required BigInt vcTreePosition, + int? vanLeafPosition, + }) = _VotingTreeVoteConfirmation; +} + @freezed sealed class VotingVanWitness with _$VotingVanWitness { const factory VotingVanWitness({ diff --git a/lib/src/rust/api/voting.freezed.dart b/lib/src/rust/api/voting.freezed.dart index e37783f8a..852e88a79 100644 --- a/lib/src/rust/api/voting.freezed.dart +++ b/lib/src/rust/api/voting.freezed.dart @@ -332,6 +332,7 @@ class __$VotingBallotIntentCopyWithImpl<$Res> mixin _$VotingChainResponse { int get statusCode; String get body; + BigInt? get retryAfterSecs; /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @@ -348,15 +349,18 @@ mixin _$VotingChainResponse { other is VotingChainResponse && (identical(other.statusCode, statusCode) || other.statusCode == statusCode) && - (identical(other.body, body) || other.body == body)); + (identical(other.body, body) || other.body == body) && + (identical(other.retryAfterSecs, retryAfterSecs) || + other.retryAfterSecs == retryAfterSecs)); } @override - int get hashCode => Object.hash(runtimeType, statusCode, body); + int get hashCode => + Object.hash(runtimeType, statusCode, body, retryAfterSecs); @override String toString() { - return 'VotingChainResponse(statusCode: $statusCode, body: $body)'; + return 'VotingChainResponse(statusCode: $statusCode, body: $body, retryAfterSecs: $retryAfterSecs)'; } } @@ -366,7 +370,7 @@ abstract mixin class $VotingChainResponseCopyWith<$Res> { VotingChainResponse value, $Res Function(VotingChainResponse) _then) = _$VotingChainResponseCopyWithImpl; @useResult - $Res call({int statusCode, String body}); + $Res call({int statusCode, String body, BigInt? retryAfterSecs}); } /// @nodoc @@ -384,6 +388,7 @@ class _$VotingChainResponseCopyWithImpl<$Res> $Res call({ Object? statusCode = null, Object? body = null, + Object? retryAfterSecs = freezed, }) { return _then(_self.copyWith( statusCode: null == statusCode @@ -394,6 +399,10 @@ class _$VotingChainResponseCopyWithImpl<$Res> ? _self.body : body // ignore: cast_nullable_to_non_nullable as String, + retryAfterSecs: freezed == retryAfterSecs + ? _self.retryAfterSecs + : retryAfterSecs // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } @@ -489,13 +498,14 @@ extension VotingChainResponsePatterns on VotingChainResponse { @optionalTypeArgs TResult maybeWhen<TResult extends Object?>( - TResult Function(int statusCode, String body)? $default, { + TResult Function(int statusCode, String body, BigInt? retryAfterSecs)? + $default, { required TResult orElse(), }) { final _that = this; switch (_that) { case _VotingChainResponse() when $default != null: - return $default(_that.statusCode, _that.body); + return $default(_that.statusCode, _that.body, _that.retryAfterSecs); case _: return orElse(); } @@ -516,12 +526,13 @@ extension VotingChainResponsePatterns on VotingChainResponse { @optionalTypeArgs TResult when<TResult extends Object?>( - TResult Function(int statusCode, String body) $default, + TResult Function(int statusCode, String body, BigInt? retryAfterSecs) + $default, ) { final _that = this; switch (_that) { case _VotingChainResponse(): - return $default(_that.statusCode, _that.body); + return $default(_that.statusCode, _that.body, _that.retryAfterSecs); } } @@ -539,12 +550,13 @@ extension VotingChainResponsePatterns on VotingChainResponse { @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>( - TResult? Function(int statusCode, String body)? $default, + TResult? Function(int statusCode, String body, BigInt? retryAfterSecs)? + $default, ) { final _that = this; switch (_that) { case _VotingChainResponse() when $default != null: - return $default(_that.statusCode, _that.body); + return $default(_that.statusCode, _that.body, _that.retryAfterSecs); case _: return null; } @@ -554,12 +566,15 @@ extension VotingChainResponsePatterns on VotingChainResponse { /// @nodoc class _VotingChainResponse implements VotingChainResponse { - const _VotingChainResponse({required this.statusCode, required this.body}); + const _VotingChainResponse( + {required this.statusCode, required this.body, this.retryAfterSecs}); @override final int statusCode; @override final String body; + @override + final BigInt? retryAfterSecs; /// Create a copy of VotingChainResponse /// with the given fields replaced by the non-null parameter values. @@ -577,15 +592,18 @@ class _VotingChainResponse implements VotingChainResponse { other is _VotingChainResponse && (identical(other.statusCode, statusCode) || other.statusCode == statusCode) && - (identical(other.body, body) || other.body == body)); + (identical(other.body, body) || other.body == body) && + (identical(other.retryAfterSecs, retryAfterSecs) || + other.retryAfterSecs == retryAfterSecs)); } @override - int get hashCode => Object.hash(runtimeType, statusCode, body); + int get hashCode => + Object.hash(runtimeType, statusCode, body, retryAfterSecs); @override String toString() { - return 'VotingChainResponse(statusCode: $statusCode, body: $body)'; + return 'VotingChainResponse(statusCode: $statusCode, body: $body, retryAfterSecs: $retryAfterSecs)'; } } @@ -597,7 +615,7 @@ abstract mixin class _$VotingChainResponseCopyWith<$Res> __$VotingChainResponseCopyWithImpl; @override @useResult - $Res call({int statusCode, String body}); + $Res call({int statusCode, String body, BigInt? retryAfterSecs}); } /// @nodoc @@ -615,6 +633,7 @@ class __$VotingChainResponseCopyWithImpl<$Res> $Res call({ Object? statusCode = null, Object? body = null, + Object? retryAfterSecs = freezed, }) { return _then(_VotingChainResponse( statusCode: null == statusCode @@ -625,6 +644,10 @@ class __$VotingChainResponseCopyWithImpl<$Res> ? _self.body : body // ignore: cast_nullable_to_non_nullable as String, + retryAfterSecs: freezed == retryAfterSecs + ? _self.retryAfterSecs + : retryAfterSecs // ignore: cast_nullable_to_non_nullable + as BigInt?, )); } } @@ -12240,6 +12263,312 @@ class __$VotingSignedVoteCommitmentCopyWithImpl<$Res> } } +/// @nodoc +mixin _$VotingTreeVoteConfirmation { + BigInt get vcTreePosition; + int? get vanLeafPosition; + + /// Create a copy of VotingTreeVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $VotingTreeVoteConfirmationCopyWith<VotingTreeVoteConfirmation> + get copyWith => + _$VotingTreeVoteConfirmationCopyWithImpl<VotingTreeVoteConfirmation>( + this as VotingTreeVoteConfirmation, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is VotingTreeVoteConfirmation && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash(runtimeType, vcTreePosition, vanLeafPosition); + + @override + String toString() { + return 'VotingTreeVoteConfirmation(vcTreePosition: $vcTreePosition, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class $VotingTreeVoteConfirmationCopyWith<$Res> { + factory $VotingTreeVoteConfirmationCopyWith(VotingTreeVoteConfirmation value, + $Res Function(VotingTreeVoteConfirmation) _then) = + _$VotingTreeVoteConfirmationCopyWithImpl; + @useResult + $Res call({BigInt vcTreePosition, int? vanLeafPosition}); +} + +/// @nodoc +class _$VotingTreeVoteConfirmationCopyWithImpl<$Res> + implements $VotingTreeVoteConfirmationCopyWith<$Res> { + _$VotingTreeVoteConfirmationCopyWithImpl(this._self, this._then); + + final VotingTreeVoteConfirmation _self; + final $Res Function(VotingTreeVoteConfirmation) _then; + + /// Create a copy of VotingTreeVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? vcTreePosition = null, + Object? vanLeafPosition = freezed, + }) { + return _then(_self.copyWith( + vcTreePosition: null == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + vanLeafPosition: freezed == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// Adds pattern-matching-related methods to [VotingTreeVoteConfirmation]. +extension VotingTreeVoteConfirmationPatterns on VotingTreeVoteConfirmation { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap<TResult extends Object?>( + TResult Function(_VotingTreeVoteConfirmation value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map<TResult extends Object?>( + TResult Function(_VotingTreeVoteConfirmation value) $default, + ) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation(): + return $default(_that); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull<TResult extends Object?>( + TResult? Function(_VotingTreeVoteConfirmation value)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen<TResult extends Object?>( + TResult Function(BigInt vcTreePosition, int? vanLeafPosition)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation() when $default != null: + return $default(_that.vcTreePosition, _that.vanLeafPosition); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when<TResult extends Object?>( + TResult Function(BigInt vcTreePosition, int? vanLeafPosition) $default, + ) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation(): + return $default(_that.vcTreePosition, _that.vanLeafPosition); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull<TResult extends Object?>( + TResult? Function(BigInt vcTreePosition, int? vanLeafPosition)? $default, + ) { + final _that = this; + switch (_that) { + case _VotingTreeVoteConfirmation() when $default != null: + return $default(_that.vcTreePosition, _that.vanLeafPosition); + case _: + return null; + } + } +} + +/// @nodoc + +class _VotingTreeVoteConfirmation implements VotingTreeVoteConfirmation { + const _VotingTreeVoteConfirmation( + {required this.vcTreePosition, this.vanLeafPosition}); + + @override + final BigInt vcTreePosition; + @override + final int? vanLeafPosition; + + /// Create a copy of VotingTreeVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$VotingTreeVoteConfirmationCopyWith<_VotingTreeVoteConfirmation> + get copyWith => __$VotingTreeVoteConfirmationCopyWithImpl< + _VotingTreeVoteConfirmation>(this, _$identity); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _VotingTreeVoteConfirmation && + (identical(other.vcTreePosition, vcTreePosition) || + other.vcTreePosition == vcTreePosition) && + (identical(other.vanLeafPosition, vanLeafPosition) || + other.vanLeafPosition == vanLeafPosition)); + } + + @override + int get hashCode => Object.hash(runtimeType, vcTreePosition, vanLeafPosition); + + @override + String toString() { + return 'VotingTreeVoteConfirmation(vcTreePosition: $vcTreePosition, vanLeafPosition: $vanLeafPosition)'; + } +} + +/// @nodoc +abstract mixin class _$VotingTreeVoteConfirmationCopyWith<$Res> + implements $VotingTreeVoteConfirmationCopyWith<$Res> { + factory _$VotingTreeVoteConfirmationCopyWith( + _VotingTreeVoteConfirmation value, + $Res Function(_VotingTreeVoteConfirmation) _then) = + __$VotingTreeVoteConfirmationCopyWithImpl; + @override + @useResult + $Res call({BigInt vcTreePosition, int? vanLeafPosition}); +} + +/// @nodoc +class __$VotingTreeVoteConfirmationCopyWithImpl<$Res> + implements _$VotingTreeVoteConfirmationCopyWith<$Res> { + __$VotingTreeVoteConfirmationCopyWithImpl(this._self, this._then); + + final _VotingTreeVoteConfirmation _self; + final $Res Function(_VotingTreeVoteConfirmation) _then; + + /// Create a copy of VotingTreeVoteConfirmation + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? vcTreePosition = null, + Object? vanLeafPosition = freezed, + }) { + return _then(_VotingTreeVoteConfirmation( + vcTreePosition: null == vcTreePosition + ? _self.vcTreePosition + : vcTreePosition // ignore: cast_nullable_to_non_nullable + as BigInt, + vanLeafPosition: freezed == vanLeafPosition + ? _self.vanLeafPosition + : vanLeafPosition // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + /// @nodoc mixin _$VotingVanWitness { List<Uint8List> get authPath; diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 938a406e5..75e00888e 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -95,7 +95,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -1211184662; + int get rustContentHash => -353494689; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -740,6 +740,9 @@ abstract class RustLibApi extends BaseApi { required String eventsJson, required Coin c}); + Future<String?> crateApiVotingVotingDelegationVanCommitmentHex( + {required String roundId, required int bundleIndex, required Coin c}); + Future<String?> crateApiVotingVotingDraftsLoad( {required String roundId, required Coin c}); @@ -780,6 +783,21 @@ abstract class RustLibApi extends BaseApi { required String shareDeliveriesJson, required Coin c}); + Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree( + {required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c}); + + Future<VotingTreeVoteConfirmation> + crateApiVotingVotingRecoverConfirmVoteFromTree( + {required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c}); + Future<VotingRoundRecovery> crateApiVotingVotingRecovery( {required String roundId, required Coin c}); @@ -871,12 +889,29 @@ abstract class RustLibApi extends BaseApi { Future<int> crateApiVotingVotingSyncTree( {required String roundId, required String voteNodeUrl, required Coin c}); + Future<BigInt?> crateApiVotingVotingTreeFindLeaf( + {required String roundId, + required String nodeUrl, + required String targetHex}); + Future<VotingVanWitness> crateApiVotingVotingVanWitness( {required String roundId, required int bundleIndex, required String voteNodeUrl, required Coin c}); + Future<String> crateApiVotingVotingVoteCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}); + + Future<String> crateApiVotingVotingVoteVanCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}); + Future<String> crateApiVotingVotingVoteWireJson( {required String roundId, required int bundleIndex, @@ -6906,6 +6941,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ], ); + @override + Future<String?> crateApiVotingVotingDelegationVanCommitmentHex( + {required String roundId, required int bundleIndex, required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 202, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingDelegationVanCommitmentHexConstMeta, + argValues: [roundId, bundleIndex, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingDelegationVanCommitmentHexConstMeta => + const TaskConstMeta( + debugName: "voting_delegation_van_commitment_hex", + argNames: ["roundId", "bundleIndex", "c"], + ); + @override Future<String?> crateApiVotingVotingDraftsLoad( {required String roundId, required Coin c}) { @@ -6916,7 +6981,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 202, port: port_); + funcId: 203, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -6946,7 +7011,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(draftsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 203, port: port_); + funcId: 204, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6975,7 +7040,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(snapshotHeight, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 204, port: port_); + funcId: 205, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -7002,7 +7067,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 205, port: port_); + funcId: 206, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7029,7 +7094,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 206, port: port_); + funcId: 207, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7065,7 +7130,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txHash, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 207, port: port_); + funcId: 208, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7099,7 +7164,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 208, port: port_); + funcId: 209, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_payloads, @@ -7131,7 +7196,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_loose(proposalIds, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 209, port: port_); + funcId: 210, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_plan, @@ -7170,7 +7235,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(shareDeliveriesJson, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 210, port: port_); + funcId: 211, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7205,6 +7270,95 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ], ); + @override + Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree( + {required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(vanLeafPosition, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 212, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: + kCrateApiVotingVotingRecoverConfirmDelegationFromTreeConstMeta, + argValues: [roundId, bundleIndex, vanLeafPosition, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta + get kCrateApiVotingVotingRecoverConfirmDelegationFromTreeConstMeta => + const TaskConstMeta( + debugName: "voting_recover_confirm_delegation_from_tree", + argNames: ["roundId", "bundleIndex", "vanLeafPosition", "c"], + ); + + @override + Future<VotingTreeVoteConfirmation> + crateApiVotingVotingRecoverConfirmVoteFromTree( + {required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_u_64(vcTreePosition, serializer); + sse_encode_opt_box_autoadd_u_32(vanLeafPosition, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 213, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_voting_tree_vote_confirmation, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingRecoverConfirmVoteFromTreeConstMeta, + argValues: [ + roundId, + bundleIndex, + proposalId, + vcTreePosition, + vanLeafPosition, + c + ], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingRecoverConfirmVoteFromTreeConstMeta => + const TaskConstMeta( + debugName: "voting_recover_confirm_vote_from_tree", + argNames: [ + "roundId", + "bundleIndex", + "proposalId", + "vcTreePosition", + "vanLeafPosition", + "c" + ], + ); + @override Future<VotingRoundRecovery> crateApiVotingVotingRecovery( {required String roundId, required Coin c}) { @@ -7215,7 +7369,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 211, port: port_); + funcId: 214, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_recovery, @@ -7244,7 +7398,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 212, port: port_); + funcId: 215, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7273,7 +7427,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 213, port: port_); + funcId: 216, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7311,7 +7465,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(nullifierImtRoot, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 214, port: port_); + funcId: 217, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7352,7 +7506,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 215, port: port_); + funcId: 218, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_info, @@ -7380,7 +7534,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(roundIds, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 216, port: port_); + funcId: 219, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_session, @@ -7418,7 +7572,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 217, port: port_); + funcId: 220, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7463,7 +7617,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 218, port: port_); + funcId: 221, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7506,7 +7660,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + funcId: 222, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7535,7 +7689,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + funcId: 223, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_submission_payload, @@ -7575,7 +7729,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + funcId: 224, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7631,7 +7785,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + funcId: 225, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_plan_item, @@ -7687,7 +7841,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + funcId: 226, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7733,7 +7887,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 224, port: port_); + funcId: 227, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7773,7 +7927,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 225, port: port_); + funcId: 228, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7819,7 +7973,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 226, port: port_); + funcId: 229, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7838,6 +7992,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["roundId", "voteNodeUrl", "c"], ); + @override + Future<BigInt?> crateApiVotingVotingTreeFindLeaf( + {required String roundId, + required String nodeUrl, + required String targetHex}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_String(nodeUrl, serializer); + sse_encode_String(targetHex, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 230, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_u_64, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingTreeFindLeafConstMeta, + argValues: [roundId, nodeUrl, targetHex], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingTreeFindLeafConstMeta => + const TaskConstMeta( + debugName: "voting_tree_find_leaf", + argNames: ["roundId", "nodeUrl", "targetHex"], + ); + @override Future<VotingVanWitness> crateApiVotingVotingVanWitness( {required String roundId, @@ -7853,7 +8039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 227, port: port_); + funcId: 231, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -7872,6 +8058,74 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["roundId", "bundleIndex", "voteNodeUrl", "c"], ); + @override + Future<String> crateApiVotingVotingVoteCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 232, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingVoteCommitmentHexConstMeta, + argValues: [roundId, bundleIndex, proposalId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingVoteCommitmentHexConstMeta => + const TaskConstMeta( + debugName: "voting_vote_commitment_hex", + argNames: ["roundId", "bundleIndex", "proposalId", "c"], + ); + + @override + Future<String> crateApiVotingVotingVoteVanCommitmentHex( + {required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(roundId, serializer); + sse_encode_u_32(bundleIndex, serializer); + sse_encode_u_32(proposalId, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 233, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiVotingVotingVoteVanCommitmentHexConstMeta, + argValues: [roundId, bundleIndex, proposalId, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiVotingVotingVoteVanCommitmentHexConstMeta => + const TaskConstMeta( + debugName: "voting_vote_van_commitment_hex", + argNames: ["roundId", "bundleIndex", "proposalId", "c"], + ); + @override Future<String> crateApiVotingVotingVoteWireJson( {required String roundId, @@ -7887,7 +8141,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 228, port: port_); + funcId: 234, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -9704,11 +9958,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { VotingChainResponse dco_decode_voting_chain_response(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; - if (arr.length != 2) - throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + if (arr.length != 3) + throw Exception('unexpected arr length: expect 3 but see ${arr.length}'); return VotingChainResponse( statusCode: dco_decode_u_16(arr[0]), body: dco_decode_String(arr[1]), + retryAfterSecs: dco_decode_opt_box_autoadd_u_64(arr[2]), ); } @@ -10161,6 +10416,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( + dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List<dynamic>; + if (arr.length != 2) + throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); + return VotingTreeVoteConfirmation( + vcTreePosition: dco_decode_u_64(arr[0]), + vanLeafPosition: dco_decode_opt_box_autoadd_u_32(arr[1]), + ); + } + @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -12428,7 +12696,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs var var_statusCode = sse_decode_u_16(deserializer); var var_body = sse_decode_String(deserializer); - return VotingChainResponse(statusCode: var_statusCode, body: var_body); + var var_retryAfterSecs = sse_decode_opt_box_autoadd_u_64(deserializer); + return VotingChainResponse( + statusCode: var_statusCode, + body: var_body, + retryAfterSecs: var_retryAfterSecs); } @protected @@ -12925,6 +13197,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { commitmentBundleJson: var_commitmentBundleJson); } + @protected + VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_vcTreePosition = sse_decode_u_64(deserializer); + var var_vanLeafPosition = sse_decode_opt_box_autoadd_u_32(deserializer); + return VotingTreeVoteConfirmation( + vcTreePosition: var_vcTreePosition, + vanLeafPosition: var_vanLeafPosition); + } + @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -14896,6 +15179,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.statusCode, serializer); sse_encode_String(self.body, serializer); + sse_encode_opt_box_autoadd_u_64(self.retryAfterSecs, serializer); } @protected @@ -15230,6 +15514,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(self.commitmentBundleJson, serializer); } + @protected + void sse_encode_voting_tree_vote_confirmation( + VotingTreeVoteConfirmation self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_64(self.vcTreePosition, serializer); + sse_encode_opt_box_autoadd_u_32(self.vanLeafPosition, serializer); + } + @protected void sse_encode_voting_van_witness( VotingVanWitness self, SseSerializer serializer) { diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 48d6103cc..fd5cdffb6 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -745,6 +745,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( dynamic raw); + @protected + VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( + dynamic raw); + @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); @@ -1509,6 +1513,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( SseDeserializer deserializer); + @protected + VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( + SseDeserializer deserializer); + @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); @@ -2311,6 +2319,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_signed_vote_commitment( VotingSignedVoteCommitment self, SseSerializer serializer); + @protected + void sse_encode_voting_tree_vote_confirmation( + VotingTreeVoteConfirmation self, SseSerializer serializer); + @protected void sse_encode_voting_van_witness( VotingVanWitness self, SseSerializer serializer); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 439dfe012..fbeaa8738 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -747,6 +747,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( dynamic raw); + @protected + VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( + dynamic raw); + @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); @@ -1511,6 +1515,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( SseDeserializer deserializer); + @protected + VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( + SseDeserializer deserializer); + @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); @@ -2313,6 +2321,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { void sse_encode_voting_signed_vote_commitment( VotingSignedVoteCommitment self, SseSerializer serializer); + @protected + void sse_encode_voting_tree_vote_confirmation( + VotingTreeVoteConfirmation self, SseSerializer serializer); + @protected void sse_encode_voting_van_witness( VotingVanWitness self, SseSerializer serializer); diff --git a/lib/store.dart b/lib/store.dart index b07485439..3eecdc802 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -14,7 +14,10 @@ import 'package:flutter/material.dart'; import 'package:zkool/main.dart'; import 'package:zkool/router.dart'; import 'package:zkool/services/block_height_service.dart'; +import 'package:zkool/services/votechain_backoff.dart'; +import 'package:zkool/services/votechain_classify.dart'; import 'package:zkool/services/votechain_confirmation.dart'; +import 'package:zkool/services/votechain_failover.dart'; import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/coin.dart'; import 'package:zkool/src/rust/api/contacts.dart'; @@ -1569,7 +1572,7 @@ class VotingSubmissionGuard extends _$VotingSubmissionGuard { @freezed sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { factory VotingSubmissionJobState({ - required String stage, // idle|preparing|proving|submitting|confirming|voting|shares|done|error + required String stage, // idle|preparing|proving|submitting|confirming|voting|shares|retrying|done|error required double progress, String? error, /// Voting weight (zatoshi) delegated by the prepared bundle, shown in @@ -1582,6 +1585,10 @@ sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { int? confirmHeight, /// Honest "done" headline describing what THIS run actually completed. String? doneLabel, + /// Current automatic retry of a transiently failed run (1-based). + int? retryAttempt, + /// Seconds until the next automatic retry fires. + int? retryInSeconds, }) = _VotingSubmissionJobState; } @@ -1592,11 +1599,8 @@ sealed class VotingSubmissionJobState with _$VotingSubmissionJobState { /// run (`delegate` vs `poll_delegation`), never re-broadcasting a recorded tx. @Riverpod(keepAlive: true) class VotingSubmissionJob extends _$VotingSubmissionJob { - Timer? _shareTimer; - @override VotingSubmissionJobState build(String roundId) { - ref.onDispose(() => _shareTimer?.cancel()); return VotingSubmissionJobState(stage: "idle", progress: 0); } @@ -1617,65 +1621,104 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { if (state.stage != "idle" && state.stage != "error" && state.stage != "done") { - return; // already running + return; // already running (or waiting to retry) } - state = state.copyWith(stage: "running", progress: 0, error: null); + state = state.copyWith( + stage: "running", + progress: 0, + error: null, + retryAttempt: null, + retryInSeconds: null, + ); ref.read(votingSubmissionGuardProvider.notifier).setActive(true); - try { - final delegated = await _runDelegation( - chainUrl: chainUrl, - pirServerUrl: pirServerUrl, - pirLayout: pirLayout, - roundParamsJson: roundParamsJson, - roundName: roundName, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl, - ); - final voted = await _runVotes( - chainUrl: chainUrl, - voteNodeUrl: voteNodeUrl, - ); - // The vote chain servers double as helper (share) servers; the voting - // flow never passes shareServerUrls, so fall back to the configured - // vote servers (mirrors vizor's context.config.voteServers). - final shareUrls = await _effectiveShareServerUrls(shareServerUrls); - // The voting pages never pass ceremonyStart/voteEnd either — resolve - // them from the chain round status so the share plan can schedule. - var effectiveCeremony = ceremonyStart; - var effectiveVoteEnd = voteEnd; - if (effectiveCeremony == 0 || effectiveVoteEnd == null) { - final timing = await _roundShareTiming(chainUrl: chainUrl); - if (timing != null) { - effectiveCeremony = timing.ceremonyStart; - effectiveVoteEnd = timing.voteEnd; + // Every step below is plan-driven and idempotent, so re-running the body + // after a transient failure is always safe: recorded state is re-read and + // the plan decides what still needs doing. Transient failures retry with + // backoff; deterministic rejections fail fast to the error stage. + var attempt = 0; + while (true) { + try { + final chainUrls = await _effectiveChainUrls(chainUrl); + final failover = VoteChainFailover(allServers: chainUrls); + final delegated = await _runDelegation( + chainUrls: chainUrls, + failover: failover, + pirServerUrl: pirServerUrl, + pirLayout: pirLayout, + roundParamsJson: roundParamsJson, + roundName: roundName, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + ); + final voted = await _runVotes( + chainUrls: chainUrls, + failover: failover, + voteNodeUrl: voteNodeUrl, + ); + // The vote chain servers double as helper (share) servers; the voting + // flow never passes shareServerUrls, so fall back to the configured + // vote servers (mirrors vizor's context.config.voteServers). + final shareUrls = await _effectiveShareServerUrls(shareServerUrls); + // The voting pages never pass ceremonyStart/voteEnd either — resolve + // them from the chain round status so the share plan can schedule. + var effectiveCeremony = ceremonyStart; + var effectiveVoteEnd = voteEnd; + if (effectiveCeremony == 0 || effectiveVoteEnd == null) { + final timing = + await _roundShareTiming(chainUrls: chainUrls, failover: failover); + if (timing != null) { + effectiveCeremony = timing.ceremonyStart; + effectiveVoteEnd = timing.voteEnd; + } } + final shared = await _submitShares( + ceremonyStart: effectiveCeremony, + voteEnd: effectiveVoteEnd, + shareServerUrls: shareUrls, + singleShare: singleShare, + ); + final String doneLabel; + if (delegated) { + doneLabel = "Delegation confirmed"; + } else if (voted) { + doneLabel = "Votes submitted"; + } else if (shared) { + doneLabel = "Shares submitted"; + } else { + doneLabel = await _remainingLabel(); + } + state = state.copyWith(stage: "done", progress: 1, doneLabel: doneLabel); + ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + // The round is now recorded locally and its plan advanced; refresh the + // voting page so the tile leaves "Join" and shows the real status + // without a manual refresh. + ref.invalidate(votingRoundListProvider); + ref.invalidate(votingSessionProvider(roundId)); + return; + } on TransientVoteChainException catch (e) { + attempt++; + if (attempt > voteChainMaxAutoRetries) { + state = state.copyWith( + stage: "error", + error: e.toString(), + retryAttempt: null, + retryInSeconds: null, + ); + ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + return; + } + final delay = voteChainRetryDelay(attempt); + state = state.copyWith( + stage: "retrying", + retryAttempt: attempt, + retryInSeconds: delay.inSeconds, + ); + await Future<void>.delayed(delay); + } on Exception catch (e) { + state = state.copyWith(stage: "error", error: e.toString()); + ref.read(votingSubmissionGuardProvider.notifier).setActive(false); + return; } - final shared = await _submitShares( - ceremonyStart: effectiveCeremony, - voteEnd: effectiveVoteEnd, - shareServerUrls: shareUrls, - singleShare: singleShare, - ); - final String doneLabel; - if (delegated) { - doneLabel = "Delegation confirmed"; - } else if (voted) { - doneLabel = "Votes submitted"; - } else if (shared) { - doneLabel = "Shares submitted"; - } else { - doneLabel = await _remainingLabel(); - } - state = state.copyWith(stage: "done", progress: 1, doneLabel: doneLabel); - ref.read(votingSubmissionGuardProvider.notifier).setActive(false); - // The round is now recorded locally and its plan advanced; refresh the - // voting page so the tile leaves "Join" and shows the real status - // without a manual refresh. - ref.invalidate(votingRoundListProvider); - ref.invalidate(votingSessionProvider(roundId)); - } on Exception catch (e) { - state = state.copyWith(stage: "error", error: e.toString()); - ref.read(votingSubmissionGuardProvider.notifier).setActive(false); } } @@ -1683,10 +1726,27 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { state = VotingSubmissionJobState(stage: "idle", progress: 0); } + /// The vote chain front the caller chose first, followed by the remaining + /// configured vote servers — the failover candidate list for chain calls. + Future<List<String>> _effectiveChainUrls(String chainUrl) async { + final urls = <String>[]; + if (chainUrl.isNotEmpty) urls.add(chainUrl); + try { + final config = await ref.read(votingConfigProvider.future); + for (final s in config?.voteServers ?? const <VotingServiceEndpoint>[]) { + if (!urls.contains(s.url)) urls.add(s.url); + } + } on Exception { + // Config unavailable: failover degrades to the single passed URL. + } + return urls; + } + /// Runs the delegation steps for this round; returns true when a delegation /// was confirmed in this run (fresh broadcast or recorded-hash poll). Future<bool> _runDelegation({ - required String chainUrl, + required List<String> chainUrls, + required VoteChainFailover failover, required String pirServerUrl, VotingPirLayout? pirLayout, String? roundParamsJson, @@ -1787,29 +1847,37 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } state = state.copyWith(stage: "submitting"); - final res = await votechainSubmitDelegation( - baseUrl: chainUrl, - submissionJson: wireJson, - c: c, + final res = await failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) => votechainSubmitDelegation( + baseUrl: u, + submissionJson: wireJson, + c: c, + ), ); if (res.statusCode == 422) { throw AnyhowException( "Delegation rejected by the vote chain: ${res.body}", ); } + final submittedHash = txHashFromVoteChainBody(res.body) ?? ""; + final rejection = parseVoteChainRejection(res.body); if (res.statusCode < 200 || res.statusCode >= 300) { + // A 502 "broadcast outcome unknown" body carries the deterministic + // tx hash: the tx may have landed — record it and let confirmation + // polling learn the truth. Any other non-2xx without a hash fails. + if (submittedHash.isEmpty) { + throw AnyhowException( + "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + } else if (rejection.code > 0 || submittedHash.isEmpty) { throw AnyhowException( - "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", - ); - } - final result = jsonDecode(res.body) as Map<String, dynamic>; - txHash = result['tx_hash'] as String? ?? ""; - final code = result['code'] as int? ?? -1; - if (code != 0 || txHash.isEmpty) { - throw AnyhowException( - "Vote chain rejected the delegation: ${result['log'] ?? res.body}", + "Vote chain rejected the delegation: ${rejection.log}", ); } + txHash = submittedHash; await delegationMarkSubmitted( roundId: roundId, @@ -1832,27 +1900,76 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } state = state.copyWith(stage: "confirming"); - final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash!); - await delegationConfirm( - roundId: roundId, - bundleIndex: bundleIndex, - txHash: txHash, - eventsJson: conf.eventsJson, - c: c, - ); - state = state.copyWith(txHash: txHash, confirmHeight: conf.height); + final String recordedHash = txHash!; + int? confirmHeight; + try { + final conf = await _pollTxConfirmationWithFallback( + chainUrls: chainUrls, + failover: failover, + txHash: recordedHash, + wireJson: () async => + await delegationWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ) ?? + "", + rebroadcast: () => failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) async { + final wire = await delegationWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ); + if (wire == null || wire.isEmpty) { + throw AnyhowException( + "No delegation wire JSON to re-broadcast " + "round $roundId bundle $bundleIndex", + ); + } + return votechainSubmitDelegation( + baseUrl: u, + submissionJson: wire, + c: c, + ); + }, + ), + markSubmitted: (h) => delegationMarkSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: h, + c: c, + ), + ); + confirmHeight = conf.height; + await delegationConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: recordedHash, + eventsJson: conf.eventsJson, + c: c, + ); + } on DuplicateNullifierOnResubmitException { + // The delegation committed on-chain but its hash was never recorded + // locally; recover the VAN leaf position from the commitment tree. + await _reconcileDelegation( + chainUrls: chainUrls, + bundleIndex: bundleIndex, + ); + } + state = state.copyWith(txHash: recordedHash, confirmHeight: confirmHeight); await ref.read(votingSessionProvider(roundId).notifier).refresh(); // The done state must be backed by the fork's recorded confirmation: - // verify the bundle reads back as confirmed (tx hash + VAN leaf) before - // claiming success — a stale or partial state must not show - // "Delegation confirmed". + // verify the bundle reads back as confirmed (tx hash or a + // commitment-tree-recovered VAN leaf) before claiming success — a stale + // or partial state must not show "Delegation confirmed". final verified = await ref.read(votingSessionProvider(roundId).future); final status = verified.plan?.delegationStatuses .where((s) => s.bundleIndex == bundleIndex) .firstOrNull; - if (status == null || - status.phase != "confirmed" || - (status.txHash ?? "").isEmpty) { + if (status == null || status.phase != "confirmed") { throw AnyhowException( "Delegation confirmation was not recorded for " "round $roundId bundle $bundleIndex", @@ -1908,14 +2025,24 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { /// them, and the share plan needs both to schedule submissions). Returns /// null when the fetch fails or the fields are missing. Future<({int ceremonyStart, int voteEnd})?> _roundShareTiming({ - required String chainUrl, + required List<String> chainUrls, + required VoteChainFailover failover, }) async { final c = coinContext.coin; - final res = await votechainRoundStatus( - baseUrl: chainUrl, - roundId: roundId, - c: c, - ); + final VotingChainResponse res; + try { + res = await failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) => votechainRoundStatus( + baseUrl: u, + roundId: roundId, + c: c, + ), + ); + } on TransientVoteChainException { + return null; + } if (res.statusCode < 200 || res.statusCode >= 300) return null; final body = jsonDecode(res.body) as Map<String, dynamic>; final round = body['round'] as Map<String, dynamic>? ?? {}; @@ -2016,28 +2143,202 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { /// Polls the vote chain until the tx is included in a block (HTTP 200 with /// a positive `height`), returning the parsed confirmation. - Future<VoteChainTxConfirmation> _pollTxConfirmation({ - required String chainUrl, + /// + /// A recorded hash whose tx never confirms is re-broadcast with + /// byte-identical wire and polling continues: the chain derives the tx hash + /// from the payload, so the recorded hash stays valid, and server-side + /// dedup makes the re-broadcast harmless when the tx is merely slow. This + /// recovers a server crash that lost an accepted tx from its in-memory + /// mempool. A duplicate-nullifier 422 on the re-broadcast means the tx + /// committed successfully without the client learning its hash — the + /// caller reconciles from the commitment tree via + /// [DuplicateNullifierOnResubmitException]. + Future<VoteChainTxConfirmation> _pollTxConfirmationWithFallback({ + required List<String> chainUrls, + required VoteChainFailover failover, required String txHash, + required Future<String> Function() wireJson, + required Future<VotingChainResponse> Function() rebroadcast, + required Future<void> Function(String txHash) markSubmitted, }) async { final c = coinContext.coin; - for (var attempt = 0; attempt < 45; attempt++) { - final res = await votechainTxConfirmation( - baseUrl: chainUrl, - txHash: txHash, - c: c, + Future<VoteChainTxConfirmation?> pollWindow() async { + for (var attempt = 0; attempt < 45; attempt++) { + final res = await failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) => votechainTxConfirmation( + baseUrl: u, + txHash: txHash, + c: c, + ), + ); + if (res.statusCode == 200) { + final conf = parseVoteChainTxConfirmation(res.body); + if (conf != null) return conf; + } else if (res.statusCode == 422) { + // Included in a block but its execution failed — permanent. + final rejection = parseVoteChainRejection(res.body); + throw AnyhowException( + "The vote chain included tx $txHash but its execution " + "failed: ${rejection.log}", + ); + } + await Future<void>.delayed(const Duration(seconds: 2)); + } + return null; + } + + final first = await pollWindow(); + if (first != null) return first; + + final rebuilt = await wireJson(); + if (rebuilt.isEmpty) { + throw AnyhowException( + "No wire JSON available to re-broadcast tx $txHash", ); - if (res.statusCode == 200) { - final conf = parseVoteChainTxConfirmation(res.body); - if (conf != null) return conf; + } + final res = await rebroadcast(); + if (res.statusCode == 422) { + final rejection = parseVoteChainRejection(res.body); + if (classifyVoteChainRejection(res.body) == + ChainRejectionKind.duplicateNullifier) { + throw DuplicateNullifierOnResubmitException( + "The vote chain says a nullifier in the re-broadcast of $txHash " + "was already spent: the submission committed on-chain but its " + "confirmation was never recorded locally. ${rejection.log}", + ); } - await Future<void>.delayed(const Duration(seconds: 2)); + throw AnyhowException( + "Vote chain rejected the re-broadcast of $txHash: ${rejection.log}", + ); } - throw AnyhowException( + if (res.statusCode < 200 || res.statusCode >= 300) { + throw TransientVoteChainException( + "Re-broadcast of $txHash failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + final rebroadcastHash = txHashFromVoteChainBody(res.body) ?? ""; + final code = parseVoteChainRejection(res.body).code; + if (code > 0) { + throw AnyhowException( + "Vote chain rejected the re-broadcast of $txHash: " + "${parseVoteChainRejection(res.body).log}", + ); + } + if (rebroadcastHash.isNotEmpty && rebroadcastHash != txHash) { + throw AnyhowException( + "Vote chain returned tx hash $rebroadcastHash for a byte-identical " + "re-broadcast of $txHash — refusing to record a mismatched hash", + ); + } + await markSubmitted(txHash); + + final second = await pollWindow(); + if (second != null) return second; + throw TransientVoteChainException( "Timed out waiting for tx $txHash to confirm", ); } + /// Recovers a delegation whose nullifier is spent on-chain but whose tx + /// hash was never recorded locally: locate the delegation's VAN commitment + /// (`gov_comm`) in the commitment tree and record the confirmation from the + /// recovered leaf position. + Future<void> _reconcileDelegation({ + required List<String> chainUrls, + required int bundleIndex, + }) async { + final c = coinContext.coin; + final vanHex = await votingDelegationVanCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ); + if (vanHex == null || vanHex.isEmpty) { + throw AnyhowException( + "The delegation for round $roundId bundle $bundleIndex is on-chain " + "but its commitment is not persisted — the wallet cannot locate it " + "in the commitment tree. Contact support.", + ); + } + BigInt? position; + for (final url in chainUrls) { + try { + position = await votingTreeFindLeaf( + roundId: roundId, + nodeUrl: url, + targetHex: vanHex, + ); + } on Exception { + continue; // this server's tree is unavailable; try the next + } + if (position != null) break; + } + if (position == null) { + throw AnyhowException( + "The chain says the delegation nullifier for round $roundId bundle " + "$bundleIndex was spent, but its commitment was not found in the " + "commitment tree. Contact support.", + ); + } + await votingRecoverConfirmDelegationFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + vanLeafPosition: position.toInt(), + c: c, + ); + } + + /// Recovers a vote whose nullifier is spent on-chain but whose tx hash was + /// never recorded locally: locate the vote commitment in the commitment + /// tree and record the confirmation from the recovered leaf positions. + Future<void> _reconcileVote({ + required List<String> chainUrls, + required int bundleIndex, + required int proposalId, + }) async { + final c = coinContext.coin; + final targetHex = await votingVoteCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, + ); + BigInt? vcPosition; + for (final url in chainUrls) { + try { + vcPosition = await votingTreeFindLeaf( + roundId: roundId, + nodeUrl: url, + targetHex: targetHex, + ); + } on Exception { + continue; + } + if (vcPosition != null) break; + } + if (vcPosition == null) { + throw AnyhowException( + "The chain says the vote nullifier for proposal $proposalId was " + "spent, but the vote commitment was not found in the commitment " + "tree. Contact support.", + ); + } + // The cast-vote tx appends the VAN output commitment immediately before + // the vote commitment (verified against the vote-sdk keeper), so the + // vote's VAN position is the vote commitment position minus one. + final van = vcPosition > BigInt.zero ? vcPosition - BigInt.one : null; + await votingRecoverConfirmVoteFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + vcTreePosition: vcPosition, + vanLeafPosition: van?.toInt(), + c: c, + ); + } + /// Casts and confirms the remaining votes for a round, recovery-first: /// `cast_vote` steps commit (streamed), `submit_vote` steps broadcast and /// confirm, `poll_vote` steps only poll a previously recorded tx. Ballot @@ -2045,14 +2346,16 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { /// round's cast steps appear (mirrors vizor's writeBallotIntents). Returns /// true when at least one vote was confirmed in this run. Future<bool> _runVotes({ - required String chainUrl, + required List<String> chainUrls, + required VoteChainFailover failover, required String voteNodeUrl, }) async { // An unset Vote Node URL falls back to the vote chain's REST API: the // chain server also serves the commitment tree the VAN witnesses sync // from (the polls page resolves the same default for the chain). - final resolvedVoteNodeUrl = - voteNodeUrl.isNotEmpty ? voteNodeUrl : chainUrl; + final resolvedVoteNodeUrl = voteNodeUrl.isNotEmpty + ? voteNodeUrl + : (chainUrls.isNotEmpty ? chainUrls.first : ""); final c = coinContext.coin; // Durable ballot intents first (mirrors vizor's writeBallotIntents): @@ -2160,7 +2463,8 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { await _submitVote( bundleIndex: bundleIndex, proposalId: step.proposalId, - chainUrl: chainUrl, + chainUrls: chainUrls, + failover: failover, ); didWork = true; } @@ -2169,7 +2473,8 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { await _submitVote( bundleIndex: bundleIndex, proposalId: step.proposalId, - chainUrl: chainUrl, + chainUrls: chainUrls, + failover: failover, ); didWork = true; } @@ -2188,32 +2493,104 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); } state = state.copyWith(stage: "confirming"); - final conf = - await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); - await votingConfirm( - roundId: roundId, + final conf = await _pollVoteWithRecovery( + chainUrls: chainUrls, + failover: failover, bundleIndex: bundleIndex, proposalId: step.proposalId, txHash: txHash, - eventsJson: conf.eventsJson, - c: c, ); didWork = true; if (state.txHash == null) { - state = state.copyWith(txHash: txHash, confirmHeight: conf.height); + state = state.copyWith(txHash: txHash, confirmHeight: conf?.height); } } } return didWork; } + /// Polls a previously recorded vote tx and confirms it, with the + /// re-broadcast and commitment-tree reconciliation fallbacks. Returns the + /// confirmation, or null when the vote was reconciled from the tree (no tx + /// events exist). + Future<VoteChainTxConfirmation?> _pollVoteWithRecovery({ + required List<String> chainUrls, + required VoteChainFailover failover, + required int bundleIndex, + required int proposalId, + required String txHash, + }) async { + final c = coinContext.coin; + try { + final conf = await _pollTxConfirmationWithFallback( + chainUrls: chainUrls, + failover: failover, + txHash: txHash, + wireJson: () => votingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, + ), + rebroadcast: () => failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) async { + final wire = await votingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, + ); + if (wire.isEmpty) { + throw AnyhowException( + "No vote wire JSON to re-broadcast proposal $proposalId", + ); + } + return votechainSubmitVote( + baseUrl: u, + submissionJson: wire, + c: c, + ); + }, + ), + markSubmitted: (h) => votingMarkVoteSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: h, + c: c, + ), + ); + await votingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + eventsJson: conf.eventsJson, + c: c, + ); + return conf; + } on DuplicateNullifierOnResubmitException { + await _reconcileVote( + chainUrls: chainUrls, + bundleIndex: bundleIndex, + proposalId: proposalId, + ); + return null; + } + } + /// Broadcasts one committed vote and confirms it: rebuild the wire from /// the persisted commitment, submit to the vote chain, record the tx hash, - /// poll until included in a block, and record the confirmation. + /// poll until included in a block, and record the confirmation. Resubmits + /// are byte-identical (the wire is persisted) and confirmation polling has + /// the re-broadcast + commitment-tree reconciliation fallbacks. Future<void> _submitVote({ required int bundleIndex, required int proposalId, - required String chainUrl, + required List<String> chainUrls, + required VoteChainFailover failover, }) async { final c = coinContext.coin; state = state.copyWith(stage: "voting", progress: 0); @@ -2223,29 +2600,37 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { proposalId: proposalId, c: c, ); - final res = await votechainSubmitVote( - baseUrl: chainUrl, - submissionJson: wireJson, - c: c, + final res = await failover.run( + baseUrls: chainUrls, + roundId: roundId, + call: (u) => votechainSubmitVote( + baseUrl: u, + submissionJson: wireJson, + c: c, + ), ); if (res.statusCode == 422) { throw AnyhowException( "Vote rejected by the vote chain: ${res.body}", ); } + final submittedHash = txHashFromVoteChainBody(res.body) ?? ""; + final rejection = parseVoteChainRejection(res.body); if (res.statusCode < 200 || res.statusCode >= 300) { + // A 502 "broadcast outcome unknown" body carries the deterministic + // tx hash: the tx may have landed — record it and let confirmation + // polling learn the truth. Any other non-2xx without a hash fails. + if (submittedHash.isEmpty) { + throw AnyhowException( + "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", + ); + } + } else if (rejection.code > 0 || submittedHash.isEmpty) { throw AnyhowException( - "Vote chain submit failed (HTTP ${res.statusCode}): ${res.body}", - ); - } - final result = jsonDecode(res.body) as Map<String, dynamic>; - final txHash = result['tx_hash'] as String? ?? ""; - final code = result['code'] as int? ?? -1; - if (code != 0 || txHash.isEmpty) { - throw AnyhowException( - "Vote chain rejected the vote: ${result['log'] ?? res.body}", + "Vote chain rejected the vote: ${rejection.log}", ); } + final txHash = submittedHash; await votingMarkVoteSubmitted( roundId: roundId, @@ -2255,35 +2640,16 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); state = state.copyWith(stage: "confirming"); - final conf = await _pollTxConfirmation(chainUrl: chainUrl, txHash: txHash); - await votingConfirm( - roundId: roundId, + final conf = await _pollVoteWithRecovery( + chainUrls: chainUrls, + failover: failover, bundleIndex: bundleIndex, proposalId: proposalId, txHash: txHash, - eventsJson: conf.eventsJson, - c: c, ); if (state.txHash == null) { - state = state.copyWith(txHash: txHash, confirmHeight: conf.height); - } - } - - /// Delay until the next planned share submission (min positive - /// submitAt − now), capped at an hour; 60s when nothing is pending. - int _shareTrackingDelaySeconds(List<VotingSharePlanItem> plans, int now) { - final nowBig = BigInt.from(now); - var minDelta = BigInt.zero; - var found = false; - for (final p in plans) { - final delta = p.submitAt - nowBig; - if (delta > BigInt.zero && (!found || delta < minDelta)) { - minDelta = delta; - found = true; - } + state = state.copyWith(txHash: txHash, confirmHeight: conf?.height); } - if (!found) return 60; - return minDelta > BigInt.from(3600) ? 3600 : minDelta.toInt(); } /// Converts UI drafts to the fork's DraftVote JSON for the commit step: @@ -2336,13 +2702,14 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { // confirmations. final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); if (unconfirmed.isNotEmpty) { - _scheduleShareTracking( - delaySeconds: 60, - ceremonyStart: ceremonyStart, - voteEnd: voteEndValue, - shareServerUrls: shareServerUrls, - singleShare: singleShare, - ); + ref.read(votingShareTrackerProvider.notifier).arm( + roundId: roundId, + delaySeconds: 60, + ceremonyStart: ceremonyStart, + voteEnd: voteEndValue, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); } return false; } @@ -2369,6 +2736,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); final body = jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); + var failed = false; for (final server in plan.targetServers) { final res = await votechainSubmitShare( serverUrl: server, @@ -2376,12 +2744,17 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); if (res.statusCode < 200 || res.statusCode >= 300) { - throw AnyhowException( - "Share submit to $server failed " - "(HTTP ${res.statusCode}): ${res.body}", + debugPrint( + "Voting: share submit to $server failed " + "(HTTP ${res.statusCode}) — the tracker will retry", ); + failed = true; } } + // The vote itself is already confirmed on-chain; a helper outage must + // not fail the whole run. Unrecorded shares stay in the payload list + // and the tracker retries them while the round window is open. + if (failed) continue; await votingShareRecord( roundId: roundId, bundleIndex: payload.bundleIndex, @@ -2394,9 +2767,13 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { submitted = true; } - // Background tracking until every share confirms (or the vote window ends). - _scheduleShareTracking( - delaySeconds: _shareTrackingDelaySeconds(plans, now), + // Background tracking until every share confirms (or the vote window + // ends). The tracker is session-independent: it survives client restarts + // via the polls page / splash re-arm hooks. + final tracker = ref.read(votingShareTrackerProvider.notifier); + tracker.arm( + roundId: roundId, + delaySeconds: voteChainShareTrackingDelay(plans, now), ceremonyStart: ceremonyStart, voteEnd: voteEndValue, shareServerUrls: shareServerUrls, @@ -2404,34 +2781,86 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); return submitted; } +} + +/// Delay until the next planned share submission (min positive +/// submitAt − now), capped at an hour; 60s when nothing is pending. +int voteChainShareTrackingDelay(List<VotingSharePlanItem> plans, int now) { + final nowBig = BigInt.from(now); + var minDelta = BigInt.zero; + var found = false; + for (final p in plans) { + final delta = p.submitAt - nowBig; + if (delta > BigInt.zero && (!found || delta < minDelta)) { + minDelta = delta; + found = true; + } + } + if (!found) return 60; + return minDelta > BigInt.from(3600) ? 3600 : minDelta.toInt(); +} + +/// Session-independent helper-share tracking for one round. +/// +/// Armed by the submission job, the voting polls page, and the post-wallet- +/// open hook, so a client restart does not strand share delivery while the +/// round window is open. Each tick submits unrecorded share payloads +/// (a helper outage during the foreground run leaves them unrecorded), polls +/// helper status for sent shares, and resubmits overdue ones — best-effort, +/// with the next tick retrying after any failure. +@Riverpod(keepAlive: true) +class VotingShareTracker extends _$VotingShareTracker { + final Map<String, Timer> _timers = {}; + + @override + bool build() { + ref.onDispose(() { + for (final timer in _timers.values) { + timer.cancel(); + } + _timers.clear(); + }); + return false; // needsAttention flag + } + + /// Sets the "share delivery pending" attention flag shown by the voting + /// page banner. + void markAttention(bool attention) { + state = attention; + } - void _scheduleShareTracking({ + /// Arms (or re-arms) the tracking timer for a round. + void arm({ + required String roundId, required int delaySeconds, required int ceremonyStart, required int? voteEnd, required List<String> shareServerUrls, required bool singleShare, }) { - _shareTimer?.cancel(); - _shareTimer = Timer(Duration(seconds: delaySeconds), () async { - if (state.stage == "done" || state.stage == "error") { - try { - await _trackShares( - ceremonyStart: ceremonyStart, - voteEnd: voteEnd, - shareServerUrls: shareServerUrls, - singleShare: singleShare, - ); - } on Exception catch (_) { - // The next tick retries; share tracking is best-effort. - } + _timers[roundId]?.cancel(); + _timers[roundId] = Timer(Duration(seconds: delaySeconds), () async { + _timers.remove(roundId); + try { + final pending = await tick( + roundId: roundId, + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: shareServerUrls, + singleShare: singleShare, + ); + state = pending; + } on Exception { + // The next tick retries; share tracking is best-effort. } }); } - /// One share-tracking tick: poll helper status for sent shares, resubmit - /// when the plan reports overdue shares, then re-arm if work remains. - Future<void> _trackShares({ + /// One share-tracking tick: submit unrecorded payloads, poll helper status + /// for sent shares, resubmit overdue shares, then re-arm if work remains. + /// Returns whether work is still pending after the tick. + Future<bool> tick({ + required String roundId, required int ceremonyStart, required int? voteEnd, required List<String> shareServerUrls, @@ -2439,6 +2868,63 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { }) async { final c = coinContext.coin; final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + var pending = false; + + // Submit shares whose rows were never recorded (all-target helper + // failure in the foreground run, or a client crash before recording). + // `votingSharePayloads` excludes recorded shares, so this never re-sends. + final payloads = await votingSharePayloads(roundId: roundId, c: c); + if (payloads.isNotEmpty && voteEnd != null) { + final plans = await votingSharePlans( + shareCount: payloads.length, + serverUrls: shareServerUrls, + now: BigInt.from(now), + voteEnd: BigInt.from(voteEnd), + ceremonyStart: BigInt.from(ceremonyStart), + singleShare: singleShare, + c: c, + ); + for (var i = 0; i < payloads.length && i < plans.length; i++) { + final payload = payloads[i]; + final plan = plans[i]; + final wireJson = await votingShareWireJson( + roundId: roundId, + bundleIndex: payload.bundleIndex, + proposalId: payload.proposalId, + shareIndex: payload.shareIndex, + vcTreePosition: payload.vcTreePosition, + submitAt: plan.submitAt, + c: c, + ); + final body = + jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); + var failed = false; + for (final server in plan.targetServers) { + final res = await votechainSubmitShare( + serverUrl: server, + payloadJson: body, + c: c, + ); + if (res.statusCode < 200 || res.statusCode >= 300) { + failed = true; + } + } + if (failed) { + pending = true; + continue; + } + await votingShareRecord( + roundId: roundId, + bundleIndex: payload.bundleIndex, + proposalId: payload.proposalId, + shareIndex: payload.shareIndex, + sentToUrls: plan.targetServers, + submitAt: plan.submitAt, + c: c, + ); + } + } + final plan = await votingSharePlan( roundId: roundId, now: BigInt.from(now), @@ -2449,26 +2935,34 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); final unconfirmed = await votingShareUnconfirmed(roundId: roundId, c: c); - if (unconfirmed.isEmpty) return; + if (unconfirmed.isEmpty && !pending) return false; for (final share in unconfirmed) { if (share.sentToUrls.isEmpty) continue; final shareId = hex.encode(share.nullifier); - final res = await votechainShareStatus( - serverUrl: share.sentToUrls.first, - roundId: roundId, - shareId: shareId, - c: c, - ); - if (res.statusCode == 200) { - await votingShareConfirm( + // Try every helper the share was sent to, not just the first: a dead + // helper must not hide a confirmation another helper can report. + var confirmed = false; + for (final server in share.sentToUrls) { + final res = await votechainShareStatus( + serverUrl: server, roundId: roundId, - bundleIndex: share.bundleIndex, - proposalId: share.proposalId, - shareIndex: share.shareIndex, + shareId: shareId, c: c, ); + if (res.statusCode == 200) { + await votingShareConfirm( + roundId: roundId, + bundleIndex: share.bundleIndex, + proposalId: share.proposalId, + shareIndex: share.shareIndex, + c: c, + ); + confirmed = true; + break; + } } + if (!confirmed) pending = true; } if (plan.summary.overdue > BigInt.zero) { @@ -2494,10 +2988,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { c: c, ); if (res.statusCode < 200 || res.statusCode >= 300) { - throw AnyhowException( - "Share resubmit to $server failed " - "(HTTP ${res.statusCode}): ${res.body}", - ); + pending = true; } } await votingShareAddServers( @@ -2512,7 +3003,8 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } if (voteEnd != null && plan.nextTrackingDelaySecs != null) { - _scheduleShareTracking( + arm( + roundId: roundId, delaySeconds: plan.nextTrackingDelaySecs!.toInt(), ceremonyStart: ceremonyStart, voteEnd: voteEnd, @@ -2523,5 +3015,69 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { // Reflect the confirmations in the plan so the round tile and status // screens update ("Resume" -> "View results" once every share confirms). await ref.read(votingSessionProvider(roundId).notifier).refresh(); + return pending; + } +} + +/// Re-arms share tracking for every local round whose plan still has share +/// work (submissions or confirmations). Called when the voting page opens and +/// after the wallet unlocks, so a client restart does not strand helper-share +/// delivery while the round window is open. +Future<void> armShareTrackingForPendingRounds(WidgetRef ref) async { + final c = coinContext.coin; + final Map<String, VotingSessionState> sessions; + try { + sessions = await ref.read(votingSessionsAllProvider.future); + } on Exception { + return; // wallet/rounds unavailable + } + List<String> serverUrls; + try { + final config = await ref.read(votingConfigProvider.future); + serverUrls = config?.voteServers.map((s) => s.url).toList() ?? const []; + } on Exception { + serverUrls = const []; + } + if (serverUrls.isEmpty) return; + + var anyPending = false; + for (final entry in sessions.entries) { + final roundId = entry.key; + final steps = entry.value.plan?.nextSteps ?? const <VotingNextStep>[]; + final hasShareWork = + steps.any((s) => s.kind == "submit_shares" || s.kind == "confirm_share"); + if (!hasShareWork) continue; + // Resolve the round window from the chain so the share plan can schedule. + var ceremonyStart = 0; + int? voteEnd; + try { + final res = await votechainRoundStatus( + baseUrl: serverUrls.first, + roundId: roundId, + c: c, + ); + if (res.statusCode >= 200 && res.statusCode < 300) { + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final ceremony = round['ceremony_phase_start']; + final end = round['vote_end_time']; + if (ceremony is int) ceremonyStart = ceremony; + if (end is int) voteEnd = end; + } + } on Exception { + // Timing unavailable: arm anyway; the tick resolves it on retry. + } + ref.read(votingShareTrackerProvider.notifier).arm( + roundId: roundId, + delaySeconds: 60, + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: serverUrls, + singleShare: false, + ); + anyPending = true; + } + if (anyPending) { + ref.read(votingShareTrackerProvider.notifier).markAttention(true); } } diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index 4a27b7355..b416a86da 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -5050,7 +5050,7 @@ class __$VotingSessionStateCopyWithImpl<$Res> /// @nodoc mixin _$VotingSubmissionJobState { String - get stage; // idle|preparing|proving|submitting|confirming|voting|shares|done|error + get stage; // idle|preparing|proving|submitting|confirming|voting|shares|retrying|done|error double get progress; String? get error; @@ -5068,6 +5068,12 @@ mixin _$VotingSubmissionJobState { /// Honest "done" headline describing what THIS run actually completed. String? get doneLabel; + /// Current automatic retry of a transiently failed run (1-based). + int? get retryAttempt; + + /// Seconds until the next automatic retry fires. + int? get retryInSeconds; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -5091,16 +5097,29 @@ mixin _$VotingSubmissionJobState { (identical(other.confirmHeight, confirmHeight) || other.confirmHeight == confirmHeight) && (identical(other.doneLabel, doneLabel) || - other.doneLabel == doneLabel)); + other.doneLabel == doneLabel) && + (identical(other.retryAttempt, retryAttempt) || + other.retryAttempt == retryAttempt) && + (identical(other.retryInSeconds, retryInSeconds) || + other.retryInSeconds == retryInSeconds)); } @override - int get hashCode => Object.hash(runtimeType, stage, progress, error, - eligibleWeightZatoshi, txHash, confirmHeight, doneLabel); + int get hashCode => Object.hash( + runtimeType, + stage, + progress, + error, + eligibleWeightZatoshi, + txHash, + confirmHeight, + doneLabel, + retryAttempt, + retryInSeconds); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel, retryAttempt: $retryAttempt, retryInSeconds: $retryInSeconds)'; } } @@ -5117,7 +5136,9 @@ abstract mixin class $VotingSubmissionJobStateCopyWith<$Res> { BigInt? eligibleWeightZatoshi, String? txHash, int? confirmHeight, - String? doneLabel}); + String? doneLabel, + int? retryAttempt, + int? retryInSeconds}); } /// @nodoc @@ -5140,6 +5161,8 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> Object? txHash = freezed, Object? confirmHeight = freezed, Object? doneLabel = freezed, + Object? retryAttempt = freezed, + Object? retryInSeconds = freezed, }) { return _then(_self.copyWith( stage: null == stage @@ -5170,6 +5193,14 @@ class _$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.doneLabel : doneLabel // ignore: cast_nullable_to_non_nullable as String?, + retryAttempt: freezed == retryAttempt + ? _self.retryAttempt + : retryAttempt // ignore: cast_nullable_to_non_nullable + as int?, + retryInSeconds: freezed == retryInSeconds + ? _self.retryInSeconds + : retryInSeconds // ignore: cast_nullable_to_non_nullable + as int?, )); } } @@ -5272,7 +5303,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { BigInt? eligibleWeightZatoshi, String? txHash, int? confirmHeight, - String? doneLabel)? + String? doneLabel, + int? retryAttempt, + int? retryInSeconds)? $default, { required TResult orElse(), }) { @@ -5286,7 +5319,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { _that.eligibleWeightZatoshi, _that.txHash, _that.confirmHeight, - _that.doneLabel); + _that.doneLabel, + _that.retryAttempt, + _that.retryInSeconds); case _: return orElse(); } @@ -5314,7 +5349,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { BigInt? eligibleWeightZatoshi, String? txHash, int? confirmHeight, - String? doneLabel) + String? doneLabel, + int? retryAttempt, + int? retryInSeconds) $default, ) { final _that = this; @@ -5327,7 +5364,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { _that.eligibleWeightZatoshi, _that.txHash, _that.confirmHeight, - _that.doneLabel); + _that.doneLabel, + _that.retryAttempt, + _that.retryInSeconds); } } @@ -5352,7 +5391,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { BigInt? eligibleWeightZatoshi, String? txHash, int? confirmHeight, - String? doneLabel)? + String? doneLabel, + int? retryAttempt, + int? retryInSeconds)? $default, ) { final _that = this; @@ -5365,7 +5406,9 @@ extension VotingSubmissionJobStatePatterns on VotingSubmissionJobState { _that.eligibleWeightZatoshi, _that.txHash, _that.confirmHeight, - _that.doneLabel); + _that.doneLabel, + _that.retryAttempt, + _that.retryInSeconds); case _: return null; } @@ -5382,11 +5425,13 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { this.eligibleWeightZatoshi, this.txHash, this.confirmHeight, - this.doneLabel}); + this.doneLabel, + this.retryAttempt, + this.retryInSeconds}); @override final String stage; -// idle|preparing|proving|submitting|confirming|voting|shares|done|error +// idle|preparing|proving|submitting|confirming|voting|shares|retrying|done|error @override final double progress; @override @@ -5410,6 +5455,14 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { @override final String? doneLabel; + /// Current automatic retry of a transiently failed run (1-based). + @override + final int? retryAttempt; + + /// Seconds until the next automatic retry fires. + @override + final int? retryInSeconds; + /// Create a copy of VotingSubmissionJobState /// with the given fields replaced by the non-null parameter values. @override @@ -5434,16 +5487,29 @@ class _VotingSubmissionJobState implements VotingSubmissionJobState { (identical(other.confirmHeight, confirmHeight) || other.confirmHeight == confirmHeight) && (identical(other.doneLabel, doneLabel) || - other.doneLabel == doneLabel)); + other.doneLabel == doneLabel) && + (identical(other.retryAttempt, retryAttempt) || + other.retryAttempt == retryAttempt) && + (identical(other.retryInSeconds, retryInSeconds) || + other.retryInSeconds == retryInSeconds)); } @override - int get hashCode => Object.hash(runtimeType, stage, progress, error, - eligibleWeightZatoshi, txHash, confirmHeight, doneLabel); + int get hashCode => Object.hash( + runtimeType, + stage, + progress, + error, + eligibleWeightZatoshi, + txHash, + confirmHeight, + doneLabel, + retryAttempt, + retryInSeconds); @override String toString() { - return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel)'; + return 'VotingSubmissionJobState(stage: $stage, progress: $progress, error: $error, eligibleWeightZatoshi: $eligibleWeightZatoshi, txHash: $txHash, confirmHeight: $confirmHeight, doneLabel: $doneLabel, retryAttempt: $retryAttempt, retryInSeconds: $retryInSeconds)'; } } @@ -5462,7 +5528,9 @@ abstract mixin class _$VotingSubmissionJobStateCopyWith<$Res> BigInt? eligibleWeightZatoshi, String? txHash, int? confirmHeight, - String? doneLabel}); + String? doneLabel, + int? retryAttempt, + int? retryInSeconds}); } /// @nodoc @@ -5485,6 +5553,8 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> Object? txHash = freezed, Object? confirmHeight = freezed, Object? doneLabel = freezed, + Object? retryAttempt = freezed, + Object? retryInSeconds = freezed, }) { return _then(_VotingSubmissionJobState( stage: null == stage @@ -5515,6 +5585,14 @@ class __$VotingSubmissionJobStateCopyWithImpl<$Res> ? _self.doneLabel : doneLabel // ignore: cast_nullable_to_non_nullable as String?, + retryAttempt: freezed == retryAttempt + ? _self.retryAttempt + : retryAttempt // ignore: cast_nullable_to_non_nullable + as int?, + retryInSeconds: freezed == retryInSeconds + ? _self.retryInSeconds + : retryInSeconds // ignore: cast_nullable_to_non_nullable + as int?, )); } } diff --git a/lib/store.g.dart b/lib/store.g.dart index 6ae353aa9..7f0c39bd6 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -2136,7 +2136,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'8ab47e4d2b936d5e6c152c05f85197abb7a0d648'; + r'f959d1379c1c2fd71f730fcf36c32f2b80bd35dd'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → @@ -2202,3 +2202,85 @@ abstract class _$VotingSubmissionJob element.handleValue(ref, created); } } + +/// Session-independent helper-share tracking for one round. +/// +/// Armed by the submission job, the voting polls page, and the post-wallet- +/// open hook, so a client restart does not strand share delivery while the +/// round window is open. Each tick submits unrecorded share payloads +/// (a helper outage during the foreground run leaves them unrecorded), polls +/// helper status for sent shares, and resubmits overdue ones — best-effort, +/// with the next tick retrying after any failure. + +@ProviderFor(VotingShareTracker) +const votingShareTrackerProvider = VotingShareTrackerProvider._(); + +/// Session-independent helper-share tracking for one round. +/// +/// Armed by the submission job, the voting polls page, and the post-wallet- +/// open hook, so a client restart does not strand share delivery while the +/// round window is open. Each tick submits unrecorded share payloads +/// (a helper outage during the foreground run leaves them unrecorded), polls +/// helper status for sent shares, and resubmits overdue ones — best-effort, +/// with the next tick retrying after any failure. +final class VotingShareTrackerProvider + extends $NotifierProvider<VotingShareTracker, bool> { + /// Session-independent helper-share tracking for one round. + /// + /// Armed by the submission job, the voting polls page, and the post-wallet- + /// open hook, so a client restart does not strand share delivery while the + /// round window is open. Each tick submits unrecorded share payloads + /// (a helper outage during the foreground run leaves them unrecorded), polls + /// helper status for sent shares, and resubmits overdue ones — best-effort, + /// with the next tick retrying after any failure. + const VotingShareTrackerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'votingShareTrackerProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$votingShareTrackerHash(); + + @$internal + @override + VotingShareTracker create() => VotingShareTracker(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(bool value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider<bool>(value), + ); + } +} + +String _$votingShareTrackerHash() => + r'54be86dcd23224ea6f76eebc469ef97181ca15c1'; + +/// Session-independent helper-share tracking for one round. +/// +/// Armed by the submission job, the voting polls page, and the post-wallet- +/// open hook, so a client restart does not strand share delivery while the +/// round window is open. Each tick submits unrecorded share payloads +/// (a helper outage during the foreground run leaves them unrecorded), polls +/// helper status for sent shares, and resubmits overdue ones — best-effort, +/// with the next tick retrying after any failure. + +abstract class _$VotingShareTracker extends $Notifier<bool> { + bool build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref<bool, bool>; + final element = ref.element as $ClassProviderElement< + AnyNotifier<bool, bool>, bool, Object?, Object?>; + element.handleValue(ref, created); + } +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..e627d2d48 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,8 @@ +# rustc 1.88 (and a few releases around it) fails to compile libcrux-psq +# 0.0.8 — a transitive nym dependency — with E0716 ("temporary value dropped +# while borrowed"), a known temporary-lifetime regression. 1.95.0 builds the +# whole workspace (incl. flutter_rust_bridge codegen) cleanly. Keep this +# pinned until the nym/libcrux pins move to a version that compiles on newer +# stable releases. +[toolchain] +channel = "1.95.0" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5080d5e82..d969b4b1d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,15 +13,17 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } -zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "faa06af424d284bf98a1a2687b65e6b1bf312ab1", features = ["zsa-orchard"] } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fccb06451cbc5adde7c274abac08d9e91281e2a4", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" bip39 = "2.1.0" nonempty = "0.11" env_logger = "0.11" +ff = "0.13" hex = "0.4" log = "0.4" +pasta_curves = "0.5" rand = "0.6" rand_core = "0.6" @@ -150,6 +152,10 @@ unexpected_cfgs = {level = "warn", check-cfg = ['cfg(frb_expand)']} [dev-dependencies] chrono = "0.4" rand = "0.6" +# Recovery-reconciliation tests exercise the voting fork's public prelude and +# the in-memory commitment-tree server. Same git source as the zcash_voting +# dep so the workspace [patch] override applies to it too. +vote-commitment-tree = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fccb06451cbc5adde7c274abac08d9e91281e2a4" } [features] default = ["flutter"] diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 24dcf9bf1..ff0584604 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -1518,6 +1518,148 @@ pub async fn voting_confirm( Ok(confirmation.into()) } +// --------------------------------------------------------------------------- +// Chain-evidence recovery +// +// When a submitted tx's hash is unknown (the broadcast response was lost and +// the chain spent the nullifier), the commitment tree still holds the +// evidence: the client's own vote commitment and VAN commitments are known +// from persisted recovery state. These helpers locate the leaves and record +// the confirmation without a tx hash. +// --------------------------------------------------------------------------- + +/// Confirmation evidence recovered from a commitment-tree scan. +#[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VotingTreeVoteConfirmation { + pub vc_tree_position: u64, + pub van_leaf_position: Option<u32>, +} + +/// Hex-encoded vote commitment leaf value for one committed vote, used to +/// locate the vote's commitment-tree leaf when the tx hash is unknown. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_vote_commitment_hex( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + c: &Coin, +) -> Result<String> { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let committed = + zcash_voting::prelude::CommittedVote::recover(&db, round_id, bundle_index, proposal_id) + .await?; + let signed = committed.signed_commitment(&db).await?; + Ok(hex::encode(signed.vote_commitment)) +} + +/// Hex-encoded cast-vote VAN output commitment for one committed vote (the +/// commitment-tree leaf appended immediately before the vote commitment). +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_vote_van_commitment_hex( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + c: &Coin, +) -> Result<String> { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let committed = + zcash_voting::prelude::CommittedVote::recover(&db, round_id, bundle_index, proposal_id) + .await?; + let signed = committed.signed_commitment(&db).await?; + Ok(hex::encode(signed.vote_authority_note_new)) +} + +/// Hex-encoded delegation VAN commitment (`gov_comm`) for a bundle, or `None` +/// when it was never persisted. Used to locate the delegation's tree leaf. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_delegation_van_commitment_hex( + round_id: &str, + bundle_index: u32, + c: &Coin, +) -> Result<Option<String>> { + use ff::PrimeField; + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let van = zcash_voting::prelude::delegation_van_commitment(&db, round_id, bundle_index).await?; + Ok(van.map(|value| hex::encode(value.to_repr()))) +} + +/// Scans the round's commitment tree for a leaf matching `target_hex` and +/// returns its global position, or `None` when absent. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_tree_find_leaf( + round_id: &str, + node_url: &str, + target_hex: &str, +) -> Result<Option<u64>> { + use ff::PrimeField; + let bytes: [u8; 32] = hex::decode(target_hex)? + .try_into() + .map_err(|_| anyhow::anyhow!("vote commitment hex must be 32 bytes"))?; + let target = Option::from(pasta_curves::Fp::from_repr(bytes)) + .ok_or_else(|| anyhow::anyhow!("vote commitment hex is not a canonical field element"))?; + Ok(zcash_voting::prelude::find_leaf_position(node_url, round_id, target).await?) +} + +/// Records a cast-vote confirmation whose evidence came from a +/// commitment-tree scan (no tx hash available). The vote's phase becomes +/// Confirmed so the resume plan proceeds to share submission. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_recover_confirm_vote_from_tree( + round_id: &str, + bundle_index: u32, + proposal_id: u32, + vc_tree_position: u64, + van_leaf_position: Option<u32>, + c: &Coin, +) -> Result<VotingTreeVoteConfirmation> { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + let confirmation = zcash_voting::prelude::record_vote_confirmation_from_tree( + &db, + round_id, + bundle_index, + proposal_id, + vc_tree_position, + van_leaf_position, + ) + .await?; + Ok(VotingTreeVoteConfirmation { + vc_tree_position: confirmation.vc_tree_position, + van_leaf_position: confirmation.van_leaf_position, + }) +} + +/// Records a delegation confirmation recovered from a commitment-tree scan +/// (no tx hash available). The bundle's phase becomes Confirmed so voting can +/// proceed. +#[cfg_attr(feature = "flutter", frb)] +pub async fn voting_recover_confirm_delegation_from_tree( + round_id: &str, + bundle_index: u32, + van_leaf_position: u32, + c: &Coin, +) -> Result<()> { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, c.account).await?; + let db = voting::open_voting_db(c.get_pool()?, &mut *connection, &wallet_id).await?; + zcash_voting::prelude::record_delegation_confirmation_from_tree( + &db, + round_id, + bundle_index, + van_leaf_position, + ) + .await?; + Ok(()) +} + // --------------------------------------------------------------------------- // Recovery / plan mirrors // --------------------------------------------------------------------------- @@ -2235,6 +2377,7 @@ pub async fn voting_sessions(round_ids: Vec<String>, c: &Coin) -> Result<Vec<Vot pub struct VotingChainResponse { pub status_code: u16, pub body: String, + pub retry_after_secs: Option<u64>, } /// Voting traffic honors the external-proxy setting (transport 3) only; it is @@ -2252,8 +2395,8 @@ fn votechain_proxy(c: &Coin) -> String { pub async fn votechain_list_rounds(base_url: &str, c: &Coin) -> Result<VotingChainResponse> { let base_url = base_url.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = crate::net::votechain::list_rounds(&base_url, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + let (status_code, body, retry_after_secs) = crate::net::votechain::list_rounds(&base_url, &proxy).await?; + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Fetches one round's status (`{ "round": ... }` envelope). @@ -2266,9 +2409,9 @@ pub async fn votechain_round_status( let base_url = base_url.to_string(); let round_id = round_id.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::round_status(&base_url, &round_id, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Fetches the round tally envelope. @@ -2281,9 +2424,9 @@ pub async fn votechain_round_tally( let base_url = base_url.to_string(); let round_id = round_id.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::round_tally(&base_url, &round_id, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Broadcasts a delegation transaction to the vote chain. @@ -2296,9 +2439,9 @@ pub async fn votechain_submit_delegation( let base_url = base_url.to_string(); let submission_json = submission_json.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::submit_delegation(&base_url, &submission_json, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Broadcasts a vote commitment transaction to the vote chain. @@ -2311,9 +2454,9 @@ pub async fn votechain_submit_vote( let base_url = base_url.to_string(); let submission_json = submission_json.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::submit_vote_commitment(&base_url, &submission_json, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Fetches the on-chain confirmation for a transaction; 404 = not confirmed. @@ -2326,9 +2469,9 @@ pub async fn votechain_tx_confirmation( let base_url = base_url.to_string(); let tx_hash = tx_hash.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::tx_confirmation(&base_url, &tx_hash, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Posts one encrypted share to a helper server. @@ -2341,9 +2484,9 @@ pub async fn votechain_submit_share( let server_url = server_url.to_string(); let payload_json = payload_json.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::submit_share(&server_url, &payload_json, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Resends a previously generated share to a helper server (same endpoint as @@ -2357,9 +2500,9 @@ pub async fn votechain_resubmit_share( let server_url = server_url.to_string(); let payload_json = payload_json.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::submit_share(&server_url, &payload_json, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } /// Checks whether a helper has confirmed a share identified by its nullifier. @@ -2374,9 +2517,9 @@ pub async fn votechain_share_status( let round_id = round_id.to_string(); let share_id = share_id.to_string(); let proxy = votechain_proxy(c); - let (status_code, body) = + let (status_code, body, retry_after_secs) = crate::net::votechain::share_status(&server_url, &round_id, &share_id, &proxy).await?; - Ok(VotingChainResponse { status_code, body }) + Ok(VotingChainResponse { status_code, body, retry_after_secs }) } #[cfg(test)] diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index ec94bf459..6c4df0e52 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1211184662; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -353494689; // Section: executor @@ -7974,6 +7974,49 @@ fn wire__crate__api__voting__voting_confirm_impl( }, ) } +fn wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_delegation_van_commitment_hex", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_bundle_index = <u32>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_delegation_van_commitment_hex( + &api_round_id, + api_bundle_index, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_drafts_load_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -8352,6 +8395,101 @@ fn wire__crate__api__voting__voting_record_execution_impl( }, ) } +fn wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_recover_confirm_delegation_from_tree", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_bundle_index = <u32>::sse_decode(&mut deserializer); + let api_van_leaf_position = <u32>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::voting::voting_recover_confirm_delegation_from_tree( + &api_round_id, + api_bundle_index, + api_van_leaf_position, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_recover_confirm_vote_from_tree", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_bundle_index = <u32>::sse_decode(&mut deserializer); + let api_proposal_id = <u32>::sse_decode(&mut deserializer); + let api_vc_tree_position = <u64>::sse_decode(&mut deserializer); + let api_van_leaf_position = <Option<u32>>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_recover_confirm_vote_from_tree( + &api_round_id, + api_bundle_index, + api_proposal_id, + api_vc_tree_position, + api_van_leaf_position, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_recovery_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -9061,6 +9199,49 @@ fn wire__crate__api__voting__voting_sync_tree_impl( }, ) } +fn wire__crate__api__voting__voting_tree_find_leaf_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_tree_find_leaf", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_node_url = <String>::sse_decode(&mut deserializer); + let api_target_hex = <String>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_tree_find_leaf( + &api_round_id, + &api_node_url, + &api_target_hex, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_van_witness_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -9106,6 +9287,96 @@ fn wire__crate__api__voting__voting_van_witness_impl( }, ) } +fn wire__crate__api__voting__voting_vote_commitment_hex_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_vote_commitment_hex", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_bundle_index = <u32>::sse_decode(&mut deserializer); + let api_proposal_id = <u32>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_vote_commitment_hex( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__voting__voting_vote_van_commitment_hex_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "voting_vote_van_commitment_hex", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_round_id = <String>::sse_decode(&mut deserializer); + let api_bundle_index = <u32>::sse_decode(&mut deserializer); + let api_proposal_id = <u32>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::voting::voting_vote_van_commitment_hex( + &api_round_id, + api_bundle_index, + api_proposal_id, + &api_c, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__voting__voting_vote_wire_json_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -11396,9 +11667,11 @@ impl SseDecode for crate::api::voting::VotingChainResponse { fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { let mut var_statusCode = <u16>::sse_decode(deserializer); let mut var_body = <String>::sse_decode(deserializer); + let mut var_retryAfterSecs = <Option<u64>>::sse_decode(deserializer); return crate::api::voting::VotingChainResponse { status_code: var_statusCode, body: var_body, + retry_after_secs: var_retryAfterSecs, }; } } @@ -11957,6 +12230,18 @@ impl SseDecode for crate::api::voting::VotingSignedVoteCommitment { } } +impl SseDecode for crate::api::voting::VotingTreeVoteConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_vcTreePosition = <u64>::sse_decode(deserializer); + let mut var_vanLeafPosition = <Option<u32>>::sse_decode(deserializer); + return crate::api::voting::VotingTreeVoteConfirmation { + vc_tree_position: var_vcTreePosition, + van_leaf_position: var_vanLeafPosition, + }; + } +} + impl SseDecode for crate::api::voting::VotingVanWitness { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -12532,82 +12817,115 @@ fn pde_ffi_dispatcher_primary_impl( wire__crate__api__voting__voting_config_resolve_impl(port, ptr, rust_vec_len, data_len) } 201 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 202 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), - 203 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), - 204 => { + 202 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 203 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), + 204 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), + 205 => { wire__crate__api__voting__voting_eligible_weight_impl(port, ptr, rust_vec_len, data_len) } - 205 => { + 206 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 206 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 207 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + 207 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 208 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 209 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 210 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 211 => wire__crate__api__voting__voting_record_execution_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 212 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 208 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 209 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), - 210 => wire__crate__api__voting__voting_record_execution_impl( + 213 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 211 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), - 212 => { + 214 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 215 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 213 => wire__crate__api__voting__voting_reset_session_state_impl( + 216 => wire__crate__api__voting__voting_reset_session_state_impl( port, ptr, rust_vec_len, data_len, ), - 214 => wire__crate__api__voting__voting_round_params_json_impl( + 217 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 215 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 216 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), - 217 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 218 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 219 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), + 220 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 218 => wire__crate__api__voting__voting_share_add_servers_impl( + 221 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 219 => { + 222 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 220 => { + 223 => { wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) } - 221 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 222 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), - 223 => { + 224 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 225 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 226 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 224 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 227 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 225 => { + 228 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 226 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 227 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 228 => { + 229 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 230 => { + wire__crate__api__voting__voting_tree_find_leaf_impl(port, ptr, rust_vec_len, data_len) + } + 231 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 232 => wire__crate__api__voting__voting_vote_commitment_hex_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 233 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 234 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -13965,6 +14283,7 @@ impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingChainResponse { [ self.status_code.into_into_dart().into_dart(), self.body.into_into_dart().into_dart(), + self.retry_after_secs.into_into_dart().into_dart(), ] .into_dart() } @@ -14681,6 +15000,27 @@ impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingSignedVoteCommi } } // Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingTreeVoteConfirmation { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + [ + self.vc_tree_position.into_into_dart().into_dart(), + self.van_leaf_position.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::voting::VotingTreeVoteConfirmation +{ +} +impl flutter_rust_bridge::IntoIntoDart<crate::api::voting::VotingTreeVoteConfirmation> + for crate::api::voting::VotingTreeVoteConfirmation +{ + fn into_into_dart(self) -> crate::api::voting::VotingTreeVoteConfirmation { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::voting::VotingVanWitness { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -16565,6 +16905,7 @@ impl SseEncode for crate::api::voting::VotingChainResponse { fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { <u16>::sse_encode(self.status_code, serializer); <String>::sse_encode(self.body, serializer); + <Option<u64>>::sse_encode(self.retry_after_secs, serializer); } } @@ -16926,6 +17267,14 @@ impl SseEncode for crate::api::voting::VotingSignedVoteCommitment { } } +impl SseEncode for crate::api::voting::VotingTreeVoteConfirmation { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + <u64>::sse_encode(self.vc_tree_position, serializer); + <Option<u32>>::sse_encode(self.van_leaf_position, serializer); + } +} + impl SseEncode for crate::api::voting::VotingVanWitness { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { diff --git a/rust/src/net/votechain.rs b/rust/src/net/votechain.rs index b97c066a4..55550fb3f 100644 --- a/rust/src/net/votechain.rs +++ b/rust/src/net/votechain.rs @@ -6,46 +6,108 @@ //! //! JSON envelopes are returned as raw bodies — the vote-sdk schema is still //! evolving and the Dart UI parses leniently (mirroring vizor's client). -//! HTTP status is preserved for 2xx, 404, and 422 (422 = deterministic chain -//! rejection whose body is a `VotingTxResult`), so the UI can distinguish a -//! rejection from a transport error; only network failures produce `Err`. +//! Every completed HTTP response is an answer: the status code, body, and +//! `Retry-After` header are passed through unchanged (422 = deterministic +//! chain rejection whose body is a `VotingTxResult`; 404 = not found; 5xx = +//! server-side trouble the caller may fail over from). Only transport +//! failures produce `Err`. +//! +//! Transient failures retry in place: idempotent GETs retry on any transport +//! error, and POSTs retry only when the request never reached the server (a +//! connection error), so a resent submission cannot double-deliver. Failover +//! across the configured vote servers is the Dart caller's job. use anyhow::{anyhow, Result}; use std::time::Duration; +use tokio::time::sleep; + +/// Attempts for idempotent vote-chain reads. A gateway 500 or a dropped +/// connection must not fail a whole voting run. +const GET_ATTEMPTS: usize = 3; +/// Attempts for vote-chain writes. Only connection failures retry — the +/// request never reached the server — anything else (including a timeout +/// after the request was sent) is final for this server. +const POST_ATTEMPTS: usize = 2; +/// Backoff between in-place retry attempts. +const RETRY_DELAY: Duration = Duration::from_millis(500); -/// Returns the status code and body of a GET, without erroring on 404. -async fn get(base_url: &str, path: &str, proxy: &str) -> Result<(u16, String)> { +/// Returns the status code, body, and `Retry-After` of a GET. Every completed +/// HTTP response is an answer; only transport failures are `Err`. +async fn get(base_url: &str, path: &str, proxy: &str) -> Result<(u16, String, Option<u64>)> { let url = endpoint(base_url, path)?; + let mut last_err: Option<anyhow::Error> = None; + for attempt in 0..GET_ATTEMPTS { + if attempt > 0 { + sleep(RETRY_DELAY * attempt as u32).await; + } + match get_once(&url, proxy).await { + Ok(response) => return Ok(response), + Err(e) => last_err = Some(e), + } + } + Err(last_err.expect("GET_ATTEMPTS is at least 1")) +} + +/// One GET attempt; 404 and other non-2xx statuses are answers, not errors. +async fn get_once(url: &str, proxy: &str) -> Result<(u16, String, Option<u64>)> { let response = client(proxy, Duration::from_secs(15))? - .get(&url) + .get(url) .send() .await .map_err(|e| anyhow!("vote chain GET {url}: {e}"))?; let status = response.status().as_u16(); + let retry_after = retry_after_secs(response.headers()); let body = response.text().await?; - if status != 404 && (status < 200 || status >= 300) { - return Err(anyhow!("vote chain GET {url}: HTTP {status}: {body}")); - } - Ok((status, body)) + Ok((status, body, retry_after)) } -/// Returns the status code and body of a POST, without erroring on 422 -/// (deterministic chain rejection). -async fn post(base_url: &str, path: &str, body_json: &str, proxy: &str) -> Result<(u16, String)> { +/// Returns the status code, body, and `Retry-After` of a POST. Every completed +/// HTTP response (including 422 deterministic rejections and 5xx) is an +/// answer; only transport failures are `Err`. +async fn post( + base_url: &str, + path: &str, + body_json: &str, + proxy: &str, +) -> Result<(u16, String, Option<u64>)> { let url = endpoint(base_url, path)?; - let response = client(proxy, Duration::from_secs(60))? - .post(&url) - .header("content-type", "application/json") - .body(body_json.to_string()) - .send() - .await - .map_err(|e| anyhow!("vote chain POST {url}: {e}"))?; - let status = response.status().as_u16(); - let body = response.text().await?; - if status != 422 && (status < 200 || status >= 300) { - return Err(anyhow!("vote chain POST {url}: HTTP {status}: {body}")); + let mut last_err: Option<anyhow::Error> = None; + for attempt in 0..POST_ATTEMPTS { + if attempt > 0 { + sleep(RETRY_DELAY).await; + } + let send = client(proxy, Duration::from_secs(60))? + .post(&url) + .header("content-type", "application/json") + .body(body_json.to_string()) + .send() + .await; + let response = match send { + Ok(response) => response, + Err(e) => { + let err = anyhow!("vote chain POST {url}: {e}"); + if e.is_connect() { + last_err = Some(err); + continue; + } + return Err(err); + } + }; + let status = response.status().as_u16(); + let retry_after = retry_after_secs(response.headers()); + let body = response.text().await?; + return Ok((status, body, retry_after)); } - Ok((status, body)) + Err(last_err.expect("POST_ATTEMPTS is at least 1")) +} + +/// Parses a `Retry-After` header in seconds (the vote-sdk sends an integer +/// delay; HTTP-date values are ignored). +fn retry_after_secs(headers: &reqwest::header::HeaderMap) -> Option<u64> { + headers + .get(reqwest::header::RETRY_AFTER) + .and_then(|value| value.to_str().ok()) + .and_then(|raw| raw.trim().parse::<u64>().ok()) } /// Builds a `/shielded-vote/v1/...` URL under `base_url`. @@ -66,17 +128,25 @@ fn client(proxy: &str, timeout: Duration) -> Result<reqwest::Client> { /// Lists rounds from the vote server. Current vote-sdk returns /// `{ "rounds": [...] }`; an empty `{}` means no rounds. -pub async fn list_rounds(base_url: &str, proxy: &str) -> Result<(u16, String)> { +pub async fn list_rounds(base_url: &str, proxy: &str) -> Result<(u16, String, Option<u64>)> { get(base_url, "rounds", proxy).await } /// Fetches one round's status (`{ "round": ... }` envelope). -pub async fn round_status(base_url: &str, round_id: &str, proxy: &str) -> Result<(u16, String)> { +pub async fn round_status( + base_url: &str, + round_id: &str, + proxy: &str, +) -> Result<(u16, String, Option<u64>)> { get(base_url, &format!("round/{round_id}"), proxy).await } /// Fetches the round tally envelope (`tally-results`). -pub async fn round_tally(base_url: &str, round_id: &str, proxy: &str) -> Result<(u16, String)> { +pub async fn round_tally( + base_url: &str, + round_id: &str, + proxy: &str, +) -> Result<(u16, String, Option<u64>)> { get(base_url, &format!("tally-results/{round_id}"), proxy).await } @@ -85,7 +155,7 @@ pub async fn submit_delegation( base_url: &str, submission_json: &str, proxy: &str, -) -> Result<(u16, String)> { +) -> Result<(u16, String, Option<u64>)> { post(base_url, "delegate-vote", submission_json, proxy).await } @@ -94,7 +164,7 @@ pub async fn submit_vote_commitment( base_url: &str, commitment_json: &str, proxy: &str, -) -> Result<(u16, String)> { +) -> Result<(u16, String, Option<u64>)> { post(base_url, "cast-vote", commitment_json, proxy).await } @@ -103,7 +173,7 @@ pub async fn tx_confirmation( base_url: &str, tx_hash: &str, proxy: &str, -) -> Result<(u16, String)> { +) -> Result<(u16, String, Option<u64>)> { get(base_url, &format!("tx/{tx_hash}"), proxy).await } @@ -113,7 +183,7 @@ pub async fn submit_share( server_url: &str, payload_json: &str, proxy: &str, -) -> Result<(u16, String)> { +) -> Result<(u16, String, Option<u64>)> { post(server_url, "shares", payload_json, proxy).await } @@ -123,12 +193,28 @@ pub async fn share_status( round_id: &str, share_id: &str, proxy: &str, -) -> Result<(u16, String)> { +) -> Result<(u16, String, Option<u64>)> { get(server_url, &format!("share-status/{round_id}/{share_id}"), proxy).await } -/// Fetches raw bytes from an arbitrary URL (voting config blobs). +/// Fetches raw bytes from an arbitrary URL (voting config blobs). Idempotent, +/// so it retries like [get]. pub async fn fetch_bytes(url: &str, proxy: &str) -> Result<Vec<u8>> { + let mut last_err: Option<anyhow::Error> = None; + for attempt in 0..GET_ATTEMPTS { + if attempt > 0 { + sleep(RETRY_DELAY * attempt as u32).await; + } + match fetch_bytes_once(url, proxy).await { + Ok(bytes) => return Ok(bytes), + Err(e) => last_err = Some(e), + } + } + Err(last_err.expect("GET_ATTEMPTS is at least 1")) +} + +/// One config-blob fetch attempt. +async fn fetch_bytes_once(url: &str, proxy: &str) -> Result<Vec<u8>> { let response = client(proxy, Duration::from_secs(15))? .get(url) .send() diff --git a/rust/src/voting.rs b/rust/src/voting.rs index 63b97cfa6..7d1abd56f 100644 --- a/rust/src/voting.rs +++ b/rust/src/voting.rs @@ -742,6 +742,12 @@ pub async fn vote_payloads( } /// Reconstructs the chain-ready wire JSON for a committed vote. +/// +/// The first build is persisted under a prop (mirroring the delegation wire) +/// and returned verbatim afterwards, so a resubmission after a crash is +/// byte-identical to the original broadcast — the chain derives the tx hash +/// from those bytes, and an identical resubmission keeps the recorded hash +/// valid. pub async fn vote_wire_json( pool: SqlitePool, wallet_id: &str, @@ -749,11 +755,17 @@ pub async fn vote_wire_json( bundle_index: u32, proposal_id: u32, ) -> Result<String> { + let prop_key = format!("voting_round_vote_wire:{round_id}:{bundle_index}:{proposal_id}"); let mut conn = pool.acquire().await?; + if let Some(saved) = crate::db::get_prop(&mut conn, &prop_key).await? { + return Ok(saved); + } let db = open_voting_db(pool, &mut conn, wallet_id).await?; let committed = CommittedVote::recover(&db, round_id, bundle_index, proposal_id).await?; let signed = committed.signed_commitment(&db).await?; - Ok(zcash_voting::wire::VoteCommitmentWire::try_from(&signed)?.to_json()?) + let wire = zcash_voting::wire::VoteCommitmentWire::try_from(&signed)?.to_json()?; + crate::db::put_prop(&mut conn, &prop_key, &wire).await?; + Ok(wire) } /// Reconstructs one helper-share payload as helper wire JSON from the diff --git a/rust/tests/voting_recovery_reconcile.rs b/rust/tests/voting_recovery_reconcile.rs new file mode 100644 index 000000000..1b4a5e778 --- /dev/null +++ b/rust/tests/voting_recovery_reconcile.rs @@ -0,0 +1,280 @@ +//! Recovery-reconciliation tests for the voting fork: recording chain +//! confirmations whose evidence came from a commitment-tree scan instead of +//! tx events (no tx hash), and locating leaves in the commitment tree. + +use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; +use vote_commitment_tree::MemoryTreeServer; +use zcash_voting::prelude::{ + delegation_van_commitment, find_leaf_position_with_api, record_delegation_confirmation_from_tree, + record_van_position, record_vote_confirmation_from_tree, DelegationPhase, Network, RoundParams, + VotePhase, VotingDb, +}; + +const ROUND_ID: &str = "1111111111111111111111111111111111111111111111111111111111111111"; +const WALLET_ID: &str = "wallet-reconcile"; + +fn round_params() -> RoundParams { + RoundParams { + vote_round_id: ROUND_ID.to_string(), + snapshot_height: 100, + ea_pk: vec![0xEA_u8; 32], + nc_root: vec![0xAA_u8; 32], + nullifier_imt_root: vec![0xBB_u8; 32], + } +} + +async fn test_db() -> (sqlx::SqlitePool, VotingDb) { + let pool = SqlitePoolOptions::new() + .max_connections(1) + .connect_with(SqliteConnectOptions::new().in_memory(true)) + .await + .unwrap(); + let mut conn = pool.acquire().await.unwrap(); + let db = VotingDb::from_pool(pool.clone(), &mut conn).await.unwrap(); + drop(conn); + db.set_wallet_id(WALLET_ID); + db.create_round(Network::Testnet, &round_params(), None) + .await + .unwrap(); + (pool, db) +} + +async fn insert_bundle(pool: &sqlx::SqlitePool, bundle_index: u32, gov_comm: Option<Vec<u8>>) { + sqlx::query( + "INSERT INTO voting_bundles (round_id, wallet_id, bundle_index, address_index, total_note_value, gov_comm) + VALUES (?, ?, ?, 0, 100, ?)", + ) + .bind(ROUND_ID) + .bind(WALLET_ID) + .bind(bundle_index as i64) + .bind(gov_comm) + .execute(pool) + .await + .unwrap(); +} + +async fn insert_vote( + pool: &sqlx::SqlitePool, + bundle_index: u32, + proposal_id: u32, + with_recovery: bool, +) { + sqlx::query( + "INSERT INTO voting_votes (round_id, wallet_id, bundle_index, proposal_id, choice, commitment, created_at, commitment_bundle_json) + VALUES (?, ?, ?, ?, 2, NULL, 1, ?)", + ) + .bind(ROUND_ID) + .bind(WALLET_ID) + .bind(bundle_index as i64) + .bind(proposal_id as i64) + .bind(if with_recovery { Some(recovery_json()) } else { None }) + .execute(pool) + .await + .unwrap(); +} + +/// Mirrors the wire format produced by the fork's `serialize_recovery` for a +/// committed vote; the recovery JSON round-trips through `parse_recovery`. +fn recovery_json() -> String { + serde_json::to_string(&serde_json::json!({ + "format": "zcash_voting_vote_recovery_v1", + "vote_round_id": ROUND_ID, + "bundle_index": 0, + "proposal_id": 1, + "vote_decision": 2, + "anchor_height": 100, + "vc_tree_position": 0, + "single_share": false, + "num_options": 3, + "van_nullifier": vec![0x31_u8; 32], + "vote_authority_note_new": vec![0x32_u8; 32], + "vote_commitment": vec![0x33_u8; 32], + "proof": vec![0x34_u8; 8], + "shares_hash": vec![0x35_u8; 32], + "r_vpk": vec![0x36_u8; 32], + "alpha_v": vec![0x37_u8; 32], + "vote_auth_sig": vec![0x38_u8; 64], + "encrypted_shares": [], + "share_blinds": [], + "share_comms": [], + })) + .unwrap() +} + +fn fp(x: u64) -> pasta_curves::Fp { + pasta_curves::Fp::from(x) +} + +#[tokio::test] +async fn tree_confirmation_records_vote_without_tx_hash() { + let (pool, db) = test_db().await; + insert_bundle(&pool, 0, None).await; + insert_vote(&pool, 0, 1, true).await; + + let result = record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 42, Some(41)) + .await + .unwrap(); + assert_eq!(result.vc_tree_position, 42); + assert_eq!(result.van_leaf_position, Some(41)); + + let mut conn = pool.acquire().await.unwrap(); + // Phase derivation reports Confirmed without a tx hash; the bundle's VAN + // pointer advanced to the vote's VAN output position. + assert_eq!( + db.vote_phase(&mut conn, ROUND_ID, 0, 1).await.unwrap(), + VotePhase::Confirmed + ); + assert_eq!( + db.delegation_phase(&mut conn, ROUND_ID, 0).await.unwrap(), + DelegationPhase::Confirmed + ); +} + +#[tokio::test] +async fn tree_confirmation_rejects_missing_recovery_bundle() { + let (pool, db) = test_db().await; + insert_bundle(&pool, 0, None).await; + insert_vote(&pool, 0, 1, false).await; + + let err = record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 42, None) + .await + .unwrap_err(); + assert!(matches!(err, zcash_voting::VotingError::InvalidInput { .. }), "got {err:?}"); +} + +#[tokio::test] +async fn tree_confirmation_replay_is_idempotent_and_conflict_checked() { + let (pool, db) = test_db().await; + insert_bundle(&pool, 0, None).await; + insert_vote(&pool, 0, 1, true).await; + + record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 42, Some(41)) + .await + .unwrap(); + // Replay with the same evidence is accepted. + record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 42, Some(41)) + .await + .unwrap(); + // A different VC position conflicts with the recorded one. + let err = record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 43, Some(42)) + .await + .unwrap_err(); + assert!(matches!(err, zcash_voting::VotingError::InvalidInput { .. }), "got {err:?}"); +} + +#[tokio::test] +async fn delegation_tree_confirmation_stores_van_position_and_never_rewinds() { + let (pool, db) = test_db().await; + insert_bundle(&pool, 0, None).await; + + record_delegation_confirmation_from_tree(&db, ROUND_ID, 0, 7) + .await + .unwrap(); + let mut conn = pool.acquire().await.unwrap(); + assert_eq!( + db.delegation_phase(&mut conn, ROUND_ID, 0).await.unwrap(), + DelegationPhase::Confirmed + ); + + // A later vote confirmation advanced the pointer past the delegation + // position; recovery must not rewind it. + drop(conn); + record_van_position(&db, ROUND_ID, 0, 9).await.unwrap(); + record_delegation_confirmation_from_tree(&db, ROUND_ID, 0, 7) + .await + .unwrap(); + let position: Option<i64> = sqlx::query_scalar( + "SELECT van_leaf_position FROM voting_bundles + WHERE round_id = ? AND wallet_id = ? AND bundle_index = 0", + ) + .bind(ROUND_ID) + .bind(WALLET_ID) + .fetch_one(&pool) + .await + .unwrap(); + assert_eq!(position, Some(9)); +} + +#[tokio::test] +async fn delegation_van_commitment_reads_persisted_gov_comm() { + use ff::PrimeField as _; + let (pool, db) = test_db().await; + let gov_comm = fp(77); + insert_bundle(&pool, 0, Some(gov_comm.to_repr().to_vec())).await; + + let recovered = delegation_van_commitment(&db, ROUND_ID, 0) + .await + .unwrap() + .expect("bundle gov_comm must load"); + assert_eq!(recovered, gov_comm); +} + +#[tokio::test] +async fn find_leaf_position_locates_leaf_in_server_pages() { + let mut server = MemoryTreeServer::empty(); + // One delegation leaf, then a cast-vote pair (VAN output, then vote + // commitment) — mirroring the chain's append order. + server.append(fp(10)).unwrap(); + server.checkpoint(1).unwrap(); + server.append_two(fp(20), fp(21)).unwrap(); + server.checkpoint(2).unwrap(); + + assert_eq!( + find_leaf_position_with_api(&server, fp(10), 4).await.unwrap(), + Some(0) + ); + assert_eq!( + find_leaf_position_with_api(&server, fp(21), 4).await.unwrap(), + Some(2) + ); + assert_eq!( + find_leaf_position_with_api(&server, fp(99), 4).await.unwrap(), + None + ); +} + +#[tokio::test] +async fn find_leaf_position_returns_none_on_empty_tree() { + let server = MemoryTreeServer::empty(); + assert_eq!( + find_leaf_position_with_api(&server, fp(1), 4).await.unwrap(), + None + ); +} + +#[tokio::test] +async fn migration_v13_upgrade_adds_confirmed_without_hash_column() { + let (pool, _db) = test_db().await; + // Simulate a v13 wallet DB: drop the v14 column and rewind the version. + sqlx::query("ALTER TABLE voting_votes DROP COLUMN confirmed_without_hash") + .execute(&pool) + .await + .unwrap(); + sqlx::query("UPDATE voting_schema_version SET version = 13") + .execute(&pool) + .await + .unwrap(); + + let mut conn = pool.acquire().await.unwrap(); + let db = VotingDb::from_pool(pool.clone(), &mut conn).await.unwrap(); + drop(conn); + db.set_wallet_id(WALLET_ID); + + // The upgrade must restore the column and phase derivation end to end. + insert_bundle(&pool, 0, None).await; + insert_vote(&pool, 0, 1, true).await; + record_vote_confirmation_from_tree(&db, ROUND_ID, 0, 1, 42, Some(41)) + .await + .unwrap(); + let mut conn = pool.acquire().await.unwrap(); + assert_eq!( + db.vote_phase(&mut conn, ROUND_ID, 0, 1).await.unwrap(), + VotePhase::Confirmed + ); + drop(conn); + let version: i64 = sqlx::query_scalar("SELECT MAX(version) FROM voting_schema_version") + .fetch_one(&pool) + .await + .unwrap(); + assert_eq!(version, 14); +} diff --git a/test/services/votechain_backoff_test.dart b/test/services/votechain_backoff_test.dart new file mode 100644 index 000000000..7dd826352 --- /dev/null +++ b/test/services/votechain_backoff_test.dart @@ -0,0 +1,15 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/services/votechain_backoff.dart'; + +void main() { + test('voteChainRetryDelay follows the 30/60/120 schedule', () { + expect(voteChainRetryDelay(1), const Duration(seconds: 30)); + expect(voteChainRetryDelay(2), const Duration(seconds: 60)); + expect(voteChainRetryDelay(3), const Duration(seconds: 120)); + expect(voteChainRetryDelay(10), const Duration(seconds: 120)); + }); + + test('max auto retries is bounded', () { + expect(voteChainMaxAutoRetries, 3); + }); +} diff --git a/test/services/votechain_classify_test.dart b/test/services/votechain_classify_test.dart new file mode 100644 index 000000000..bca07c157 --- /dev/null +++ b/test/services/votechain_classify_test.dart @@ -0,0 +1,63 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/services/votechain_classify.dart'; + +void main() { + group('classifyVoteChainRejection', () { + test('detects duplicate nullifier rejections', () { + expect( + classifyVoteChainRejection('nullifier already spent'), + ChainRejectionKind.duplicateNullifier, + ); + expect( + classifyVoteChainRejection( + '{"code":1,"log":"nullifier already spent"}', + ), + ChainRejectionKind.duplicateNullifier, + ); + expect( + classifyVoteChainRejection( + 'failed to execute message; nullifier spend check failed', + ), + ChainRejectionKind.duplicateNullifier, + ); + }); + + test('classifies other rejections as permanent', () { + expect( + classifyVoteChainRejection('vote round is not active'), + ChainRejectionKind.other, + ); + expect( + classifyVoteChainRejection('{"code":2,"log":"bad proof"}'), + ChainRejectionKind.other, + ); + expect(classifyVoteChainRejection(''), ChainRejectionKind.other); + }); + }); + + group('txHashFromVoteChainBody', () { + test('extracts tx_hash from the JSON envelope', () { + expect( + txHashFromVoteChainBody( + '{"tx_hash":"ABCDEF123456","code":0,"log":""}', + ), + 'ABCDEF123456', + ); + }); + + test('extracts tx_hash from the 502 unknown-outcome message', () { + expect( + txHashFromVoteChainBody( + 'broadcast outcome unknown after retries; tx_hash=ABCDEF123456', + ), + 'ABCDEF123456', + ); + }); + + test('returns null when no hash is present', () { + expect(txHashFromVoteChainBody('{}'), isNull); + expect(txHashFromVoteChainBody('not json at all'), isNull); + expect(txHashFromVoteChainBody(''), isNull); + }); + }); +} diff --git a/test/services/votechain_confirmation_test.dart b/test/services/votechain_confirmation_test.dart index a13af4989..495c45640 100644 --- a/test/services/votechain_confirmation_test.dart +++ b/test/services/votechain_confirmation_test.dart @@ -78,4 +78,20 @@ void main() { expect(conf!.eventsJson, '[]'); }); }); + + group('parseVoteChainRejection', () { + test('extracts code and log from the envelope', () { + final rejection = parseVoteChainRejection( + '{"tx_hash":"","code":3,"log":"nullifier already spent"}', + ); + expect(rejection.code, 3); + expect(rejection.log, 'nullifier already spent'); + }); + + test('falls back to the raw body for non-envelope bodies', () { + final rejection = parseVoteChainRejection('plain text'); + expect(rejection.code, -1); + expect(rejection.log, 'plain text'); + }); + }); } diff --git a/test/services/votechain_failover_test.dart b/test/services/votechain_failover_test.dart new file mode 100644 index 000000000..e2005adc0 --- /dev/null +++ b/test/services/votechain_failover_test.dart @@ -0,0 +1,136 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/services/votechain_failover.dart'; +import 'package:zkool/src/rust/api/voting.dart'; + +VotingChainResponse response(int status, {String body = '{}', int? retryAfter}) { + return VotingChainResponse( + statusCode: status, + body: body, + retryAfterSecs: retryAfter == null ? null : BigInt.from(retryAfter), + ); +} + +void main() { + test('candidate ordering: caller list first, then config, deduplicated', () { + final failover = VoteChainFailover( + allServers: const ['a', 'b', 'c'], + delay: (_) async {}, + ); + expect( + failover.orderedCandidates(['c', 'd'], 'r1'), + ['c', 'd', 'a', 'b'], + ); + }); + + test('remembers the last working URL per round and tries it first', () async { + final calls = <String>[]; + final failover = VoteChainFailover( + allServers: const ['a', 'b'], + delay: (_) async {}, + ); + await failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (url) async { + calls.add(url); + if (url == 'a') throw Exception('down'); + return response(200); + }, + ); + expect(calls, ['a', 'b']); + + final again = await failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (url) async { + calls.add(url); + return response(200); + }, + ); + expect(again.statusCode, 200); + // The remembered URL (b) is tried first and answers immediately. + expect(calls, ['a', 'b', 'b']); + }); + + test('4xx is a final answer', () async { + final failover = VoteChainFailover(delay: (_) async {}); + final res = await failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (url) async => url == 'a' ? response(422, body: 'rejected') : fail('b must not be tried'), + ); + expect(res.statusCode, 422); + }); + + test('404 is a final answer (not confirmed yet)', () async { + final failover = VoteChainFailover(delay: (_) async {}); + final res = await failover.run( + baseUrls: ['a'], + roundId: 'r1', + call: (_) async => response(404, body: '{"error":"tx not found"}'), + ); + expect(res.statusCode, 404); + }); + + test('5xx rotates to the next server', () async { + final failover = VoteChainFailover(delay: (_) async {}); + final res = await failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (url) async => url == 'a' ? response(500) : response(200), + ); + expect(res.statusCode, 200); + }); + + test('503 honors Retry-After and retries the same URL once', () async { + final delays = <Duration>[]; + var calls = 0; + final failover = VoteChainFailover(delay: (d) async => delays.add(d)); + final res = await failover.run( + baseUrls: ['a'], + roundId: 'r1', + call: (_) async { + calls++; + return calls == 1 + ? response(503, retryAfter: 5) + : response(200); + }, + ); + expect(res.statusCode, 200); + expect(delays, [const Duration(seconds: 5)]); + }); + + test('502 with a tx hash is returned as an answer', () async { + final failover = VoteChainFailover(delay: (_) async {}); + final res = await failover.run( + baseUrls: ['a'], + roundId: 'r1', + call: (_) async => + response(502, body: 'broadcast outcome unknown after retries; tx_hash=ABCDEF'), + ); + expect(res.statusCode, 502); + expect(res.body, contains('ABCDEF')); + }); + + test('502 without a hash rotates to the next server', () async { + final failover = VoteChainFailover(delay: (_) async {}); + final res = await failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (url) async => url == 'a' ? response(502, body: 'boom') : response(200), + ); + expect(res.statusCode, 200); + }); + + test('all candidates failing raises TransientVoteChainException', () async { + final failover = VoteChainFailover(delay: (_) async {}); + expect( + () => failover.run( + baseUrls: ['a', 'b'], + roundId: 'r1', + call: (_) async => throw Exception('down'), + ), + throwsA(isA<TransientVoteChainException>()), + ); + }); +} From 294e71ff6bb263ce3a5456ffbcc1a72438aa9dfd Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 22 Aug 2026 19:39:32 +0800 Subject: [PATCH 117/189] fix(voting): recovery edge cases found in live testing Fixes surfaced while testing the resumable-recovery work against real rounds: - delegation recovery reuses the persisted wire instead of re-proving when a resume still has a delegate step (avoids a wasted ZK proof and the fork's round-phase bookkeeping); fork rev bumped to 04950416, which treats a round-phase advance past a milestone as a no-op - duplicate-nullifier 422 on the fresh delegation submit now explains that the on-chain delegation may belong to a wiped/lost voting hotkey instead of dumping the raw body - share delivery uses the vote-server failover (cluster semantics): unreachable helpers rotate; an all-fleet outage raises a transient error that the job auto-retries; the background tracker uses the same routing and retries unrecorded shares - vote-commit FRB wrapper releases its pool connection before the long ZK proof (matching the delegation wrapper) and the wallet pool gains headroom (5 -> 10 connections) so proofs cannot starve concurrent DB traffic into 'pool timed out' - share-tracking re-arm scan runs on a provider-scoped ref instead of the calling page's widget ref (the splash screen unmounts itself mid- scan at startup) - shardtree pinned at WARN to stop its per-append span flood - orchard memo decryption tolerates a missing note row like the sapling path instead of failing the whole tx - rust-toolchain.toml ships the matching rust-analyzer component --- Cargo.lock | 6 +- lib/pages/splash.dart | 2 +- lib/pages/voting_polls.dart | 5 +- lib/store.dart | 349 ++++++++++++++++++++++-------------- lib/store.g.dart | 69 ++++++- rust-toolchain.toml | 3 + rust/Cargo.toml | 4 +- rust/src/api/coin.rs | 6 +- rust/src/api/init.rs | 25 ++- rust/src/api/voting.rs | 20 ++- rust/src/memo.rs | 11 +- 11 files changed, 335 insertions(+), 165 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0f06cbea..9a6ea9ada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13213,7 +13213,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vote-commitment-tree" version = "0.4.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=049504162f11a09c89d33414d35e747851891d04#049504162f11a09c89d33414d35e747851891d04" dependencies = [ "anyhow", "ff", @@ -13229,7 +13229,7 @@ dependencies = [ [[package]] name = "vote-commitment-tree-client" version = "0.6.0-rc.2" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=049504162f11a09c89d33414d35e747851891d04#049504162f11a09c89d33414d35e747851891d04" dependencies = [ "base64 0.22.1", "ff", @@ -14418,7 +14418,7 @@ dependencies = [ [[package]] name = "zcash_voting" version = "2.0.0-rc.5" -source = "git+https://github.com/hhanh00/zcash_voting.git?rev=fccb06451cbc5adde7c274abac08d9e91281e2a4#fccb06451cbc5adde7c274abac08d9e91281e2a4" +source = "git+https://github.com/hhanh00/zcash_voting.git?rev=049504162f11a09c89d33414d35e747851891d04#049504162f11a09c89d33414d35e747851891d04" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/lib/pages/splash.dart b/lib/pages/splash.dart index 342460bd4..222daaa15 100644 --- a/lib/pages/splash.dart +++ b/lib/pages/splash.dart @@ -109,7 +109,7 @@ class SplashPageState extends ConsumerState<SplashPage> { // Re-arm helper-share tracking for rounds with pending share work, so a // client restart resumes share delivery without visiting the voting page. if (settings.votingConfigUrl.isNotEmpty) { - unawaited(Future(() => armShareTrackingForPendingRounds(ref))); + unawaited(Future(() => ref.read(shareTrackingArmProvider.notifier).run())); } final synchronizer = ref.read(synchronizerProvider.notifier); synchronizer.autoSync(); diff --git a/lib/pages/voting_polls.dart b/lib/pages/voting_polls.dart index 03d2707e6..2b2227d71 100644 --- a/lib/pages/voting_polls.dart +++ b/lib/pages/voting_polls.dart @@ -48,8 +48,9 @@ class VotingPollsPageState extends ConsumerState<VotingPollsPage> { }); // Opening the voting page re-arms helper-share tracking for rounds with // pending share work, so a restart resumes delivery without a manual - // status-page visit. - Future(() => armShareTrackingForPendingRounds(ref)); + // status-page visit. Runs on a provider-scoped ref, so navigating away + // before the scan completes is safe. + Future(() => ref.read(shareTrackingArmProvider.notifier).run()); } /// Voting v1 supports software accounts only; the fork signs with the diff --git a/lib/store.dart b/lib/store.dart index 3eecdc802..64c7b1718 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1672,6 +1672,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { } } final shared = await _submitShares( + failover: failover, ceremonyStart: effectiveCeremony, voteEnd: effectiveVoteEnd, shareServerUrls: shareUrls, @@ -1786,77 +1787,109 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { String? txHash; if (delegateStep != null || freshDelegate) { state = state.copyWith(stage: "preparing"); - // The delegation keys embed an app-owned voting hotkey; auto-create - // one when missing and the round isn't already hotkey-bound (mirrors - // vizor's _ensureHotkey). A bound round without the stored hotkey - // keeps failing with the load error instead of silently generating a - // mismatched key. - if (!(plan?.hotkeyBound ?? false)) { - await _ensureVotingHotkey(); - } - // The voting pages never pass a lightwalletd URL — use the app's - // configured one for the fresh prepare (the fork needs it to fetch - // the snapshot anchor tree state). - final lwdUrl = (lightwalletdUrl == null || lightwalletdUrl!.isEmpty) - ? await _appLwdUrl() - : lightwalletdUrl!; - final prepared = roundParamsJson != null && roundName != null - ? await delegationPrepare( - roundParamsJson: roundParamsJson, - roundName: roundName, - sessionJson: null, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lwdUrl, - c: c, - ) - : await delegationPrepareResume( - roundId: roundId, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl, - c: c, - ); - state = state.copyWith( - eligibleWeightZatoshi: prepared.eligibleWeightZatoshi, - ); - - state = state.copyWith(stage: "proving"); - final pir = await _resolvePirConfig( - pirServerUrl: pirServerUrl, - pirLayout: pirLayout, - ); - await _buildDelegation( - roundId: roundId, - bundleIndex: bundleIndex, - pirLayout: pir.$2, - pirServerUrl: pir.$1, - ); - - // The FRB boundary drops the build result when a StreamSink is present, - // so the wire body comes from the prop persisted by the build. - final wireJson = await delegationWireJson( + // Recovery with a persisted wire: a previous run already proved and + // built the submission. Re-proving would waste a ZK proof and trip the + // fork's round-phase bookkeeping when votes already exist for the + // round — reuse the persisted wire for a byte-identical resubmission + // instead (the server dedups it or the tree reconciliation records the + // confirmation). + var wireJson = await delegationWireJson( roundId: roundId, bundleIndex: bundleIndex, c: c, ); + if (wireJson == null || wireJson.isEmpty) { + // The delegation keys embed an app-owned voting hotkey; auto-create + // one when missing and the round isn't already hotkey-bound (mirrors + // vizor's _ensureHotkey). A bound round without the stored hotkey + // keeps failing with the load error instead of silently generating a + // mismatched key. + if (!(plan?.hotkeyBound ?? false)) { + await _ensureVotingHotkey(); + } + // The voting pages never pass a lightwalletd URL — use the app's + // configured one for the fresh prepare (the fork needs it to fetch + // the snapshot anchor tree state). + final lwdUrl = (lightwalletdUrl == null || lightwalletdUrl!.isEmpty) + ? await _appLwdUrl() + : lightwalletdUrl!; + final prepared = roundParamsJson != null && roundName != null + ? await delegationPrepare( + roundParamsJson: roundParamsJson, + roundName: roundName, + sessionJson: null, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lwdUrl, + c: c, + ) + : await delegationPrepareResume( + roundId: roundId, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c, + ); + state = state.copyWith( + eligibleWeightZatoshi: prepared.eligibleWeightZatoshi, + ); + + state = state.copyWith(stage: "proving"); + final pir = await _resolvePirConfig( + pirServerUrl: pirServerUrl, + pirLayout: pirLayout, + ); + await _buildDelegation( + roundId: roundId, + bundleIndex: bundleIndex, + pirLayout: pir.$2, + pirServerUrl: pir.$1, + ); + + // The FRB boundary drops the build result when a StreamSink is + // present, so the wire body comes from the prop persisted by the + // build. + wireJson = await delegationWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, + ); + if (wireJson == null || wireJson.isEmpty) { + throw AnyhowException( + "No wire JSON produced for round $roundId bundle $bundleIndex", + ); + } + } + if (wireJson == null || wireJson.isEmpty) { throw AnyhowException( "No wire JSON produced for round $roundId bundle $bundleIndex", ); } - state = state.copyWith(stage: "submitting"); final res = await failover.run( baseUrls: chainUrls, roundId: roundId, call: (u) => votechainSubmitDelegation( baseUrl: u, - submissionJson: wireJson, + submissionJson: wireJson!, c: c, ), ); if (res.statusCode == 422) { + final rejection = parseVoteChainRejection(res.body); + if (classifyVoteChainRejection(res.body) == + ChainRejectionKind.duplicateNullifier) { + throw AnyhowException( + "The vote chain says this delegation's nullifier is already " + "spent: the delegation is recorded on-chain, but this wallet " + "has no record of submitting it. If the wallet was restored or " + "its voting data cleared after the original submission, it no " + "longer holds the voting hotkey the on-chain delegation is " + "bound to, and it cannot sign votes for this round. " + "${rejection.log}", + ); + } throw AnyhowException( "Delegation rejected by the vote chain: ${res.body}", ); @@ -2678,6 +2711,7 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { /// (the real inputs arrive with the dynamic config in a later phase). /// Returns true when at least one share was submitted and recorded. Future<bool> _submitShares({ + required VoteChainFailover failover, required int ceremonyStart, required int? voteEnd, required List<String> shareServerUrls, @@ -2736,25 +2770,31 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); final body = jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); - var failed = false; - for (final server in plan.targetServers) { - final res = await votechainSubmitShare( - serverUrl: server, + // The vote itself is already confirmed on-chain; a helper outage must + // not fail the whole run. Share submits go through the failover + // service: unreachable helpers rotate to the next target (the helper + // fleet works as a cluster), and only an all-targets-down outage + // raises TransientVoteChainException — which the job's auto-retry + // picks up. Unrecorded shares stay in the payload list and the tracker + // retries them while the round window is open. + final res = await failover.run( + baseUrls: plan.targetServers, + roundId: roundId, + call: (u) => votechainSubmitShare( + serverUrl: u, payloadJson: body, c: c, + ), + ); + if (res.statusCode < 200 || res.statusCode >= 300) { + // A definitive rejection from the first answering helper (e.g. the + // round window closed): leave the share unrecorded for the tracker. + debugPrint( + "Voting: share submit rejected (HTTP ${res.statusCode}) — " + "the tracker will retry", ); - if (res.statusCode < 200 || res.statusCode >= 300) { - debugPrint( - "Voting: share submit to $server failed " - "(HTTP ${res.statusCode}) — the tracker will retry", - ); - failed = true; - } + continue; } - // The vote itself is already confirmed on-chain; a helper outage must - // not fail the whole run. Unrecorded shares stay in the payload list - // and the tracker retries them while the round window is open. - if (failed) continue; await votingShareRecord( roundId: roundId, bundleIndex: payload.bundleIndex, @@ -2869,6 +2909,9 @@ class VotingShareTracker extends _$VotingShareTracker { final c = coinContext.coin; final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; var pending = false; + // Per-tick failover: rotates across the target helpers and falls back to + // the rest of the configured fleet when a target is unreachable. + final failover = VoteChainFailover(allServers: shareServerUrls); // Submit shares whose rows were never recorded (all-target helper // failure in the foreground run, or a client crash before recording). @@ -2898,18 +2941,25 @@ class VotingShareTracker extends _$VotingShareTracker { ); final body = jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); - var failed = false; - for (final server in plan.targetServers) { - final res = await votechainSubmitShare( - serverUrl: server, - payloadJson: body, - c: c, + final VotingChainResponse res; + try { + // Same cluster semantics as the foreground run: rotate across the + // target helpers, and mark the tick pending when the whole fleet + // is unreachable — the next tick retries. + res = await failover.run( + baseUrls: plan.targetServers, + roundId: roundId, + call: (u) => votechainSubmitShare( + serverUrl: u, + payloadJson: body, + c: c, + ), ); - if (res.statusCode < 200 || res.statusCode >= 300) { - failed = true; - } + } on TransientVoteChainException { + pending = true; + continue; } - if (failed) { + if (res.statusCode < 200 || res.statusCode >= 300) { pending = true; continue; } @@ -2981,15 +3031,23 @@ class VotingShareTracker extends _$VotingShareTracker { ); final body = jsonEncode({...jsonDecode(wireJson), "vote_round_id": roundId}); - for (final server in item.targetServers) { - final res = await votechainResubmitShare( - serverUrl: server, - payloadJson: body, - c: c, + final VotingChainResponse res; + try { + res = await failover.run( + baseUrls: item.targetServers, + roundId: roundId, + call: (u) => votechainResubmitShare( + serverUrl: u, + payloadJson: body, + c: c, + ), ); - if (res.statusCode < 200 || res.statusCode >= 300) { - pending = true; - } + } on TransientVoteChainException { + pending = true; + continue; + } + if (res.statusCode < 200 || res.statusCode >= 300) { + pending = true; } await votingShareAddServers( roundId: roundId, @@ -3023,61 +3081,82 @@ class VotingShareTracker extends _$VotingShareTracker { /// work (submissions or confirmations). Called when the voting page opens and /// after the wallet unlocks, so a client restart does not strand helper-share /// delivery while the round window is open. -Future<void> armShareTrackingForPendingRounds(WidgetRef ref) async { - final c = coinContext.coin; - final Map<String, VotingSessionState> sessions; - try { - sessions = await ref.read(votingSessionsAllProvider.future); - } on Exception { - return; // wallet/rounds unavailable - } - List<String> serverUrls; +/// +/// Takes a provider-scoped [Ref] (see [ShareTrackingArm]) — never a widget +/// ref, which dies with its page and throws when read after unmount. +Future<void> armShareTrackingForPendingRounds(Ref ref) async { try { - final config = await ref.read(votingConfigProvider.future); - serverUrls = config?.voteServers.map((s) => s.url).toList() ?? const []; - } on Exception { - serverUrls = const []; - } - if (serverUrls.isEmpty) return; - - var anyPending = false; - for (final entry in sessions.entries) { - final roundId = entry.key; - final steps = entry.value.plan?.nextSteps ?? const <VotingNextStep>[]; - final hasShareWork = - steps.any((s) => s.kind == "submit_shares" || s.kind == "confirm_share"); - if (!hasShareWork) continue; - // Resolve the round window from the chain so the share plan can schedule. - var ceremonyStart = 0; - int? voteEnd; + final c = coinContext.coin; + final Map<String, VotingSessionState> sessions; try { - final res = await votechainRoundStatus( - baseUrl: serverUrls.first, - roundId: roundId, - c: c, - ); - if (res.statusCode >= 200 && res.statusCode < 300) { - final body = jsonDecode(res.body) as Map<String, dynamic>; - final round = body['round'] as Map<String, dynamic>? ?? {}; - final ceremony = round['ceremony_phase_start']; - final end = round['vote_end_time']; - if (ceremony is int) ceremonyStart = ceremony; - if (end is int) voteEnd = end; - } + sessions = await ref.read(votingSessionsAllProvider.future); + } on Exception { + return; // wallet/rounds unavailable + } + List<String> serverUrls; + try { + final config = await ref.read(votingConfigProvider.future); + serverUrls = config?.voteServers.map((s) => s.url).toList() ?? const []; } on Exception { - // Timing unavailable: arm anyway; the tick resolves it on retry. + serverUrls = const []; } - ref.read(votingShareTrackerProvider.notifier).arm( + if (serverUrls.isEmpty) return; + + var anyPending = false; + for (final entry in sessions.entries) { + final roundId = entry.key; + final steps = entry.value.plan?.nextSteps ?? const <VotingNextStep>[]; + final hasShareWork = steps.any( + (s) => s.kind == "submit_shares" || s.kind == "confirm_share", + ); + if (!hasShareWork) continue; + // Resolve the round window from the chain so the share plan can + // schedule. + var ceremonyStart = 0; + int? voteEnd; + try { + final res = await votechainRoundStatus( + baseUrl: serverUrls.first, roundId: roundId, - delaySeconds: 60, - ceremonyStart: ceremonyStart, - voteEnd: voteEnd, - shareServerUrls: serverUrls, - singleShare: false, + c: c, ); - anyPending = true; - } - if (anyPending) { - ref.read(votingShareTrackerProvider.notifier).markAttention(true); + if (res.statusCode >= 200 && res.statusCode < 300) { + final body = jsonDecode(res.body) as Map<String, dynamic>; + final round = body['round'] as Map<String, dynamic>? ?? {}; + final ceremony = round['ceremony_phase_start']; + final end = round['vote_end_time']; + if (ceremony is int) ceremonyStart = ceremony; + if (end is int) voteEnd = end; + } + } on Exception { + // Timing unavailable: arm anyway; the tick resolves it on retry. + } + ref.read(votingShareTrackerProvider.notifier).arm( + roundId: roundId, + delaySeconds: 60, + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + shareServerUrls: serverUrls, + singleShare: false, + ); + anyPending = true; + } + if (anyPending) { + ref.read(votingShareTrackerProvider.notifier).markAttention(true); + } + } on Exception { + // Best-effort background scan: never surface errors from the re-arm. } } + +/// Re-runnable trigger for the share-tracking re-arm scan. Runs the scan on a +/// provider-scoped ref that outlives any page; callers invoke +/// `ref.read(shareTrackingArmProvider.notifier).run()` from initState, which +/// is safe even when the page unmounts before the scan completes. +@Riverpod(keepAlive: true) +class ShareTrackingArm extends _$ShareTrackingArm { + @override + void build() {} + + Future<void> run() => armShareTrackingForPendingRounds(ref); +} diff --git a/lib/store.g.dart b/lib/store.g.dart index 7f0c39bd6..b98bfc7f3 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -2136,7 +2136,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'f959d1379c1c2fd71f730fcf36c32f2b80bd35dd'; + r'74833aa2e2d32c5e38e4b931309a4776a4cc3f57'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → @@ -2261,7 +2261,7 @@ final class VotingShareTrackerProvider } String _$votingShareTrackerHash() => - r'54be86dcd23224ea6f76eebc469ef97181ca15c1'; + r'fb64664f086a6d186faebbae65da843a83dec41e'; /// Session-independent helper-share tracking for one round. /// @@ -2284,3 +2284,68 @@ abstract class _$VotingShareTracker extends $Notifier<bool> { element.handleValue(ref, created); } } + +/// Re-runnable trigger for the share-tracking re-arm scan. Runs the scan on a +/// provider-scoped ref that outlives any page; callers invoke +/// `ref.read(shareTrackingArmProvider.notifier).run()` from initState, which +/// is safe even when the page unmounts before the scan completes. + +@ProviderFor(ShareTrackingArm) +const shareTrackingArmProvider = ShareTrackingArmProvider._(); + +/// Re-runnable trigger for the share-tracking re-arm scan. Runs the scan on a +/// provider-scoped ref that outlives any page; callers invoke +/// `ref.read(shareTrackingArmProvider.notifier).run()` from initState, which +/// is safe even when the page unmounts before the scan completes. +final class ShareTrackingArmProvider + extends $NotifierProvider<ShareTrackingArm, void> { + /// Re-runnable trigger for the share-tracking re-arm scan. Runs the scan on a + /// provider-scoped ref that outlives any page; callers invoke + /// `ref.read(shareTrackingArmProvider.notifier).run()` from initState, which + /// is safe even when the page unmounts before the scan completes. + const ShareTrackingArmProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'shareTrackingArmProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$shareTrackingArmHash(); + + @$internal + @override + ShareTrackingArm create() => ShareTrackingArm(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(void value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider<void>(value), + ); + } +} + +String _$shareTrackingArmHash() => r'd2bf9df564e8f0806abb55ab64c1a9a1e9611a69'; + +/// Re-runnable trigger for the share-tracking re-arm scan. Runs the scan on a +/// provider-scoped ref that outlives any page; callers invoke +/// `ref.read(shareTrackingArmProvider.notifier).run()` from initState, which +/// is safe even when the page unmounts before the scan completes. + +abstract class _$ShareTrackingArm extends $Notifier<void> { + void build(); + @$mustCallSuper + @override + void runBuild() { + build(); + final ref = this.ref as $Ref<void, void>; + final element = ref.element as $ClassProviderElement< + AnyNotifier<void, void>, void, Object?, Object?>; + element.handleValue(ref, null); + } +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e627d2d48..b24d1a1a5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -6,3 +6,6 @@ # stable releases. [toolchain] channel = "1.95.0" +# Ship the toolchain-matched rust-analyzer so IDE language support works with +# the pinned compiler. +components = ["rust-analyzer"] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d969b4b1d..5fde611c0 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,7 @@ required-features = ["graphql"] [dependencies] zcash-trees = { git = "https://github.com/hhanh00/zcash-trees.git", rev = "1c820645e9116bbdfed5719ba8ff1d89b9be6cb1" } -zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fccb06451cbc5adde7c274abac08d9e91281e2a4", features = ["zsa-orchard"] } +zcash_voting = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "049504162f11a09c89d33414d35e747851891d04", features = ["zsa-orchard"] } flutter_rust_bridge = { version = "=2.12.0", optional = true } anyhow = "1.0.97" @@ -155,7 +155,7 @@ rand = "0.6" # Recovery-reconciliation tests exercise the voting fork's public prelude and # the in-memory commitment-tree server. Same git source as the zcash_voting # dep so the workspace [patch] override applies to it too. -vote-commitment-tree = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "fccb06451cbc5adde7c274abac08d9e91281e2a4" } +vote-commitment-tree = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "049504162f11a09c89d33414d35e747851891d04" } [features] default = ["flutter"] diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 2796c46d2..24f144c76 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -235,7 +235,11 @@ async fn try_open( // Create a connection pool let options = get_connect_options(db_filepath, password); let pool = SqlitePoolOptions::new() - .max_connections(5) + // Voting proofs hold a connection for minutes at a time while the + // synchronizer, share tracker, and session reads run concurrently; + // keep headroom so a long proof cannot starve the pool (sqlx's + // default 30 s acquire timeout would surface as "pool timed out"). + .max_connections(10) .idle_timeout(std::time::Duration::from_secs(30)) .max_lifetime(std::time::Duration::from_secs(60 * 60)) .connect_with(options) diff --git a/rust/src/api/init.rs b/rust/src/api/init.rs index f2dc15b8e..e555fe9d2 100644 --- a/rust/src/api/init.rs +++ b/rust/src/api/init.rs @@ -33,10 +33,7 @@ pub fn init_app() { flutter_rust_bridge::setup_default_user_utils(); let _ = env_logger::builder().try_init(); - let env_filter = EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) - .from_env_lossy(); - let (filter_layer, reload_handle) = reload::Layer::new(env_filter); + let (filter_layer, reload_handle) = reload::Layer::new(base_filter()); FILTER_HANDLE.set(reload_handle).ok(); let _ = Registry::default() @@ -55,11 +52,9 @@ pub fn init_app() { pub fn set_expert_mode(enabled: bool) { if let Some(handle) = FILTER_HANDLE.get() { let filter = if enabled { - EnvFilter::new("warp=debug,rlz=debug,info") + EnvFilter::new("warp=debug,rlz=debug,shardtree=warn,info") } else { - EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) - .from_env_lossy() + base_filter() }; let _ = handle.modify(|f| *f = filter); } @@ -67,6 +62,20 @@ pub fn set_expert_mode(enabled: bool) { pub type BoxedLayer<S> = Box<dyn Layer<S> + Send + Sync + 'static>; +/// The base log filter: INFO by default, RUST_LOG overrides per target, and +/// the `shardtree` crate pinned at WARN. Every vote-commitment-tree append +/// runs a `prune_excess_checkpoints` span, and the fmt layer emits its +/// enter/exit events at the span's level — at INFO that floods the log with +/// hundreds of lines per tree sync. An explicit RUST_LOG directive for +/// `shardtree` still wins (this directive is appended last, so user-provided +/// directives match first). +fn base_filter() -> EnvFilter { + EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy() + .add_directive("shardtree=warn".parse().expect("static shardtree filter")) +} + pub fn default_layer<S>() -> BoxedLayer<S> where S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index ff0584604..48f6525ac 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -834,13 +834,19 @@ pub async fn voting_commit_with_progress( let drafts_json = drafts_json.to_string(); let vote_node_url = vote_node_url.to_string(); let drafts: Vec<DraftVote> = serde_json::from_str(&drafts_json)?; - let mut connection = c.get_connection().await?; - let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; - let hotkey = voting::voting_hotkey_load( - &mut connection, - voting::voting_network(&c.network())?, - ) - .await?; + let (wallet_id, hotkey) = { + let mut connection = c.get_connection().await?; + let wallet_id = voting::voting_wallet_id(&mut connection, account).await?; + let hotkey = voting::voting_hotkey_load( + &mut connection, + voting::voting_network(&c.network())?, + ) + .await?; + // Release the connection before the tree sync + ZK proof, which run + // for a while; don't hold a pool slot hostage during the long phase + // (a later internal acquire would queue behind it). + (wallet_id, hotkey) + }; let witness = voting::vote_van_witness(c.get_pool()?, &wallet_id, &round_id, bundle_index, &vote_node_url) .await?; diff --git a/rust/src/memo.rs b/rust/src/memo.rs index c9c623fe3..cbe0c2754 100644 --- a/rust/src/memo.rs +++ b/rust/src/memo.rs @@ -351,21 +351,24 @@ pub async fn decrypt_memo( { debug!("decrypt_memo: ivk decrypt ok for vout={vout} pool={pool}"); let cmx: ExtractedNoteCommitment = note.commitment().into(); + // The note row may be missing (e.g. a tx scanned + // before its note was stored); attach the memo + // without a note link like the sapling path instead + // of failing the whole tx. let id_note = sqlx::query("SELECT id_note FROM notes WHERE account = ? AND cmx = ?") .bind(account) .bind(&cmx.to_bytes()[..]) .map(|row: SqliteRow| row.get::<u32, _>(0)) - .fetch_one(&mut *connection) - .await - .context("Failed to find note")?; + .fetch_optional(&mut *connection) + .await?; process_memo( connection, account, height, id_tx, - Some(id_note), + id_note, None, pool, vout as u32, From 299232fa746b811cda2d5d739d96097a6acda466 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sun, 23 Aug 2026 18:41:05 +0800 Subject: [PATCH 118/189] chore: update build number --- build_number.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_number.txt b/build_number.txt index 947e93bc2..6fa50e78e 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -341 +353 From 99734a4d87d58aeea58217b784a1576cefea62cd Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Sun, 23 Aug 2026 18:51:09 +0800 Subject: [PATCH 119/189] chore(main): release zkool 6.28.0 (#1223) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 56 +++++++++++++++++++++++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 20a91f896..3c57d9436 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.27.0" + ".": "6.28.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index daf3240d9..ce49d4e2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,61 @@ # Changelog +## [6.28.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.27.0...zkool-v6.28.0) (2026-08-23) + + +### Features + +* ballot page AppBar shows the round title ([ca86e2c](https://github.com/hhanh00/zkool2/commit/ca86e2cf6e8393349b270d3a1b0ffebded7f012e)) +* gate voting round actions on chain status; zero tally for voteless closed rounds ([8404323](https://github.com/hhanh00/zkool2/commit/8404323d6bd23bf18f0191827f2cc743bdf391e3)) +* results page title shows the round title ([fb449a8](https://github.com/hhanh00/zkool2/commit/fb449a8651db5e9fd901893274666900fb16ee2b)) +* shielded voting UI (ZIP 262) ([1e5564c](https://github.com/hhanh00/zkool2/commit/1e5564ca8808768b2b2959484e7372f76a2083d2)) +* show friendly round titles and option labels in the voting UI ([f991e8c](https://github.com/hhanh00/zkool2/commit/f991e8c3279b7dca6d2fe101e88622d279424600)) +* show per-vote on-chain evidence on the done and confirmation screens ([5db3025](https://github.com/hhanh00/zkool2/commit/5db3025a8e5558f043e0652268e64aaae21b1af3)) +* show proposal title and selection in the ballot evidence ([52f3c86](https://github.com/hhanh00/zkool2/commit/52f3c868aee603afae7148a1f5adaebeaec44068)) +* show proposal titles and option labels in the tally results ([e15bafc](https://github.com/hhanh00/zkool2/commit/e15bafc82998a9d16f52d1c365b20eee535a19bf)) +* show voting power on voting confirmation and status pages ([0a7472c](https://github.com/hhanh00/zkool2/commit/0a7472cb5913446cb6fe74a2e65b3fa0dd25d81a)) +* **voting:** resumable recovery across network, server, and client failures ([ad7ad08](https://github.com/hhanh00/zkool2/commit/ad7ad0889b135b5fd58b3790061caa4f6827c1d7)) + + +### Bug Fixes + +* **account:** derive sapling address on file import and fail fast on corrupt stored addresses ([e8e9f22](https://github.com/hhanh00/zkool2/commit/e8e9f22c196ec718c675484bc9ff31d125116eb0)) +* auto-create the voting hotkey at delegation time ([06ff09c](https://github.com/hhanh00/zkool2/commit/06ff09c9867477e91072800f3464bff3509f993e)) +* batch-load voting sessions on one pool connection; keep the pool free during delegation ([f056f50](https://github.com/hhanh00/zkool2/commit/f056f5024947fbac96bde464139d5fbae79f967c)) +* build with Flutter 3.47.0 ([aca790c](https://github.com/hhanh00/zkool2/commit/aca790cd1f018eb29197a692801f9feb219083cd)) +* bump Kotlin to 2.2.20 for Flutter 3.47.0 Android build ([891ff2d](https://github.com/hhanh00/zkool2/commit/891ff2dc3fdfe21e6227e0b8b964e1a283c47658)) +* bundle sapling params in desktop and graphql builds ([c48cf9e](https://github.com/hhanh00/zkool2/commit/c48cf9e2b7194c78ca746af70a60fe446dbef654)) +* cast one proposal at a time so the vote VAN chains ([7e2a4d6](https://github.com/hhanh00/zkool2/commit/7e2a4d657a87cc9513e22fd5a3e8026b0891cf7c)) +* decode trailing escaped spaces in OA1 records ([a58529d](https://github.com/hhanh00/zkool2/commit/a58529de91b122749cabf8a0ce43ee2bad0e48e5)) +* don't re-send recorded shares; refresh status after tracking ([ca013ad](https://github.com/hhanh00/zkool2/commit/ca013ad6d649a4458b022b61495e78e6863acff9)) +* drop redundant pool predicate from diversifier index backfill ([f22a316](https://github.com/hhanh00/zkool2/commit/f22a3162ca0ac459e842d1ee2fba1be2dacb1114)) +* exclude post-snapshot notes from delegation prepare ([c343a71](https://github.com/hhanh00/zkool2/commit/c343a71c9228d84fd7893f56463160a3b1b1ac45)) +* fall back to the configured vote servers for helper shares ([4ead4da](https://github.com/hhanh00/zkool2/commit/4ead4da1cd1d08b7eb768605659277d444627bf2)) +* honest done label when only time-scheduled steps remain ([1129f34](https://github.com/hhanh00/zkool2/commit/1129f34b931379054906df293b6565081f60c8de)) +* key ballot evidence proposals by id, not list position ([8811c97](https://github.com/hhanh00/zkool2/commit/8811c975ed46328637908cff4187de62a58e2029)) +* **ledger:** transparent-only signing + NU6.3 v5 workaround for hardware wallets ([#1208](https://github.com/hhanh00/zkool2/issues/1208)) ([3fdeea0](https://github.com/hhanh00/zkool2/commit/3fdeea0a161776e275545f183cea12e416dbba80)) +* make delegation confirmation real and recoverable ([80a073b](https://github.com/hhanh00/zkool2/commit/80a073bc815354e856acc6947be67c7b264a0ccc)) +* parse the chain's string block heights; prove with voting-circuits 0.10.0 ([57357ef](https://github.com/hhanh00/zkool2/commit/57357ef871f8865712c77bc7b8611d84fc626158)) +* parse vote-sdk tally entries per-entry decision and amount ([dfd5db0](https://github.com/hhanh00/zkool2/commit/dfd5db0fe9151f0bf0b0ae394b8108e75138fd33)) +* pass one connection through voting DB reads; stop pool stalls on voting page ([c791f7f](https://github.com/hhanh00/zkool2/commit/c791f7f80e8ca1b5c3647dcc6d7120d4ab5e3b7e)) +* persist ballot intents at cast time; parse option index ([2e6f796](https://github.com/hhanh00/zkool2/commit/2e6f79655e5496fa96d1ec678f7ae4f194e903f5)) +* render option labels with vote-sdk ids, not 1-based positions ([4fcaa22](https://github.com/hhanh00/zkool2/commit/4fcaa220f80391e38f907df6d259e610f8de2462)) +* resolve share-window timing from the chain round status ([87c6be3](https://github.com/hhanh00/zkool2/commit/87c6be3d23c1624b20a5766eb702764cd3f0aff7)) +* run fresh voting submissions end-to-end (delegate + vote) ([ed4b752](https://github.com/hhanh00/zkool2/commit/ed4b7520f57c12598f41583da189b6fcc8cc6770)) +* run the PIR connect inside the prove thread ([ab74456](https://github.com/hhanh00/zkool2/commit/ab74456746657a562bd148259909bccf1400c113)) +* save settings on nav away; resolve voting config from form value ([e2fb677](https://github.com/hhanh00/zkool2/commit/e2fb677fa3808930ac5e894e513ab617cc3de58c)) +* **settings:** keep transport selector within screen width (FittedBox + padding) ([bed8131](https://github.com/hhanh00/zkool2/commit/bed813138743371f1a99ebf07f5322eeaa8ead70)) +* stop ref use after unmount when closing Folders page (issue 1203) ([ba14db4](https://github.com/hhanh00/zkool2/commit/ba14db4370bb89601f84356c3ef8ee2c6251c8e7)) +* submit helper shares from the confirmed votes' payloads ([c61dd21](https://github.com/hhanh00/zkool2/commit/c61dd21e4371058e0b4c9a4414849b2ccab925af)) +* support flutter 3.47 (intl 0.20.3); fixed 6.2.0 rename scale→decimalDigits ([f46f650](https://github.com/hhanh00/zkool2/commit/f46f65061eed1762d9814dd96e27f90aa963f3f9)) +* surface voting config resolve errors instead of swallowing them ([6c8c98b](https://github.com/hhanh00/zkool2/commit/6c8c98be3d65cf1b2d9faf6c6a4d35b509a3a5ba)) +* tally entries without a decision key are decision 0, not a total ([7b97c6a](https://github.com/hhanh00/zkool2/commit/7b97c6a62b13da3f819f98303865610429205444)) +* use app lightwalletd URL for fresh delegation prepare ([63acacb](https://github.com/hhanh00/zkool2/commit/63acacbbc038671c896d472bd933b61d19469863)) +* use the async PIR client for delegation proving ([c497c05](https://github.com/hhanh00/zkool2/commit/c497c059354a0e82e65cd14f27cba025ba97558a)) +* **voting:** default vote node URL to the vote chain server when unset ([1a9bc99](https://github.com/hhanh00/zkool2/commit/1a9bc9978231e5fe1043165b76f45a7a86ae61d8)) +* **voting:** keep back navigation to account after vote submission ([f291d65](https://github.com/hhanh00/zkool2/commit/f291d65246f4b5df07fbc0f6d97fb798af576089)) +* **voting:** recovery edge cases found in live testing ([294e71f](https://github.com/hhanh00/zkool2/commit/294e71ff6bb263ce3a5456ffbcc1a72438aa9dfd)) + ## [6.27.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.26.1...zkool-v6.27.0) (2026-08-15) diff --git a/build_number.txt b/build_number.txt index 6fa50e78e..bc23f8ef5 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -353 +354 diff --git a/pubspec.yaml b/pubspec.yaml index 0be60410f..91a011b1d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.27.0 # x-release-please-version +version: 6.28.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 9cd1a39f6..2ece8e17b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.27.0 +6.28.0 From 9dd6cb2129f6bfdaeb6f0b098520bd9f8014c3d0 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sun, 23 Aug 2026 22:32:32 +0800 Subject: [PATCH 120/189] chore: update ios provisioning profile --- misc/ios.mobileprovision.enc | Bin 12304 -> 12304 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/misc/ios.mobileprovision.enc b/misc/ios.mobileprovision.enc index 816851f42e2bef7d8ce506230db4d456e0a81dfb..19468113aea36f8e2c5fbd3e96b140660f9396a8 100644 GIT binary patch literal 12304 zcmV+rFz?S(VQh3|WM5xj0lt}q!fyv2r|0UW^l6_Jv0Wmp5&H~}kS!UY)?wg@_8phk z*xoqd`vwvDy!uDgA5ww8t&TF?)uNKEm2n`J)IEIPdpUBp@wvHg-Y%hjUqeDBJCiji zIGvnll;c>}hv;bvV9aN_{?qj9a3RJ`pRw9~7%<CBBvN<m^~#04w}dI#AeHE$qNgjS zHqLr*R_T*p1R4?BqNDv@-w+=PW`$!Q*})I1_tRdyUP%bdABeD-ar}inelUWLNZpg_ z?sIm=E{@OlXTv@-6CNcDk%DlHu${vb5|!|ISI$NSI?%kweZp=;3(q`^RNfrNf5iSB z^?y1TF$rH28P<gXfR$-9N3!^+P5fo#-J9+Nmlrd-JqWmdm!i_^3BXq*Vxwc<Z*YD9 zIqSEHlV{|A?Tq2JX9>t*(cx-%;7t7AKzOwv$NR{pDaSNa_ilE;YW`<&w~D#E10s@b zhFpx}9~UZBJc7IIu=Gspea*@4wM2}!vByJ>Xx=~P6xqQMT%PX@n*96@k6QNYoO~5( z%XWEdL%Rnfj~X0f!p6a9VZV%MGJS87+8H>g`quM&VZO5C?Cn2G=Y=)(Vm8m)=o`kl zNk~s{kzaVB8}o1Wb)hH2nvE9<1l5xEPU+REF*W6k{HAHN^ieqn*jgKp6W!qX!HzmH zutgs+Bigx#>OHyqb3t3HMm1hfAe(>aCOqMv=mfK(fgmN!p>%PaT42pI=$zAxJ+Qvv z70M}B<$i`<rgd9tC#5eLN;G1BX{L<ahpF1hr4x7XzuLcMRs#e~sZGKw&Aw&+lF0mp z+fqZuJb}Oi&bd!$KzN%M7ii3}lOdzFYT4jr;)Ove$a(-Pv-+(Yw~Y}T3C*rUBD){M zYH!7$O43*<&L;8dBMmmqB-iTH5@rFCXdjVQ75|p<4`eq}OCsbzZB1CEcP*i@HiLtQ zNn$%zU<fxpRWo><=Z+i>-#H{zjLT`#$>-&kx|$KAHliB)FJ&8qarQ9Ymg`W_%OqhM zQv!Z_iq(>siaSL&M!=BC4+a@df8G1Pkmqk>KR=UC*Hx7yaKOTB?4^GfLMw&ZSYLQ! z_^Ksg9ow{fC}uzCN4&18>Yscg39YH+@5}&uWj5oIfJO(Dj+<lLtO0_cF&p?QHS0t+ z9*J`~sb(~6G@zZ-Meu`qbmUM-qG<i8skB7<=HraCxn``-EfEMoCkfXtvz1X-5qD6Y z(7Z_a8F$_Jp#?l5Ot%BaUz)4Rp1wnzw@@B_Ps=6|;W`$$1CECgABfu&eKY_3<nDZ% zF-70it)OJ|K)o|IJW1LAD3=;{|3qNq77-H*|2wlML4_9G9t5<fYo0b7Eb1;zn!7EC z*$==an>)Wj0~uV&w<{sj%J{KzS1%&^4=QNzW<~@*I{f`1GO3>bd7ZZd2Kxa~k{IZY zIPXZ|nPN}AX@r<iMr8U}Q4VT;RH6JMU;)EQB&DUN)Ud-`r1inBt1+BM{^pO(#<8f? zD4de!%5OH;IS>?4No_B2Xoza#2i+e7EcMv2t5=q7LVy6(^5nV=PcF%VFAb($If8F` zE;AE6?L$GM?_TQla1uJHO%Fp%DyENV{n~Hcm!+$>sKdP^^OqaieC{fs`YGm`f>HdK zJaIBA_uzI4@p<Ik|KSW7KNJ!E^~N*vEJ_ds8YcGvTB)x>;C?YzZh(AQVUbM>Z&9Jd zy;Z#J@T=5yt;=1(^OrRDxSrGhOnze4)E$Nbof-;IGCJ1Wkxpd(comFYRdxk$I2&<Z zg?{}lPcTn*n-#ISB!W}@iR4_LtW*2*havJNM(U1zy0mJ#gdB`<x~3_Ab-fckh!)FR z`X^rklA^hQi=~B4smI@i+DA>~tbec5GB!OB7P#XI%t7U_k<sO*JW{Ou4~E8`Nja?U z2ct$RtvJbQ9%(Dw9-1L5G*te5TzoV{eTP#5Mz?111^e9K4y1v9bNxKN^CQZRrd!09 z0*?CRt<cNB>_Tb1se!h0Kjk39Y=>t!uqZz<<+tt1r#|_yhc0A+D2H<&-J&zAf@QP* zZsvB1UZZbzk(FSHd=29u8l`-HVc}55hi<+G_SDOz_RIoq+Dom_&;tfbj3{ALz!k4% z#-cnLKU|Tr?{tCs%QC+1Hk{;!wcg`Hy&uV&a0^+Wzj$U<V0FmU?<ob~X`x2A_%#jA z|Fdpj_(=7m<uz6UsOUm%$Wots)7r{nPw;5E+|x=RrdNg^WLY>gmrsqT9z6qS1M8Du zbgxmg=R2H<?E5_GRZ;t9B{DUNU`<x#;<yu4O6JotPo~nZK-}1j9T>9_?`;$>CBt%K z#p1XD&s6%&L~jugl{{veX)BH&!&E<cqv<AU^!X(ZVW+Ppd+KWnyem$RQtN5s`Kl}3 zpL&JYT}NK)h3KkGA3+RKMIpa#NN{y+Vi@2}XBGx=X&_Na_@v&f6T>)YzI~T6k*>VM z*9e6Co-11Kxaaut{fN8_ZHDhJYZr5!Gc^$9O?ihzccnOE1ia61Y{+Lb!jF)t%cu~X zQ#-1XiT&=K?txwE+Azmo7$t^UJ6Y$~MmIRmetTnI4F{qw8r2?E{$ubvdJhXQ-}VxT zuryNij@JZLe+x>OT={{EO4<oEtr_Wwd?l2;ZQYhEQm^1AL2AFka$JK|01uxQShx3l z``)-s)GVU(zZ?>JvTO37?ee&#Gt?$uzm&!+b0p*p0|r92+KYa1dI39=$_MD-$-hME zM19$a+KOLvDqb^S8Ln-bA1PVeT0L8ry|%f>)~F=Bi|NP3Nv`!}<G&^p#`QyR*b&u? zn6jT4Yzb>&)^T^)9|tE2{%ofM#ZV+5CYd6z6hrHgGAviBZQrN>O&`Jp5H(<H`Tf)a zFQj<W>w(JMR(2B^4$w~1Au)$YITNju?XApzAY3okH)LqApguNuyNn73aKAw3sn#UM zmfp>%yJ)Xb>lj{t)EL%Ky@0*ap-Nnl?)6|c9ygXv=rcHL^dN>eB^&G7zWLz)Qrf=4 zH>}~h=Nav<$e1zRXXBQiF3TavSg^T*;56!gUO_Y>-C?B?JC9V~OyU(}<kjMHZLM-$ zU1AkME7LFE%UG|l05SIlk`OuA;7}B>VGhdd#5Z!hUu&|eP`SsmkPk+E3`z=Hqp}f{ zR7q13x><kzDn`|X)yL%TMtzoJ-8%J?WxIbNB4(rq)-kO8v?#PeJjyi~u3ho)Mg_Ea zd3ZhjE0KKZsGER4+OwuHQ;o&xiuG)L=%31*ttxj^9irqU&H5OUNZ%NJs4NXCz8Fnu z?Esp>to@4^MZNcGzVOvCe;N-2Lk6s}7$gvbdYrU@_Ym1{!E6GWJwdYAU~ub*x|oMb znFU{FOJYHvArj<ishUAbzC8hdqba#35kn%Pdyz!22?t6)aWvSlMMt<1mf%#me3h+y znT@Xtzf#g`r!%Nn*%v(r*q#bVXfhsiuhl4X&+WDK19ISEw(hLwKO=<GKzU}WT9aL# zIV)XoF+(_r4z=J4WUxup)fDkfsaLrcDt#S{C$hu43$mCt)C^~C`kKlXG6*A(Zy6v0 zd8!>z^COthQgPkDvzzqS^E%Xhp?{jy7Y@1f83X;}px{UKtK=%<veZt!_dwnkOqFTO zITQ6`J#J#|Z-9%P&9=8;*v!^_=KAi=J@%F-ksX(Q4LYj4<yM-#6nw_bQY@ewD|bt% z0PNG_mV5E;lW4Td(f4}5DJJ>D#Vh4>x{@=`MX;$)5<CGxg*FkY`&i6?9!vF>*KgK0 z=(sz@)B&H;+LFVjwX}T~$hEXyC_Yd$(;Ox<X<=7q7JKr21D!ht_HLAz)*!%|{1*0d zE~uVvSJcwwHVl!{=W6y4$ii7lk7w7Ju6P5{f@!m{fUaW3j1$Pb98cbEE_#!A``*tB zGPW_@Hgsrak}&`0F)v;b6_gXyBOFRXZ5Fn?y*dvZtrh+heM234yON=iUz#KD>P}bW z79NWZ`kDshmcR}nsV%|Lt&(B#mCit#CL54$cqp$-d+1r2nghJ`_A5a;qYc_b{0k#6 zNm06ed{0&;<AVk^o78vkO3A4X&+3WobaE)x{0^8U_x0A-{OadEJ|pT+Fl;q_0va;O zdz(kYPqoZdDYBMl=;x-8#X4`&W&SZ-$AFl=XYjWciMZHT=5X*8`UF(#o`Aso-n<o^ zVpG>B4c{5KHB{Rx6fDC>V^FVQGHuKn!EWI6z`BHJdwdOE39Xo{KV<G|>RslreZI_~ zVYe<spG6D)kQ6UskJbt9@zYL<E1keaCsnFN`V2W*X9cjEAfLBUWj#dR)+dmvgZ^3# z<oJM&=Ck$?xNiUC@3VDVctk5Xgpa_M?6aSg$5&Cpj!(=5tykRVW@3mC;ZUT!=T04E zh54YRmHe79Er`I4rZ|FkJ}rz7)qRrl32i;75%$Hs6&-K`{`vH~da9m9QqIJDbYEp# zhR6tv9zePh57=~JPrYhEtafcc^We++5Al+td5^2DO71MYL0HeYMy~AMAF>j`zppS5 z{}}+X2Ifl@>dQ3bK{;QQuW$Tn<?kKV#*J4R%;%!gVIKj|`j9x<orcIcSKd6U=t6>J z>nw<IvIjeTT?#>BN(wq)Gdt9YA9_x~N>Xcelfk@aR0A>qnQ{_laX1BTV7Z~#e0>MJ z*F*^MldP;Y#r#qhAWb6=O8^}_@_t5E67UJ|YyuPt{OEVyb9>sqDb{*5Fk9VpBcDa_ zb#F~tb)x?!<-6AvRXkrRZ<+f+qFzfd_52L_<h=o|NP??Qnk?bKqn;|nBpc*9jaa#S zxB42C&oguamZEZuzS$-900)>O;LbQ_vht6)gfKbIteGfle8bJntJLV^smJA{6B^8% z=B_?SV+UTQ{>H&yIDuC1&ghppA)FbLjWH#mggB@gmg5`~wQdmTRof3n<GzEYSPae& z0gzw)GiIP1{uM@c15uV7D5Y#sFP3)%mAMWos%bXvAeZD6BU~g0MKk2`YS|VHL<bA% zHO95-#~UDBPKtum_qUr)mztgReM_4*=>pMB&C^B_Nf@%Rvo13uQWV^tjX`7BKv8f> z<D)ht01O_1iC(geO5K<9`9Mm>JD)xOmG>!<0h2>!Ao-z(?p1s?CN+0z(Seyv`vY%L zh<Q}iYNT!#%Uat_4qi4&^jtx+di0oBO|iAJO+R8wbBi*YMKY$%Nw1HopHgScTZ)ji zjGH;+98b9mjyMHs3H6bi@SEH(YBWx|z~g*p6~6tLBS4OX8_WMa2+ofjmP2RjkAXdP z2WYp8V>Uye3zs8#G(TLI?sTvt$)1FYm+B`;!Dmy|`_0vF<6p`#+WwL4nHcl?o;08a zk+MAOIcX=2tY<~F0w!{N<!-m-s5;ne@>`rn_Ulr<&ynOZOHwleHE8GN(8Zk($ADz` zlr9=US#aP4(-Kw(1ujSM**cLZv#l_mWQU2Us2gKK4#0GgCatkpKE<3*VK}WsUD^DR zP2q1GiJ_W&+c>FIAF+=l4q>&-<do9bPx35(04oz7zVQ6b{>pg`FvfyaRyHsEiaDN- zRu!q$)P$!$Q4t)E(M=;KX++~j6YB5GM_sU0b{RKVu}+i&Gg5FDJE5F~zm4l1ztl#H zESg%tXSd=gmVbAC5ja$B<%X$^frX!zbb0YPV8BcA)}s;}94~#rftm^=U>nGXQ>gse zFMDQiEN0Pq-_Ke@G6}iu6LybM&_mA=#P64ByeV!fK6>{@cy++^KZUU4QICJJ+E0{1 zMb3rm$C5Krre?KYZ))Omxpz`V=9m1_H<Xl`9+k!7#4^LIxXgquL(qRMONIB_H~OZO zU(y-x!<3%04E5}Ioq$a17onZzTnjIV7oCmHe%pLGYGFd&kOfe11j;>?M?=Z*iQqr^ z`bG%7`yfKc)Xw*<gLAuAY~;Q;FuVLk^excs8%8!@>JcB;O<?7Wu2PQn*<@Fp!bLR0 zEXQn828CK1WXfQ?PgQX5C_m?m7;(tMZA|kHf6P$yyB3pu!LbXR>@me>b7iZy!F3}# ze8s-1_yJ(A^;^YgjKt~@F^TPlbdRZ|eMUJB{|P!8L82a#|CaK>DmwlI`|O*_w?!&) zhG0E6&Q#r}(zW_9XivN^o~?2}?-*&9FLt2T(Ytq&&=;BVu8fYkNxG4hFE`N3Ia?X3 zhC=c5;M_4)RGwj^a539a1z=^c$FJ0LRrY0+L!sH1_T|&`eo)XwHaVUgU>0i=JO{On z*n*w)wkC+87TjwJ1+VBsj;PNDG!4t%8eO(1u*-XPX7<+8+;hq!By}yOFtOD1*EU5M zCEhcpVfM8g!*E)zbhurq{h9~LCibYbs+;4c@%*Bnoi;8W!s+D&`Mnd~A-I!LpvF;G zF}X0*YHK6j+?w%9F*4|4qUhZ{tYuz?nr~j8@;werR0yVwaya-9u_7*np&TJXBmpFz zwri?g9h&&&+O>zSg&UMXODUu8@zbOJlkg_cb1G)JgN#W{!NA2jNVeQG#JD8*`dkUQ z>e^#Q1uiq)9XjrhUry|>AdU2P5L@oFBnw+Z-n3#iv9v$tO<CqVW7xL~lVbrGWXTp6 z#ZPb+a5HG-LegLI_EG%mw6ylYlstLJTXqv-6Dz$p`Cc^kEXjeZw_JDfx6PJBiTgQc z`Y~Ah1de2GrZ$0<F#ba_rYp4R;0$+?R<nB7JlvI$dj0ca>@eyz_b5F>5$0}+%7Y>b zFa>s}Fcp*oOG%Bu(W%`iQTSq%Qz#=DoVJ`?;|~n<EtvK6EbCW6ZR<s&A6-7T!@4HZ zOIwxwyu7>Xq0lxNd0tb!OFP5sh=VzQ#TZMBFKb{W8yf)drf;`ognf+|qZ-WK2+puy zVJM$C-Q`!J|F|wM4(8}@b1VcPH^EOch6Y#)Xp+b~1HLa_vk7B0YafA&q=vWkEM})M z`{jGZw1Kq}IKY?ZLe{rg`ZjjnyhfBE9qviv;+um-ZJR6koM6lg(Q0Eb7WMDeIt^n? zFj%~ot^jswy3SuOuA~q%&G6a<k%B$KS}Ju1k&dXWI$UMKI_9+bB4P(mUgJOP(({MD z-Jxb6E#W8*o1m*nsmKx32;6V3VdGBuHnl*DYxW3r4!b9K*3##uk&`z`pS2!n>Du3i zeSm1WdSb9E1)pzxVJd-YGJ=H%_A}-}^E#(%Ieq>!_Lv(x<6$0)(-vlX8@lh6N4<1w zh!alaU3oh*TVmV5-1lT!+skHu=i$5Y7uB{Zg%@VJKcvbnj0pI3Ew>J|EDJGS?ag;t z-)>Cs3<A^Rj)YU_iTKle=%s$(`nBc`@n0(jWy66hFbFNJmp|{<In(_^1!<8yjTARf zogj|X4?B@L7d_>DMuxeioGw+7MP8Xj$1j_qY2k6KA{l9ingnChb+t9bR2?;p`u95( z8Ew%uK*f;CY?XE3H#s|rq6^ykI|yBuDzUEs%TR5L#vf!}yTm)*9p)a<_p`{1M=!YR zoVYtzIQl3Dm_;m<4YTmVGf@;`nG>#6YCHP?vf6Hu*XpAXfq`Me1jhAv%c=0Agvw!a ziV;X7*?SJuzC_L|?)uGajwa7yr&yA8VE<wn98KAh^^bXJ8h;F<UnOchbKXE2ll`qk znOeiRY7Jh@f1hKR?Iocm_Kir$CxZZ42igC4`nATf9|w)f?~csSmE-jQIu{eewDfl^ zJ6;Dw^^pH?E2ZaFM(s?5FGPrr;7pW={^i7GOiv?k5Y=+)Jly{70x>Cy$zQ+(^CUQN zYf%hBkRG-zi3yS^bCy=rRzO?F>w`rzU#$ZJe!vjNSA&jymU@ZQ1Uz~aPas|dciW0H z@P$XX_m!AJv+m|gTC)8_5xeNcBeP8r|FbbuYxi(LG(4L^?FhJ}PR6X+RWjc|TLv`9 z2@Q6`lg*I!oe6?sUruQGvvFQ^=Fsx*1n4@pC>S~NFU|uFZot~gfuv($Wkt{&81|$A z)ig%<E8@ZrSv1ypvCJJQJ(rnd^!;xN+UR<Vv1lUfE6zJEO+3or69V1RsX7ekNr*t; z670+3X<Cwh;GFsk1kHCQb2=qqr3=;Ay7u%s)R%Criufs&aJg&9d7Btb#nWJGn+@8q zYH=1Tr@4XmaGvHgzqHvpZa=Xv_EmIUiF}on7+>DK3XQr!Li`GI8a)d!tSW=pyi-<B z09|$-6F?i<s07PIfd*BrZh){@JS$OOI@v0B5siU5yE$^KMU(*eVhxJjg$i!_t;Iz4 zAOr@$KUp9<2-B=oQ>e=wLlBm6+ve8>-T4+G#obS$k_87}-Dg08JR5VNQe0*Gi64Ps z517VSTkc0s$rP+_xa&#}Fp?b#-J~W{p4)}7)e+A;RlxrGS`xs&N>6DqxTHuhWaLGl z54vugbLi<{D@??R<`9<RkG<3xu|h<YWy_Y^?Z`<VcrL3dfEx|DBSlmYfMfjNU)E&p z;~$HKlqfLh{<oSEBg1fEh=$Iv3{qXAufM~n4NNC;uWdUpuToW4({I322J?@`qt2z= z_LF2yTgGeG@f?kNQW(CVlTNEtAgrQ!I_Gh2!1@1@@v4$Xg~4enFc+E`LDw~{mlQ$) zyi^%Tlk!dZ`&+R`3XRX=iyC8&@Yo0>;u!euK*O+g$~)1;$y_wqtu>#}2#J*;<AA zm)Hgl59*SLQQEz?^|s$1P(oeU+YhhT&}dZbs@AU!qeHn6@flmx`PAf3xuI+kYB;k> zx&0Oz|1~GJ3BVjEyOukR<cjDFoTcxi0y4F!Z8?M>meeZBtt`1z+eem}6qq4#nW6!* zGmE@*LU4<41G~QTWQ(ZFQZTC#6@S|lI+UzJ1PS4g{tiJBmlZ%l5$U-l6f|osu&c_I zOGwEhK#rGEzVOw_5Hg!;pf#Bb7}Bmb71|y>MQ92ZYN3SVAy<IUEg<PJLu53e`T`WT zt!4D**xdIj)S6P#TTc!eEJ0oUGVm5}5gbkdu&xMtgMbMME}^;2rKTw9VycEx2&S4` zw(D~eMhn(w8HdDygHYrzhikF6a`nuYxM$M&K^TT5KZ?b5JHctbOqvvW6~`U<?pg0W z+arkBk^%Xt8H_E|KM^^2dCQg**&y3hLTfdc=DV&=TM}X=y~XGyCJa$^aU8b%`2Gh8 zeGx3AB-W74a!w<kvkTGGYc2q(KO>wV)7?DsS>H4Uc(o#XAa+u0gTW)~(Ro8`xZ@Gr zFXIWCT9xV#!{LH1n^UK!Y*`sz=SpG}vEiFnM98_~MYb-PP#=|<#g@gI@{~-(5zaW# zsX+a)?>c&xcm}<u&--JQhtAe!80m#K2#^SB6vfhr`L(qrg-CL)&yWXHQ)amdKL0S< z(pzPguC*nMR!J39-sI)+leNu`8PzNa7de;1E*1eB1zwrSuzc-zv2p88XGP-14#*)W zz?OQ}Z#JvK=OiULrmdzSfUtbiw2%x@yEH<wA^VxqS1#*hH4PFPoR|H4KSLbgn%9iq zl_GBH7|*yrmf9N?4>_v0v|4iAjn%ZjHJh#%qF7Lqe+@~}=_C^A4?BspBhvo!s>KqJ z5FHph*y3V%EGfrqYVr}~#OAdmo@oCuhV(I!=xGg~c31~OoY9EzNf^hDD1o?20HLf9 zg!2H<ZAv;UPltfa-2*nKzzxEfn0!jX1K_RL`Qm}nf~j)qF=SA=Z@4$BX^Pm*UBk$e zD1yKmb3$E%6|BynA9=?MNC@5TSdiNwaIxS$RGsrhOyu%-N`)X=;n4l>GDVSg{HFdA z-?$&+I=p=^daz&CcgaVUTm^8o2E<+MTMg=7vZqdL2-<T)#wlL|zg;0cBg_(vCnkG< z+yK3FtbMZCxGD8#2`AkLzhm81sXmpXDEFL@V+3~-5)~agT*K3~pEqjCjf6&mgc}nu zfjAUS@p_|8$#0>!@co42mo6-N$cuz8RhI^~>~Hyi%i-+;UJ#SlyMzskP}xYxi=TC1 zM4%T6R)>vzDIqh^M@gVAD+=iWnlC}a@OTQ`VcNbSNVxq>R}PSYuwCDf-;u`9b?~mN z8{e=%cC26<9S~3M@L=nkHqxZtV~MCW;l<v8;~i2N44ho;KMUh5_h>RJPmtTggB{#? zhE2*%Ba6ao*PIWGFu6WhA*u2!7ry$^e(}qY5U=Kwu)-2VQYRCj;Cszc4VjK^H0sSr zJ%*-+uq18VU;IqYj(hz-FJLBBU@E-viFtK^&_yJVvH9p>Dl}As*Fb*^-rc(v$82*@ zJutWTWG5hiYVJQE&Za2$x9!Lx4(-4>0xn=bBm6Dwj9X99I7{(V%yxG#ItK!w_t5v8 zJnA9azpY&~IM=bFkZv<KT@IB9hxW1{1#w7mJAQZqKoKXYR<O!oAPry>K?y%3ntklC zN^*=*iy|lf!C`rT(jkK|m%H%yjM4<~7Z~518~NOzgGZB&qV+T>zkVc*Geftk_q1YY zET8tV<7m(k39%(aho$}R%PJ1=d?~|4NndTD7|CejOR*=wGDsL?uRkTS&8!Hhcb1l$ zM}HiY81|$&3}I3VVmt1J2{AlIzHxBKaeIyH_LO$}31Vp}#Y@6w=w(Xp@eclduHIi* z=k_lA`1Jc)lbRmlyNq#&co%8$KU_}tt$W;qFWW}@M_sC9(xODpAO8m_RCORg7IFux zzuX@@#BINZi#bTBMXlNYHG*%2!uiqxzGDq<x{<g9N{32P*j9@_)2J!9W_cm|vxgfv zexCJ1QIs#DC(FvbQhr62e*JTyRiYv6&g#cZ$?}Qv%DzjZ<SRLm_$dL6H_Q;ZbwlbW z@~71G<;M!t9*h1_yK*N*^XhB$WLd1fRJ^6_9548qleIWC6!yFFJ2c3{nf@19X3qW$ zS^}RuEQa?4yLX6sWcsfb5(>9Be0&YrR=K;K$GfzKYsE6hh04;d*h@2Luf=#FDX&go zk}J`uk{-lOGd5V}z-BW+*^WCG!HBjiyra+U?WLHAebo*-TsYu#4dtZ7UY^2>rDoh_ z-oHN{sNZv!=Ae8InjjKChIdlX-yBXW1Ypqs+OL3)swtIZ@5?p-dU<E5?gY~GOcEOn zYo<d)7cb@|MHSsPrHO^}xb}s)eCoh6Z5q|#9SI7MXKzoiQuQZ);)-ViR~9D?Exou? zz*x$EL?Y1>eRr?X7K0!_;V+*|ROB+FGoMA`@KAnlgONas2@WUL9mVt?CiX)!hd<O? z6j|SeZN)c2yl4NrSzHD}y!#zzw0=(5=e_CKGI#*5yNqdnOa(q{jgraX4acxO0yS4} zL4lz*PqcEJ7&!3e^~*bm^i?ULT9|)iN76V2(!=K>WtcAD5I}e85A%~63(ccS-P<u0 z4U}kdqU?LRyJ#<=gK{gx^RgF(v`v?BUj?LzX>=I7jRMP?(;{nPK!WReS&vf`OqT$6 zTfXS_#K4VNKqXP^QDhjQKT7vdFc;$%81<gGV*+nn9S$<#i3?k>D~+NlJ#wKb3?-Rk zvpu1c`O_us%<NPW3WB8wGOE#btV{A(T_iewFGujOF#U$cQ`IRU%Bz!}&FIZ=x(s+0 z_1!RG%H^8FYeng-gXVTXTLP`q2Vp0t0vIJ3n}L@eKd<O=nVDc3&N3m9?w{=R-E#&2 z(NPW%q0Rc-Rr%@r#SDAZ?yyw2kcpubfX|+bTzpf3O^P()J9$DQ!0<%B6}J(PZq;#s znNCuR+2np!cTc4DA4lCfTxkzR(GsG){lO?nPRVT$2es&VoqUJyh<bmv0XL<8<nkhK z^4Dq$M6p-PPwd{L0@K{&t`sea*UhVLD&s2_kgh>gav0Yx(I;XO8GYgWixF3jyC^=l zwKOtKciJ1W{ajv|!a$d$F-1X8GhiEDKcB9M;S<+yQhI&~OMV2+@5ySy`794{$Eb=s zLvk>e^y#vOxPozL0~^VJ3%A#!oUxBk6v2y0i#+^7d-Jwx5aTv`{+|<yp&47f(Rw5r z1g8**@Dz7=_zt1~sb5{e$|e9^%1WKYP0`q{nrwMU6KNb(RS0Wi#wigtX=-fx9M2}8 z4<b)a#7M*yIrl)y6TEg?%`Vrb0*YN*mIHzu+gJKxS`BVss<>pt#!flmB$cBra63h` zxZ~3tZHn-xDzc4g0Jjx>8_*+s2Q!kb&jsxn3=#zqK%eKrYzM1fiAL(okhx)eV<v>* z93&EKVL`ax(7!6+nBkL~A@{9I#~$v~ACxlc6$!6P*r=-_RgfbdVzH(tSugPd1Cy<T z32nMf)m^Z}$`gB}AnQ6zwdRk}2xh+oaZHh&rMCdJkLr!Z7FLz(fVtC{m+Zg5za(a_ zKTeMGtppkt3y3I&P;V9mD*mi51V)UW9A$hZR)JIueiE66#(K7>)AC*!HI610F$t8> zN@wJ4g@yuvWm4ZQoDgVuIDLa;83)J_e;8`8luC0l|DB`O`ny*m<;dtc^h<aRp3(S+ z$@P?1MB*er_kUpReErECl8~SRy*+*X_=#G@V6u>`3PFGGxqFYie@xi2s2ASF48&iu zp0j7>Uw+eyeKUV^&da#0QK|9NgF|A^(5*a<0JF)h%)|8`L$B~UxG)7eayO)QS3Q}{ za?^;B#c}}x`-1mxsQ*R{PP$9o%6)Yv?e`SP0y!$Hu|?uS5WBZEP;3f$fKhn{TQ+zR z&sJfSvj*93blwyuvc-F8*7BC9dn?4)I_*Bp9aGLHW8O_)y<aI6*=D+c$;jv|%CY+# zs}O04s>VhGlGWLW1-cmgtP>L3`Y+mjSZiPQZF5g;zE#<x0>5t-#<^19RQiOmAjsm# zcNTure4~e;Nv?V*h%;+#AU9yZXH=ahOumGzcE_FSgoqdD&|O$H8{5(tNzmc}8H%25 z&!)o7cF-ziBe$1D5lfEfr7Zyw8qe)(b9rbeuzl2B-u%f4TF5NhsZ}QBE{nySIB?V_ zkZ0K*+xGlpF!eEHYqmvh*vCYY+$&L)b(D#jU+O)9H?u0vI(>VFdc???(vPwW6s=qn z2pN9d(^$^($M<&mFP)O&O|W(=Q&8S?^=30!>9y?+9gCmMT6oR+6=Zc)%P}ShccGjW zX^pX;qZ;Hek+evK(hRh+re{hgO1xBUCD-8B1*nHd9=3c&$II?GJC0%7ds(iT3{r-0 z^gqrSdW8O*j<IW&mCN^~;0ZVYnZ#0W+lE;stan5CzhU-nuvmdt9-hA}13_lmFcJFb zN`hB#_3m%hM{u-0t!g6S<7AjrbfF>la|a<+oy?3K__=O6B<22X&7{}hGA((2xGA~n zx|mC+^A)Sl2pYf0j0RoM&0r|0-A<eO11LJD;L0i^Jd$y{QcbZ4fSddd)%^AyT6B_W z+JG`+oO7f_w(4JyX|kcfMV432%Q;BYqC(x+M*s*Yb)9NAZ79Un3aBCJbL^X07@8vC zewjE;uTny44YPY${t?Y%Og7%*ML*)?+PmY?hlnoF6<98H9*FPFWh9O@a+d|PG^v|o zzdErDDH91>C}xP}9Q%L-tntNj3#`vG-U+NW;!2|>Pju+EUnbjA_WH&#DQVR(DmA`D zye3Hu1c{(&4`(mclon6}nGIVzDD{bW(raFtIsT)L^cJ_m-5{mlwuo8dmn~wOS7D_! zivU7MoaHhTQ)tBs@{kO;hK^U0GI_=o8+Bw4NNx-%<U68gktDdjh`k}zM}bLD2{Q_0 z17K)rqbr`tkEZtY4NGW3KKH~Os7gfCdYPml51|ZvfOcnHq^u*ifssX;B)O=j=N7LL zUjz84R;*eUjaN%woq-6M@PU1aal(W}H<P4u(*;<eiZ-w@$9wZsXy61w_OU$U8!x>q zV1o=U`UjzqX<Vo`Q^X_Kl4FDu4tmr%+E;&cwDTfP@X#jgs@oTNwsV#Y@M#vVp^{CO zqe%%(enmb2Yw;gmnEw}n;V1mB%)jY&p@wAbT1oFkZ-vF%BTjqeOk-vT1LTqe@<}bJ z1G6%<!RF6@!TuYkh@Y97KLlf!&<ana7>RwyY_}2vnc7zH4HwF$sntracVYzaNHFtH zNByN*6CS@F9PdJ-j43*45hgaP#SD5u937JoO@;cK8{ST7%8{J5D%;@a;YRcmBr||V ziar2!x!nE1HOx9qWn|_*dJaWR0`velU|DAtjyvKaqmP38wdvc8(&ji$LMqX|oGChQ z=ktZ##AGxP9h?_Ksen@X;UqC+L>a~nYTtX>8nS{%hfNb$AOofi`SRf-ohTZNw!k<P zi-Jx#UXHObPBn7@S-Uj}hj>-jd5JRl(MTxn-oiyUluaa)urVuN5hiF<g~iHJenwxA zO>Tp_1$?VU6~CEswx8HaxdcQGs4A|_Wx}`iy&Xfa!<(38os~#ff@7X|@pU90cM7=+ zG-Oyy9ZNS3FR=MXJ&bjPwM=Yt-UM7p&R0>fF%_xdHZ9c-EUnjPTY$}A$dq4I`t$-0 zoEV>NUfNg$E5Zq;xJ(!+&pN)l6w~lRBaionK|Vu;yk3}&<~J$HsY{cjLu%eluiE+- ze^u&3<z+9=3!#b)5BGYK(8YW_S8;Fy{_>k;8z|i56(yq?*ZUIxw7!$TgzY!Grxa44 z3Yb3Ow@&^_opUzRh#siQpA|~10dxA!Y7mk9#Q~(R<daFf%{XY0D&BUREl}CUifgr@ z0y7W|IkeCmcMpFEMaG%BG6KQuHbRS<U?P<0ePt!u&>>yi5UurhP5iu=QMARtoA}@C zPYTlAAcbRaVPum=ze*9SU@j0|o1|m&I}2mqcCm<gyz`yMX4leEU06OgtLB~R_K=b# zp$<=~b~Yf#Umm0=SdXKhga!lZry~p!sabAIJ_zBTl@5A_mjObz2M9NyfQ?1$Yn6^w z39p!7kO_Ii5kcl4Xp9uPF-@X}j@$2_&t3<H54J>IcH^ms9l#17wv}FuaLM9DAqa*E zCq7tp*x5pIJ0QRmW%IBQ^ObTZxhl46Z0Lk~UQuiY{~bwo4n3Rmu$5I)<qkRzz8;ab zCdH8GgzymEMUaMV5ZBTkaeI}O)9yiqVFJKWE)!be$))zoc#kh(#T2&cn@FNkQx<Q= z>#6x@zG|xYQ3ynxKL5t#X0_fxC}I;euOp#8bXII#m#%KSyj=Hz@@hf>=KwaIn4u`) zSR0i6&VufdTmL?76wQ2Wzv<I~Pi1gWpCbklzc#o{{)!e5+0SZ?O&ir)Z@3b+D!epT zn#nmj`wHUzm;7E0LOH$+!KW?EHm(3YasI~<5lxWV!qZRU6r2C~6s=)X9;OBm+GWO= zZJ^0DdTq0+ket~poDftvL0&!Bv|KisK%LI^qX&2)nhMZ}XL20-$s(@rUIC9$?%upL z<b(3Ss0W51Z!z?)E@6O=s`Bj6eNBzhK{6u$V#K5@!%&v(iL3b`2okI$vej~THX@y3 zx1rwP6BW6lw~t*H5}07}uJjcY6f>8~=L&!PKh%gYzJ?XnB*4QeO(r9bAcX4bMLeQI zGhCyR-^ny94zCUGlJ!zl*qT_<uhFAcYKZPMkn4^;*5<6$NI&u|7NT~sH5}HnB4Wun zurX_Z8>3=I>1tW=q01M8AR12ocwhrz6>ok8_#3`q7&11&9-ynF_1-ov`PF~O!}anT z^A-oS;ssUEmsd`5QfAQZX8nbale*Sj&1w<iB{|H9G<kstNIy0;musYK?szrOQGf_G zM1)4Nan5T_ho{9z!|<4?8Tdo?lD*pMoBO%*E86NFcRAC<03s_D9}Ow@_Va^grdnDL z441MFH$b!cpLSK;@|64VGYE^nKf{d*3gRLKB%KAP|7~%+(C75GH39ay1KJv5&2ypN z;>^lsrn)m^MoC_$NZ48;%sBr0b(fs0#-?t5s=ad6&c#OJN32FaYy%WEfNAlivMBZ~ zG0ko~HjuZ|JkpDD2x5~LD61=<+zVkq>qy_RS{l?kW=zZ}UoJl-OAaD#IvThvSBDA6 z(ySxN&AR4Nxl*_?Y~q#_N(2QnAzoQ*`y`2P9qn{X@o9<E{AJHdKn#C)$liJ;jo<!B zlExc&ui%u`JVSh20g5%yQ6i_3?`=|anRdvUU|r%UpOnmWNcZy@BAEeQ;~>TLVY4NS z>6)W8c|G#zR}@HxiVFX`Fw|{Of9jmPM*0}kbce}FRl?I4RP5kbE5(Gpn{XwkhuTPh zJ^{O0i{)LyCYtI|i-aQkG3Zbgx_tk1`c$q2Ya^aNgrqqXT)e?dj4}$Xw^y@=GPOxS qHqhP1fZ7;inW7xM74_KLK()q*>ZRdnkFLb!`*A3)8YCBwchxj4SGn*2 literal 12304 zcmV+rFz?S(VQh3|WM5zJP?7w}tAx!>%sQYJxi~QXtZ!}|@wY{M5utq)kV)r~^s|f; zF=WAY;UYJK_-yYwg=Rw1kg&1xwU0e>LYLdOY9-5mkB}}^VL!zqEczfi5T~_IdhvuS zE1cu5(uSak$u1xbI3V!OSoLbeVfSubd{ag!!}}?1DhDNUyz3W7D$IwkbBr>h=`#vZ z<#dK0DC9ZY5R<Qh2gR)Wxn$|EIAW;WZPpZ$_S{I25}iZt>9OCm7?XJd*{wqa;{+>H zCMHabxe`a$*`bvlw)Y%|pDPxf5~MC1aw<H@kjM|Py1#I!hh2ly&AR**MzZ`?2rO!2 zQOv_g_yR2$W1q5qZ)_(FeFHyFW}2V5X_8Gx7fl5n7jF1rf9xuzX!x;FY<0T#!6=Ui z{;peo+iCBs4hYYGaEl;=Wpd$vC_w<v*%|$w{W(n{b3PEbPZ@m1-H}e$eu+x;|FIRv z+y^pbgJ~{BZ?QvDigmyGGe^$q2_(auWz$w-bA0_^8-1lnu07~=KqB*klp9-&xLnGd zf;i_Zk$&(T2_ogWO(l9|f?3F?*nQF3%T19+K;n^;s6}Ty^P^1^AgyRNC5^_8qe=5v zcKh;ViVY||5>@k@pYu+_jSL<7GvSz%bg}-!t{_(FsN3e|4xy0Go8R0+#r}^6#ODpN z0*2apmOZ5X;+Y4zK?z*=Qic8BFd!O7YDRE+u$qGlZjMSRZrq!*oEE#}%-;)`Bkk?b z2Pt<sr&bWCul-T#hiGx*2AX{ig0&HbDb`YKPkp(wnzhTLAd_SEVis!F(-t?p13?Av zhcp5O+M`?3|1bI4beWQzB)tn)f0Pn4s{h>IUw(QOVR$C_*0kydh73u^Y+j%Ake$DQ zAhI_n9sN6QB3)5#dI73;I@StJWZw&p=${PU<rxvec1=WbAD)D}{ow+_GeXMyG}jkM zRie#j`(Hh)%Ui&?eSOt{T$|T$Z2cIJ9ux4IMTgkPOzH@7%T^w4q4PIziXC`ua)k;) zs8q%su#_>rZIkud;r-^=?sG%I>l?HbPj^<3NyC$=sm-2aSQX|(xm{}y*U!ARq>O9( z`470cM02yrj9tz-1Gg@<OQ3k)$QzA=!FDa4enbSvvG1RfBEzh+Ehg9!9ja{emX{0r z6`bman#SYk;F}ZDZ9uhWj{RIiIzxuMbWD{+wISuSys7w0ULdCx<f!GdjK|&xakh2f zRHTT&WN%Rpwbsi=l`{rKkMv(o{O~jIl##egCBZGra<BHzicU}oH(uZitBfH=YYmU+ zq#lPO`?YrMJ1_s3w=(2}9*LMSzjXlp5t-7t;1!^)&=kdpA6{N+C`%nLz7?2tJqU5J zr(^RviTXc~%O-4P(rfwBhZ^G#)NQq<)=~MD7W}2@UjGF8^)`g)kn^vlu_m#JPkw6S zoDZhenz~i-<<+6#bI$8JUQkb6LOzRNVC*i^-b{?$)nCB<aBsGeEe2)7+|AC)TVf%c z>q=Q_%C+|j=DN$qDD9W%<Ooy;%bTiX)f7u9^B6l7`F1p9dVgXNiK4+&Xi6)EEvMTt zj5~G+8;~;Wu~&7Nt)^o2(P=--WMc$@ug@Ag>!#DYVUOf3n*X0eNhJ=htQMQ$pY6*D zX&b7dHdjkE?9KDj29_ZfI3b{xD8UrA-b9BE8iTggI=QjxQ>VkG9_UEES4GI2U!G@D z@f_krSgC5R2ZjNcPU|NWV`sv4S~+k-D4WJSGoPD^)7xO&T`@U{T}y8FMoNNtpaW7Q zYN%QXpD17D4K8C*R7Vdh6Wz$gO@Sw+RpH_k{Ql^%;5OMaeO`}G+PM1VPFPXoq`h(_ zK+ghHQ28;oZ95FIPv)j?xKFQxVNnDB$P?X`9rJ4&eaX0=SY|}_Lx0RMx5e>?A|S^7 z)i8ZgBYdAT4)D0LJGQcc>AjoB2pA-q!5Ox9x8VS-jeX@KkIUxPWh`JW*&@aIQsm<r z^RvE2b{YKZBRxBJ(E(%kdXTluSE9COSfy>1{AHhukKjhjG;HoTi8$d~ggUM^bhR!% zn4JMlH!1ln7f9Q%w}pO*b;s=D*tqFE4vxT)Od6i{cZ#T$YYW!=bI@Wv!R*W2{V~X$ zxL$SER~_fs8<3LE{(}j=sM8m@d<ayuYK8VpxOo>SU6*5tLb<>Ib2@=327&k_J*GZZ zh{`X<)FYUUEk)cRIiP!tn&XVO>6M0=_LP$d@~iofmiLNOR7C->#>T;U$)Ugu6RIch z|CQHTAT{8RwAWSagK_;XsVN!08w*nq@bt3PXN_#`Qb>tyqjfKaFi87&T27Wu4P3RL zHRkXB)qIl=pl3prAwg-_7+jyQb?kDeN7q01Z1K8w!Hu@oq91r!G=5fs0?}+!%jw6= z%LeJ`Hff(c{lbRL3DAduRgut(NiBF@xa8XDq=toK7O0|?DVg(*;QJ!BLbp;NV**~H zhu|<ZaE;b5gTdO)3^{tG{I6jO9aCoh`K#I^{i;k_XYSnEcJ~5HQRxc~bq>Doe-x{l zXFxXte1h+JmV1_5qX85rx$Xw9KQv|SKzCVqdnpu8VF9Ji#ozdt^1aIV>;?^g#JczQ zOwXN<5b^gHw8dc#IrdEUUp^66#3$n>n<<!)O**Owv2x=7O32TZ0>xHA33r2%8+9g; zouc*>MH=xLx23pO``>Y30wNzlXWR<jyBtlBJ;5_kojmsDXUUhx#Jj7sLarHPuE2X^ zr-a*HDL%!sy;FJqKtWm37PXpKs%1gAL%8EU=Y=AfP@I1Q-c=DkHNEN*?`D?tF}k>4 zh4?{(i!wPq2@fs3PO|WTqKiteR%YLW%*NHY@vuUSFL5V?&-E$vyk3d>$JU*9PTCnf zZ*uy#VGbmrqpb`fnRR?K!kOS)r?=SkMD6Ir`3)JwNV-sPEgm+$Jr&pA{Nqw(Ry^hn z7z;|%;bG6jUWzPoud`6AY^Dk=-&Ss7R6sJa!xePGdJHh&?R%o`N+YYlBV6<mB}0N% z6yu*3VV}(PD<#u>(+&2GPjxgPy@f0K-u%R<*uhU15sRsS!Y1zB9h!jauQHmBL|7I5 zUa#IS_mIPDdY%e*R<K3QlX)&z1g6x_uMc7bK|KZKR>-T)b4B}R{-yi@x)RWBcq`{` zLU9~UX8rqrdU9Id3*T~1IX<d)gXQmRv!r0oBRxd-1AFGUE__ZNa~#UM8oXqnuy<hR z{yBe+mJw&Qb|**%AF62cS{pO<>$#Uj0EKo<VPGA))Xv_~gq<l8d0J(vVp~_Hlm5=M z>00=JG0YMH3aZnNVoFVd^wpI_N}@*$A3=x3km!Mcbkc#LL{w?(&wa%_4SlGz;qXwQ zH*?tnF^y@VL;lD!VRh{B9N&^EbeYu8s(9C92_GfqVI61I@p>YKO>B{q@!LiOlAR7V zF6cXF%xh46gJw(K*FLH;PLk3yVf<%k3K!=DE0&A3ear#K!s$PVnA9~lY9L-AZVp`8 zSg@F(Jhr;3FB`AcPRe)1cep1}B$}o*VU9geCQTT^uki{>{Y?#GE}sc&UH9$OF}kaM zR5~!y_`k@0JgR7o5Slk<j%Dutj8-7@s~N=0*q*1@u34PosAcHDQCg8Vq>t19E3$B4 zs6>PVq|*9hPIsi#o7wp4xgEASSQUe*W`vZ_;g)4jj3M9`vX@{mtpDvWSBPjrM~|HG zo3*Yqme(C`9;oD{eiKw~N4Hf4c&KoKgKgj`yrWOhPJzJw=j<S)>g$|;*~Nego$#3s z9Uhi`sOuyn<j=9@MOMyAXyuS>;tZQN6?}uol~`8?mbCT=h5;h#_wylyb%Rv2;*7<2 zhN~a97;81-0jHwFEH+yw=wN3kHi$9?zHOdwO*uPie#4ba8+Cw-?Zkk^iLdCpPWI=O zk6gh3s@^%P_%)U)qYVXpQUVt$o)-4*0el36F0G7Plc*QjIjQBqQrJ~ar7%~QsciEj zO_+9R2wkk7dxn*nCGVWt$Kj?P^V?(fIz~*tFj6>0cFc>oyW9m{66fQiC?zBbhQrVG zP6~jXJ0qU_)Uak1NAiNX5QGM)&`F~8zy_!@k@}9YNTNT&difgYF=G@dUJ<Q1*`X#b z4X$h*N=9n(LPJHBHU(lhF-CBI(>WkNhj+PxEe?%{shEuKX-73nVg@O-1#q@uZs?5j zAo3rBie5bU5Hu0j{~KU&>?*p;n=H^X6st3Khu}2H1KzJcC7oMZpg&z&Ie+IUO1AXG z)5zBS0CYK?0eVhsbXN2-1eh!wAmePpL_+()D!2i~S3)5vY?f);l$h%9;<s99WhgwI z<)>$sYUlxM>q3(NjqL6SCx2mc?b!V12RUkXT2O5(&3<e8tSJKY_RQW>GAUnD3+`px ztjYsf4wH+;j{M?U;Jx&oC(iME2qk<O5Uni9k^$leq%>8HJ7pLvQ8p|Z7_Dzr^TyFm zVJ7lSfX05>pPwtIi@55$Pw}i}0geL6Cf()j&-?MQ^EL#Y0IpC1;Uj?fk4iUP0#dSA z{|*Fo#r}RUfd~}&c)O7jx1d$Net-R`i2QwzRH~+-!d2_pcHw$DKk-HLQZ|0E2OxvE zkh>zz_T%#E59v;)*=iArzEaY|!kOyobZQ-XOD;G)JF1h;hSc0KZmD!@kY`$3*ST$< z55-+@7u{Y2hs&B_;K+)(<AN%`qfqui>jWQQnB>+I!$|(tZRp9?(5e54h60nBRKnBA z%Q@KPvYVSvb(RO&$dRBw|7neaN8OC;RoagB6BEC{i7FDBHeE$c)kTs!7%C3yd{?Y= zUY&4b5#ug$WMeFLZm6RZ)4{{O3?b<WEAC&g*2ACRRuN;AUU{C@M&d%hu8|e?TXBiz zT{GP-FS`-^>4grpttd)G<#tQ6mhO0oa9S0NndOJf>El~6*XMKD*-q}=crU&upIy;! zdok9T|C#F7^#dZ!ZwtpTJf+E@wNqt%+(_Jig46gz<W~eAbIvfCn51Ls&TM=ah|?)8 z+kY&&C*89jeotv&RpJ*n)}GA01-6T`;qhm!dXPyG28B-QRoE=aIH+YC8CqxI*wvbN z%so9scv&tRd$gZS3g0cwiB5k~wi7$15GA)oV8S;{Y4CcZGu5>Chru(f&MIr_BV*n9 ziELV#nQqoUUtWOT*0yfNiX8Q6)_(n8U>Q3^SH2;sRtu!@Z#lKyx+`&}yW7w@!_HF! zxpX%>e3~jnO29b?JqZZuY&9x~h(tAkk%JGfjF4e580Bu43m4%;L%jh!wd>kD!9Yv7 zO0p{hO4U%r<l#kLk3OGqPnfc0wM0!60f_e|Bay=Bnxk(nk?3keejNcG$3FOf{e@sd z8)eSX%Z`khMA0RKSZ;R6j);ikz+q5-jg~}?&H-2dahhE5Iqvo@1m39FUw(_rU`YAa zL?S-&KC7zdYS{9$BqqcEs3^3ncXY>l`HhKC=@f<Y>2I&O%M{F*=!tD;Y#Qoj^YuyZ z6)=T&PoPZxWnO9R;8D=RA^RBN<tLHxKU(N2@I8!^=wLh|Jww@{fyYP5a|npUtpU;4 zHUre)WB;+ks8^*E%6AsVIBAN7R5e>FzJ@F>+9<h{!fAuIcil<+#Ns(<r`za<qrE)Y zUhWo3JJ=s&iN*C1T`KBX9@2tE_e~aQ1_AH|%~0W_s3uz;H3L(&sFuy0k%B$Dcj9zm z4`&{XI@;&%^n8wNVX&*QJ-w1v02%6eJ4Cer`v%Bqc_#+_5gLQ|O@@NK{IkPcrSpMR zmbnw?=(rPMd!yv^fPV*+AxLWdkWqiT5l+-pvI1q<IruvT1z0}{!g;5WKI<GV{~kuw zVc+ZXainDP8!=7|s|u5G1-PFFL%?w|8<6ilH3mJuXC{6%=5C`K=N9a=)OdHGXFT-F zPTXS6*78lQCsVj(`=VM-E%oM4JX2cCOE@WtWwJ>__n_9dmDbjDwcbDVpb}a_B>l7* z3b8^Z(kB}l3}{jdt=(xZt$*2q)gydo4=(xnbS;Zp7I;#GZ1@rNcL4V{3C&pj(x-gZ zMrSHOvwt7)EXJ3#`@2e&diVT-0;>rMKJ;=JZ<8RkCI`wM{TqyF<3nW&oro>DF{4f$ z+kP4-gtWxO==GVRqxk1@eV^90ZFEF>z;XcdS`z*|^I7YZZ7eCgOmQ%E9%i$}Hl-h_ zaqzKbAA-4l+ttBSpl3qDm1(I3W6vDL=!eXDk+%#-#{y-fK5fGL&Cp%h@YVEH6q8rK zzDCo!CU`~@By?sB3@j<jSu@IY@IC&%fA2<1Rd6&)pJ!_#MizOLb+rF4$R8_-Nu;|% zV>ks)H!ypwRZ>7F`u!+%zSAg)>&=q!x9?OMEea>@Yy=#7nOZzFsI1oLY6z7+X3n5B z_h^=+i2YZ3o$HOsF8P2W@@pMVHhL~Nl_)nBejZy7_hf<*P6a@hX`gMQZE}lUo`Pa3 z$ypkidFn}p7ap1ZwJ1%PZfALA(?0Rg27KIj(8t|B1fui|@=97LFpv_9!u>ir6cB7P zdb<jkC^Q0O7}aUUU-srV6f8Ge@Hn+~pgsBiO|ACzvV^Qlq7q75irrh)YqUNa-|+n= z3%OT>>b}@0+aEz!<bGcq>(a>TCd^(7C1Iy*JC?Gp2FfJ@W~K_Zg{G>4%{BvindfB{ zCm1RYPQhvcr0A?(Xyo;ZmZ?3g`t&QMPicic*d$P_z4!<X=91}>m^`O%>5R>!^U!{_ zk%lX1C{T2o3rCQbt7Lj>Dw8E2jqT>c^Y!{G5Y6n(G-6kGSBR4$O~g)t+8O5$fz-9M z9u!Be*BZ1U9cp8Uq|DPFek{Y-_EZirdyhHg{baxv?cN_pI^um*($W>5&Mg6d^W>IC zD62vd4QtFt?P7<ZY!M10%LT#;LMyzoadmb|S_V%yEd&$Rv#tOazu?W&QI=yT>sl#i z@aoz+eY9bF;3<h3A3nbTZsw(xYAHie(ae3%S+y-<Wh#1zzU+nPfN_*E(lZSN+26!f z(xg`#zXJU^F;om2^o<7IvrXbSf>r@KhqbbSOT(>|2~ttdN3qtS@WN42A(F~9u*&lo zQsUCYo!b2tN1^g1xjBv5W72Ev$XFoQF&LiweVEX5R~m|!TR%?{YCz;tA5w7(1rRf4 znm#X6I>aRO4bXN-s=uoO-KxNEFe07V@OOye;0D{qm_guqc&x*_M=Dr1`H5@8GtLkv zE(HekFQzQ0xGSKwmKoqkEjMnj_m*9TA)OUn_ZYvCKq!VZe~YtvjehV!Pxs(jNmZ=w zZ%@SJ3a#Vl-Wjt!AdSOC&xSeQ!!bzQD46xsACjcJ*gCv&uRZmvp*QP%NBNXYZ0ptw zA9OGq><%%c;TSWx$5a0a2duqG1@}ANW8_CUstAm~%q!ML9*pF1xsWSqE5Ype9cPLZ zTVv=xy=AMx!;`47uXaFdtPxi>tU+}3E>pn{oXxlMA8yr}m60}}H;sd-@{y<gRg^!# zrt>b<7Wyqf<|1vTx+rYc=(05{hS%UeIZHh9o$wtXHQ$kA|Kf>N?SdTQ74uJAp+t}4 zj5zWSbQ8L<vGMy_kZBNzp#f#BK#nEYKL0w#qE>1Otrva%l+aS;gzbXD=3c9)&7EA3 zQ3qAlFY<znK1k5CJD`b19qWVqS;I_VXb+-Ke?GZ5Q#o;MA=0;zaj&T#_pf{%`9Azb z54CJ<@2Ay<0U11Mf8kpp)%QVobF@uzr(+RiqQl(FSN~^1=RX61ohKuWNLF!u$-|wB zbXB_g=AjCifXZdk&^22Tm5LKu(B3;NA3iX<UPQb8xw5L^gs`2EG_I3pLizo;kKVQ; z!#3EsM_Lm+zca6f%R~_m;1HFaeNfvCBL%u|*|b$4Qg0*puG-BemVFeulpF{Ics4ZY zDWH7$AK;>#yPVb&@oQc`ff9>4mQnI`0KSO{YBx!$iKM!*m6_{I3X|gHin^{q&IjWg z3l1vG!X-x65xcbrNI7cB0%IIcyVTA?_u~ng64xRfkkCFzg|6oB_0`;GO$<LJ+WrU5 zz=R@;_k0VOR|Li7Rl~S+kcIszEoRi~HfuOiAPOKM(of(W74}xZ%v?HlA}qnc&CUQy zB8*ZHX`(1wtqi(~ld;%uJW~aseY4L;tmaE^y^00MSm@5qM3B`C4W6t`@r{w%IesIt z9&xbs6&m>)xbDKsIKqZAgkV|7MtsgnO<89)4Twj3fwa#&d!e6d)XX1Cgf8g4UL*oW z%g)eWg6sfjBojxdR!)LsaG>7wl^4Y^$xP@_0&)@}e^>h<Z{r(J6XkRGyhnZ3@~odK zeM^&A`8u9qA@6NUevTC(O6T%Hj<x#|)L>g2KAU+1#HaL3GU-pzVy@W8Gy4P3REV4o zp8=1n!9hg}N?!?uB&LYJ4O(<c+j^-Ak7PB83#jfS+I+3Pd=$E&3nqjbu~4Vqmv(}c zfoZNI?1_D;fP$;6pB$!pIDci*sMJ{LV>f!3r?a>rEx*+>vC_=bmV6X*N3%haJl-0c z6=HzvvRc|wOI@~!<1>0BV-Xl~R?g@wn<((%O+Ehnc>dqJWL3_kO4a0ygu4B*(YgC9 z&uD8}x5O)Gwkg?}*8!I+)6tTa{X($JJ*)SvJkq4}f8gGd#@+S$`|`U-eAl|v$U{oZ zDG-*>&wepic4>+w8v#OY`kfX4BYI)kTo_v*fH@A!)4_o(YX)`P6A@m%J)2iT;mT`N zztiIWV+@17!!F-0R$M1)9giim0)PEIc7Sr`*p>t8=ID|b>jN<be?|du^+g~)u7(<O z+sh$X-iTWQUJ^q77*N8H+fq%~Ec$<DvOdN_#vg?)j;g6qR`{Pj%4or=5QUUbZ<r<% zG-1U|9zlTp{C-n*$AfUJn+eU@`}-`cJkLlTy?R$##hG_s!WLT<>Z@JPz*YPddxCou zr92oaXoUudjHH+8TuL?b`OQZ_nQl&vvHsZbNW<Z>(Dbzjw`2Zlg4<|NmsK)d@oMa> z)|h<dBH(nl3bh4<udrJ3|78Smq%cSu@3>OjpBT||zyn?~)tSPwI*$^Yk2Q%k!2?h4 zF(d|%ag!@+j5Cs;L*M;05bNGhP1!Rd9zYcA&vx+@p8l1!Wu?&GwW|+X2q`M3a?cws zjBZdj5&mbD%+j&CfF>GaaaCI>*CjRb?J9!>Q#WM)73U>r7mrfy0=}-=3_xt=mXSvP z1_fP4{F;-u<@iB|#t-+_tkolCE0DT0;`cr5^64)Cv*Q!W9pV4RoKU1L_r0@T*oZ(H zSFW%`V-wh2mJMsvW<8;KLT67%!jz~AG|tt%`m($A`8`OjbMD1Cb~g3kxpzLrTDc3V zQFa9DawvZLSS{d)5J&#mVJ0BQTM7+atyMWxjHQ8n=BEZ~wvo6LWS<}h2pw($gCZ2r zxl9UhCO#;Z<@bX^6R<_^9b$K=Un)S0A~EgNS-`M`G2c>7HesAWFtn4w7a0hg+Q^Zk zOJQ?)0}2^-2!*_NmxJwd9}>Gd<K=nC5}&pkA!qASo&LI`F`CG}QePTCG4l2|F{P{l zNxNx5{uSyFW<4ZvUJ!fpy2t;pjA5^h{S*U#Q%lvM9TdtuoWfG)d@(lT9JF1xe{_{V zKwz&RwTC-fWOGIq&rq=d*UqAH>8=2$I)l|)s^S|uC(N_O+x06u%c7cJjima?Sz<OT z?|cphQ)W%-ED~`W8^xUi_$}sn5J4rCsN8_^HTSm<Kji1A-ZUas%yx(LNR{dKwaIfg zTt|XnKg-y9g%THUFJydc?a9x)q|+z&eTNpDt!OtY;8gAcd)SGA+*#H<F)`v*CXCNU zA+E6JK}H!m;gilHTI7tKcr4#0&^3zft&iskECgiNNhBiQ`hD9YGytO!L#-d&3NDqa zG=w0PI6=xE!yV52c4`X2`XF-IAi|r}Go*|*O@R%tp6Jl*P~;IMRMU_Et8DKjl^4v` z@&RA!o@V<;FR5OdHss>qp(9-kKsva8l@&$g`L0#*E9m)tV<=?a@*(kJ2zl$q;T?mD zccY7<;Nc}*^&U%1P``_hpKXF8p===hznf(o#KNfm7H!c#E94)%3JqR%B#-8)r1r}z zW>kuNorUvgf!v(p2bjUV4ky-z&VmbXc!`C!<##nJ)CKHlZ2jHK={#?g9qNEgHQIN* zvSF{^Mh^A~)~95fc>`HsV{ydfSgvN`xiGX_d2%HadimZsI>iWgci*RCe*3(*_-pX> z6XmbGc#k;MAB4_rocZ8iAhl5zvk^O#Y=p{EykzinfdLvP|1_X*)p26xOoVasSnu?0 z#_*tX_rw|dAe+51QrzK~DpSYJyX_I(Lu&S5)otV<SJ!do&;d@YCpCIitoG8%tz4Tm zBo&X&2+_jGC=QndVG6v^aok|>K&|I{Lls+H!Cha^k<$YA(33vf1gLo+izcqoA6OXg zTxz29!GqX7N}iOK-C(T8^setAaAZyp{vc-n{MT;Yv%9Mh435q=hJqDhV>gzgQ^jnl zYLok^_0SDz3JXr&P<!)tdZ4?2Ra%4hshBcUYTFoq%Kk-O#H+9iDeyoz9wq#&kc8L8 z(kNbm@U3=QSiH5Aw*_N^+SqY_Ztw_rS=M1OpQ~-*>cO*g+dhTgwFwbo37!_k;aK21 z%`l^{cS_ah6%R$k(Q=yW`|?GX|Ep%&DjUtEJ7W)!--<~MG$FId;zWC17L>EV3FCjd zU^A*GtB7D#6mS5mE>kFK6To37`@`@6d*)8?4S<XyRk*mUW)<2C4{dFT0U^R00t!_4 z5gJWKoBK%R&ClZZ?#{XB*0d0<z}Z;_c;PSl#%_pOEjq@sL@`smn)0^&twP}^Lh}DL zhTqH0!#^ABlKdKlNnBvjD65CaG(#_ww16&kko;W#rAO>cERIJ(jP~0_mv&Jm&9d!j zlZ4ZRWw<h|s<x6;d60Yp!U<1i#yVy34r+kr<Ff(l9doO9nQ@hg`bS?4aFo9me44RA zdpJ}CIQFm?`nVjf0h?Cb#7s+3+?PQeU`Z8OdbxqKmxDo9)uZTt+j9X$OOy&bG`NE8 z*O2@&cOt)P80fEpoLYC=aikx9d4^6-K9~;Bt$k&_B;D^_O$R{mlt!od6-&5ln7@<E zblD+PPpAWiz70SZGGJnwCu^{9e!mBMR_zCnp;<h(mSfQNtI&Xm?oeB9`m6fH3oX#s z2snk(%Dw)SlWdH*AFsE`QB@;BJ0-5k1!CGMJi8DR>G3S~S)2T;Rarc0yn~H3q>33= zsI4fN%4@+47*}R3)wh*tF*pTgRyT$>gGNc^&?yoNsaKG+UzD_pK0G#jI7AV<1d3^G z#iR&t7~QVkXz~1n8tcB#EGO)|9?<AH=}v<>6(hh|Yl~{BMuU;a9u)iZ`aY1L^-H=r z-P*J{Y}k|L6Z-hZL~WO6l}|-B04K|H?=Yhj*oo=^?&A~j&>g=}fkd?Jw=<b`Gc00? zQ4ktyB&=*hhdY!#!Seyeecf3PPm+tF`)y|wz22OET2&Ba){s^G#Nj5FJ$C0?mV$;| zr%bVUays~C5Ld|qDyC%dw$3_`1Ni$;{g8X%ag7qcD!Op5icdNMAt$C9T`|#&Y?D2g z<h)JOZBUn2N|kz^Xad}~+NuR=HL~w~YsTf2CLq6mYk7ZEk2^5IFbwq8u>Q$q_AB}S zm%I_qki!t{+>PF#RfdieKZ_Ndd%|#6?33eZl@+_i!BeGCpBVe(Z~la(K(ly#9{pnM z+AS?NHLyVyf#CS5#<?TPfxZi1OZ-l>>M|<eZ^9+C28K@@94onU>ui2?q8C<RS!wVm z@D8cD{Q|8{h9XpXnvaV44Psy4;g)Jwg-u3>Ie>!V;Rczfqkcj-)F=EP8r%PuGJ_aa zq?0f_xm^%-&{<zMtS+d7^B46ih6jo~CsJdHBN;s2jFV!BRm!ybK8tzo+LjLP0dh8` ze3EH*I;1agBCAoOY?Z)53%hwuWFe(OceWP`z7b<f{kPV(snOpHvOs|Pp%#VBxKf4B z140ItAogFUT(I|f2u!TbSH$t^(f<%p2#j_=sx=r<->X*4kCuW|N9sb7;<xA1nWm}@ zBN%^;pey*FD;@f-1~U2`4bFxe#WeCJpF+f4;m|busUrCj5;B&`H@oEjTe(7ZVRMNK zLR9<wCOU}vNqM+Cd9$L}66HmI5k!-I4JLsQika*u*RbF!gp@X~OBzp+K|ONpJ4NVN z!P!|CMnQ(I0kEgqBJh6HNLu<nA(JM=zE8#1^?2lZ`&VnqzX_Rg;WVNka!)f2+~xyz zilaf|%dPGzD?Jz6dZOmfXJ2CH$b7_^sW0z;Wq=6%NJ{8ZI=hr*LDs})_ThSV!CP2h z7Ceo{l@jmwgTLg*2=XAwl6!@{)`~079$yE>F6aEg<d*V539|em>!{#T$6h>T=ZkU% zwc;leHbGA#E~Y9IJ0ty{HU6gnd7ecrJw-_r8iR~^KUb+r@z0rdI3RDNIRR~zI-rs$ zjb;W(h!wQYTFELkmUU-c_?kzBbjKv>YEj1ckiOZB)*wEPV@IFcfnwI++T1~#HM~fZ zI}K=rt4`wTl4zE$91cWmtFNHpUdB=>uZD0%PA%XegPdZQ?dmvHOQgyll34&er+0k- zLUw8cxe*ZYD|i8qZgM9iZ5>k7a%mr7LX3$h0jc8>`mY%+h|MOnwDpr>TDyZ%E)4yr zrRv=&G6%Mv`zT^Upnoh)Gw!WOz*fO>24zM*REgTAvE7We1{yYWzEKFc4Q80#W>_x) zkkbai(g#qwGdOI|KV((^sXH3v*E4G8ZauqCvp~gmeM5*xd7hNU&O@(-N#s@q0nx^r z2?I<pQ)d+qZfkMIP(LiRO@3-{By;f-_mtjvzIR{z_(j^;gUX!evg~!a8yfULjgM02 zbW7b+c{-yZerh6=loo9ONi_8Cf|cWLwkOe!>HxmF!Hhk**que7-NRv=@1w8wDBGx& zaL1OYvY!RhW^+N|ZlJ9#dG=tO4s_-024_ZK@R2C%KB(0!!G^d(nzWn-FTJ@fNrx@j zB=X1v^b4(Kns+F2LRjK{+U57KNw$auTFQnhDtL;5OK~RRx&`M-L1ynb-)IOdKk&wW zU5k&2d?0`(r*u_y!ThyMaq>=1mlWq1toc^R<pkpj32>`h+<%p3ta2%t9s=9np=gON zaB*nTI?v2@*5U%1*8Sr0x}~bDs52%gO&#H#S|~)|WiXkQ#*QC!fQJ1waxBML|JF>; z0B?isqtR30E1i0jQ+A&q1JtQYXR4%xQ&U@4%rkf90-bml)^lTr4c$~QPhpB!H(E7G zyiImTNRjEjv|Pwt20d+J2L**d{fV~{YG=;(8qNY24+*WxY6F}l+Ym=aYDEUQv`~Nk z59c~zAZ8;{Z17k%MTwsGSScce-17WK@8cb%D`~zyUEAJ4ANa>v552jBdiF>`=XH*m z%=5piK5ISI(Y^s&i6lZjSZo#ILla<=*A{u<R!SfsoCMIqD(<68++mG*ov*qZ?%ck* zeC<xp;SaCDY1JU-F5h5l7+s)0*1=-}Xvu+e=k%;(VtV)-R*p2`B+yk{Hk2Ft^U0R3 z5JPD>Tx>Pt0u!Lm3OU{e4+vJ1)=Y_z9r|PnUR?7-57VdH-H2@30y@bcoD0+Ix15@_ z9VwY?W7g@g$%5~=oIJUQ41Nan`;dqmuQf|ei9dAH@0IrGIAaUo$KNsEB2IRG2m((Q zX#=?Cz+v}?2t@nAmqRS$3XL7@#3-1)-_hyPj?e!JCOnkk>XUfz2sa$7E-u#_<~OJn zd$Gp|@9PN^d8O>P#S2?ZR2$Uq#g75Pc)&w;CY=x3+Z@ZwZ`lsv<pTMzri(61!15I} zwBqy)`S=fu7DNlh*dJrJf;zfQ<fkEh`QNPSxh6BsYxz0~KoU|vq3FV-+qX^%pF8uH zr$BE9D*F>9_HZD}{0_`JS<3}gX(S@vlEGJ*h*4@DgeR|Iz^lYE7yrB$N?BqT7B{Tz zYfQY!^WbVp_65H_JH90nvt@2Q;oC;BCO!qTPl7=a{ivu`a46*7JzFJ9jjj=FEx~62 z_-r`f&H9@id*Ki*WaG8X^SRTXgmk2hc=sKbJ<}NSWyY(Nu-X=ybKhU0*ox`vDLTFU zr$i#S2J)-bfCf`F*~xwd&_&y{F><GoSvjIU$%|%#fw%)5pE6KSJE3{9l{0lm5B+C< zHH?7=Uzo}&OG1>e@@=StENJBwo-cq_aeU;WH+$&A+(`c~Q+DE359#%R+tSeBqQeIe z`!0C<fw)pWsQ4<a#9A|<hTQnxK#-Hv(WJlQSJCup2GdPO{T*ITGx|(+|N8~+rES$B zrYbqB-8UEl()xZ4qxo7-T_^pH=vLs+wUC;lPxEhGiAnpV>R;zhrgH+?7>D76Ad<Ai z$z-o~7+s1w34dEGxp-?8^NCALQ_KS22;@Nmej@lL><$&fg`WT~uUin{LRRp>$c`Z_ zt&(_@Td&B%8%mD`SgmfZ`xA?+N3(r(Zg0yI`A#Gj(qJdL#6WxC0-VUSRF02Q+JPc3 zjK!MK(Pl4g=m_#>5oV=42Tw=g3ZDI_bq5kLoS!3JR0vI7MhbvcA?#I4L4hyqRxA=^ zf@wVLIWmEKQ3O#Q&`%Mb+M4g|F;ydzjr|A;P;~jb*Ntwp=nj3uPAQoO*^bV8DXGA- zH_qc?Y0Vw@pq!}?Eo;O+M|aj}?Ci}swAk=EoF_G=uPq*{#zjQajE16Iw<k*8Axny* zpg=EG7Sr?$Q5=+Y!TI;*UWbuZci{T*t=j%QJBlq>g2X0GqX1{RmXX1`t8~gjZ<P$* z{SiPK<05p0autwO%)Q3pbzjnG!KpR-wxV%m%DbsAQ;=@CUoDfPl=oDiD)5z@(0t^o zrXa!jmSug`d<}@+xY6BD7mTeQQV&QVR&D5d-KyR&s#wU=bYtOZk#XsyP;G4!V&;14 z=(O~mDfH49wUzCh?ASc%XS(shTdHc=z8G~FXT2f%`Lb(70|j}u!!u_{AFFxmi8~g- zLs7wZfA=nY^=MqsoIvI^U{9K-Vdn6kN5daWUv!1CFJ%5cR@fSj+-0MCl@M*=!#mvi z0z%UqQ&i<y@o%*y6RYk2C$LHcz$pa$qNKj?r;}Q)`{k{>UWF?B&y?`n8GycESi^dp z#c&>5ojPN*qq>H8_K(BInU7h0Kxq;?c_RaKg{FVDM%P*7bhPpH_n=+}p9J&aq)@;P ze%@O+cvLtd1EWI{+DyFno!qvr``sBQT<v&5iv?T1bXvWVU5scI75MAN+NdS*B*sX5 z`;nIPf}7FYSPjQbK)at4Xc81OtPp0T1^Y?+U0XrgGLI1cL#P%kpzrGMYpOjg?5$EO zjdOb<JQwPJXN+zbuXP-4^!@4jYX{|@{5OGaq*3l#aiu%C>brKWEw4DY*f7k*yG~~d zl%|xk@q}J;ox$~}a#-rxkk1j<Ud6ky*MrjN^J{jiVE!>iaP$@~F?yQh*~mzd0^s4r z+%&j+o*|*j6XsF1c12?9=RI?>hM2lHGJ{H3(*~q8IN%|ObAptTpau4)qS7I>6!{bV zPZnS;2D});@5$?PA18DGC}t_s=sUHQV$)T}@Tic;1mwrK6=bnF(!9(=MRe{&8I;~3 zzZF#fW4IEQs5qm5yzBVVTKzwb2An@#_%B}0NL+XL&&HQDYrAIy`Ma|ZYTsRA(shlH zEyFfX-GQbBX1^YIK8P^MIQH1*CKSD3aJIoZi}~bw%z>qI8Xj702zy-9O;AUg)Wd59 z_dX*^0MULg;J$(DT=qBTAK5iHLA})wqfyoUA4KVpjuqr9ZjIJttth#-x+v!4BMHd~ zof1aRTZ+?GK+_P&r~~SAJ)#9zKn%UMfwj~X8W(H$*<kI6kb;!`jEV}DeUQgM^iHb{ z;~l?zlwRmMnyWNhBOZcrp0Msx{KTd@aZxf)&p-Oj#n#)(sOP37`iuBfW2T&^VZnHo z8nG)pUEsvs+93slkfjLNT@%w@S{AnhFQB_vNMmQ&RLDg(01{STlR+LG#a!`>tE;{? z(K#02<NC!0-22Lf@CmP?k_GK7T?$A&MC<-lB;WUaSJL>wkiF~tS84Whq;;!3HMLJi zXw2-*vICF>al%cBJX#rC?$vjg!O7iLhO+WXFhb$7yzjks_r|_8TqtN8Q~5vOyg0k> qSc#5@pe*tGoq<m`;;p|Jtz_*kq*L5F{tIZ#yCT8j_qPp=N~i!YAt6=( From 2b59628f04f6fc46d9fc57494640af2670c3a77b Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 27 Aug 2026 06:10:40 +0800 Subject: [PATCH 121/189] fix(voting): remove sticky last-working server from share failover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VoteChainFailover was remembering the last-responding helper per round and prepending it to every subsequent call, causing one helper to receive most or all shares in a round — overriding the CSPRNG-based per-share server order already computed by the voting library. Remove _lastWorking entirely. orderedCandidates now uses the caller's baseUrls (already randomised by the library) followed by allServers as fallback, with no round-level state. --- lib/services/votechain_failover.dart | 24 ++++++++-------------- lib/store.dart | 9 -------- test/services/votechain_failover_test.dart | 22 +++++++------------- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/lib/services/votechain_failover.dart b/lib/services/votechain_failover.dart index 901a25876..63686400e 100644 --- a/lib/services/votechain_failover.dart +++ b/lib/services/votechain_failover.dart @@ -43,17 +43,16 @@ typedef VoteChainCall = Future<VotingChainResponse> Function(String baseUrl); /// "broadcast outcome unknown; tx_hash=..." envelope); otherwise next; /// - any other 5xx → next candidate. /// -/// The last URL that produced an answer is remembered per round and tried -/// first on the next run, so a recovered server is found without replaying -/// the outage. All candidates failing raises [TransientVoteChainException]. +/// Candidate order comes directly from the caller's `baseUrls` (already +/// randomised per-share by the voting library's CSPRNG), followed by any +/// remaining configured servers as fallback. All candidates failing raises +/// [TransientVoteChainException]. class VoteChainFailover { final List<String> allServers; /// Injectable sleep (tests pass a no-op). final Future<void> Function(Duration duration) delay; - final Map<String, String> _lastWorking = {}; - VoteChainFailover({ this.allServers = const [], Future<void> Function(Duration duration)? delay, @@ -63,12 +62,11 @@ class VoteChainFailover { /// first) plus [allServers]. Future<VotingChainResponse> run({ required List<String> baseUrls, - required String roundId, required VoteChainCall call, int max503Retries = 1, }) async { Object? lastError; - for (final url in orderedCandidates(baseUrls, roundId)) { + for (final url in orderedCandidates(baseUrls)) { var retries = 0; while (true) { final VotingChainResponse res; @@ -80,17 +78,14 @@ class VoteChainFailover { } final status = res.statusCode; if (status >= 200 && status < 300) { - _lastWorking[roundId] = url; return res; } if (status >= 400 && status < 500) { // A definitive answer (404 not found, 422 rejected, 409 conflict). - _lastWorking[roundId] = url; return res; } if (status == 502) { if (txHashFromVoteChainBody(res.body) != null) { - _lastWorking[roundId] = url; return res; } lastError = Exception('vote chain 502 from $url: ${res.body}'); @@ -107,20 +102,19 @@ class VoteChainFailover { } } throw TransientVoteChainException( - 'all vote chain servers failed (${orderedCandidates(baseUrls, roundId).length} tried): $lastError', + 'all vote chain servers failed (${orderedCandidates(baseUrls).length} tried): $lastError', ); } - /// Candidate order: the round's last-working URL (when configured), the - /// caller's list, then the remaining configured servers; deduplicated. - List<String> orderedCandidates(List<String> baseUrls, String roundId) { + /// Candidate order: the caller's list (CSPRNG-randomised by the voting + /// library per share), then the remaining configured servers; deduplicated. + List<String> orderedCandidates(List<String> baseUrls) { final ordered = <String>[]; void add(String? url) { if (url == null || url.isEmpty || ordered.contains(url)) return; ordered.add(url); } - add(_lastWorking[roundId]); for (final url in baseUrls) { add(url); } diff --git a/lib/store.dart b/lib/store.dart index 64c7b1718..b905bdd6c 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -1869,7 +1869,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { state = state.copyWith(stage: "submitting"); final res = await failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) => votechainSubmitDelegation( baseUrl: u, submissionJson: wireJson!, @@ -1949,7 +1948,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { "", rebroadcast: () => failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) async { final wire = await delegationWireJson( roundId: roundId, @@ -2066,7 +2064,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { try { res = await failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) => votechainRoundStatus( baseUrl: u, roundId: roundId, @@ -2199,7 +2196,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { for (var attempt = 0; attempt < 45; attempt++) { final res = await failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) => votechainTxConfirmation( baseUrl: u, txHash: txHash, @@ -2567,7 +2563,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ), rebroadcast: () => failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) async { final wire = await votingVoteWireJson( roundId: roundId, @@ -2635,7 +2630,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { ); final res = await failover.run( baseUrls: chainUrls, - roundId: roundId, call: (u) => votechainSubmitVote( baseUrl: u, submissionJson: wireJson, @@ -2779,7 +2773,6 @@ class VotingSubmissionJob extends _$VotingSubmissionJob { // retries them while the round window is open. final res = await failover.run( baseUrls: plan.targetServers, - roundId: roundId, call: (u) => votechainSubmitShare( serverUrl: u, payloadJson: body, @@ -2948,7 +2941,6 @@ class VotingShareTracker extends _$VotingShareTracker { // is unreachable — the next tick retries. res = await failover.run( baseUrls: plan.targetServers, - roundId: roundId, call: (u) => votechainSubmitShare( serverUrl: u, payloadJson: body, @@ -3035,7 +3027,6 @@ class VotingShareTracker extends _$VotingShareTracker { try { res = await failover.run( baseUrls: item.targetServers, - roundId: roundId, call: (u) => votechainResubmitShare( serverUrl: u, payloadJson: body, diff --git a/test/services/votechain_failover_test.dart b/test/services/votechain_failover_test.dart index e2005adc0..55315f260 100644 --- a/test/services/votechain_failover_test.dart +++ b/test/services/votechain_failover_test.dart @@ -17,20 +17,20 @@ void main() { delay: (_) async {}, ); expect( - failover.orderedCandidates(['c', 'd'], 'r1'), + failover.orderedCandidates(['c', 'd']), ['c', 'd', 'a', 'b'], ); }); - test('remembers the last working URL per round and tries it first', () async { + test('caller order is preserved across runs (no sticky last-working)', () async { final calls = <String>[]; final failover = VoteChainFailover( allServers: const ['a', 'b'], delay: (_) async {}, ); + // First run: 'a' fails, 'b' succeeds. await failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (url) async { calls.add(url); if (url == 'a') throw Exception('down'); @@ -39,24 +39,22 @@ void main() { ); expect(calls, ['a', 'b']); - final again = await failover.run( + // Second run with the same baseUrls: starts from 'a' again, not 'b'. + calls.clear(); + await failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (url) async { calls.add(url); return response(200); }, ); - expect(again.statusCode, 200); - // The remembered URL (b) is tried first and answers immediately. - expect(calls, ['a', 'b', 'b']); + expect(calls, ['a']); }); test('4xx is a final answer', () async { final failover = VoteChainFailover(delay: (_) async {}); final res = await failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (url) async => url == 'a' ? response(422, body: 'rejected') : fail('b must not be tried'), ); expect(res.statusCode, 422); @@ -66,7 +64,6 @@ void main() { final failover = VoteChainFailover(delay: (_) async {}); final res = await failover.run( baseUrls: ['a'], - roundId: 'r1', call: (_) async => response(404, body: '{"error":"tx not found"}'), ); expect(res.statusCode, 404); @@ -76,7 +73,6 @@ void main() { final failover = VoteChainFailover(delay: (_) async {}); final res = await failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (url) async => url == 'a' ? response(500) : response(200), ); expect(res.statusCode, 200); @@ -88,7 +84,6 @@ void main() { final failover = VoteChainFailover(delay: (d) async => delays.add(d)); final res = await failover.run( baseUrls: ['a'], - roundId: 'r1', call: (_) async { calls++; return calls == 1 @@ -104,7 +99,6 @@ void main() { final failover = VoteChainFailover(delay: (_) async {}); final res = await failover.run( baseUrls: ['a'], - roundId: 'r1', call: (_) async => response(502, body: 'broadcast outcome unknown after retries; tx_hash=ABCDEF'), ); @@ -116,7 +110,6 @@ void main() { final failover = VoteChainFailover(delay: (_) async {}); final res = await failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (url) async => url == 'a' ? response(502, body: 'boom') : response(200), ); expect(res.statusCode, 200); @@ -127,7 +120,6 @@ void main() { expect( () => failover.run( baseUrls: ['a', 'b'], - roundId: 'r1', call: (_) async => throw Exception('down'), ), throwsA(isA<TransientVoteChainException>()), From 070ec89b4368ff8c6241e1b19345abe04e680d89 Mon Sep 17 00:00:00 2001 From: rachyandco <alexis+github@roussel-zeter.eu> Date: Thu, 27 Aug 2026 00:53:46 +0200 Subject: [PATCH 122/189] fix(nym): make large syncs over the mixnet reliable (#1219) Large syncs looped forever on "stalled (no reply for 120s)": a single GetBlockRange stream for the whole range starves the nym-rpc session of reply SURBs, and nym-sdk's MessageBuffer flushes messages that waited over 6s even when earlier ids are missing, corrupting the h2 stream (GOAWAY FRAME_SIZE_ERROR) under mixnet retransmission delays. Over the mixnet, split the shielded sync into 1000-block chunks that each run a complete pass and commit, so a dropped session only costs the chunk in flight; clearnet/Tor keep the single-stream behavior. Replace the decay-based buffer with one that writes strictly consecutive message ids, drops duplicate retransmissions, and honors the server's Close message. A gap left unfilled for 120s trips the stall watchdog instead of hanging the session forever. Co-authored-by: hhanh00 <hanh425@gmail.com> --- rust/src/api/coin.rs | 6 +++ rust/src/net/nym_service.rs | 96 +++++++++++++++++++++++++++++++------ rust/src/sync.rs | 61 ++++++++++++++++++++++- 3 files changed, 148 insertions(+), 15 deletions(-) diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 24f144c76..394de3d35 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -181,6 +181,12 @@ impl Coin { Ok(Coin { proxy, ..self }) } + /// True when traffic to the server goes through the Nym mixnet, either + /// via a mixnet-native nym:// endpoint or the Nym transport. + pub(crate) fn is_mixnet(&self) -> bool { + crate::net::nym_service::parse_nym_url(&self.url).is_some() || self.transport == 2 + } + pub(crate) async fn client(&self) -> Result<Client> { // Mixnet-native endpoint (nym:// URL, a nym-rpc service): bypasses // the transport enum entirely — the mixnet IS the transport. diff --git a/rust/src/net/nym_service.rs b/rust/src/net/nym_service.rs index 606ffb048..9fd72aeb0 100644 --- a/rust/src/net/nym_service.rs +++ b/rust/src/net/nym_service.rs @@ -24,8 +24,9 @@ use nym_sdk::mixnet::{ IncludedSurbs, MixnetClient, MixnetClientBuilder, MixnetMessageSender, NymNetworkDetails, Recipient, }; -use nym_sdk::tcp_proxy::utils::{MessageBuffer, Payload, ProxiedMessage}; -use tokio::net::{TcpListener, TcpStream}; +use nym_sdk::tcp_proxy::utils::{Payload, ProxiedMessage}; +use tokio::io::AsyncWriteExt; +use tokio::net::{tcp::OwnedWriteHalf, TcpListener, TcpStream}; use tokio::sync::{oneshot, Mutex, OnceCell}; use tokio_stream::StreamExt; use tokio_util::codec::{BytesCodec, FramedRead}; @@ -152,6 +153,60 @@ async fn get_client() -> Result<MixnetClient> { Ok(client) } +/// Strictly ordered reassembly buffer for a session's incoming messages. +/// +/// nym-sdk's `MessageBuffer` flushes any message that has waited longer than +/// 6s even when earlier ids are still missing ("decay-based delivery"), which +/// reorders bytes under mixnet retransmission delays and corrupts the h2 +/// stream (GOAWAY FRAME_SIZE_ERROR). gRPC needs exact byte order, so this +/// buffer only ever writes consecutive message ids; a permanently missing id +/// is handled by the session stall watchdog instead of by corrupting data. +struct OrderedMessageBuffer { + next_id: u16, + pending: HashMap<u16, Payload>, + /// Set while writes are blocked on a missing id; cleared on progress. + blocked_since: Option<Instant>, +} + +impl OrderedMessageBuffer { + fn new() -> Self { + OrderedMessageBuffer { + next_id: 0, + pending: HashMap::new(), + blocked_since: None, + } + } + + fn push(&mut self, msg: ProxiedMessage) { + // Ignore duplicates of already-written ids (mixnet retransmissions). + if msg.message_id >= self.next_id { + self.pending.insert(msg.message_id, msg.message); + } + } + + /// Write every consecutive payload to the local socket. Returns `true` + /// when the session's Close message has been reached. + async fn flush(&mut self, write: &mut OwnedWriteHalf) -> Result<bool> { + while let Some(payload) = self.pending.remove(&self.next_id) { + self.next_id += 1; + self.blocked_since = None; + match payload { + Payload::Data(data) => write.write_all(&data).await?, + Payload::Close => return Ok(true), + } + } + if !self.pending.is_empty() && self.blocked_since.is_none() { + self.blocked_since = Some(Instant::now()); + } + Ok(false) + } + + /// How long writes have been blocked on a missing message id. + fn blocked_for(&self) -> Option<Duration> { + self.blocked_since.map(|t| t.elapsed()) + } +} + /// One ordered mixnet session per local TCP connection, mirroring nym-rpc's /// `TcpProxyClient::handle_incoming`. async fn run_session(stream: TcpStream, recipient: Recipient) -> Result<()> { @@ -201,30 +256,39 @@ async fn run_session(stream: TcpStream, recipient: Recipient) -> Result<()> { Ok::<_, anyhow::Error>(()) }); - // Incoming: reorder mixnet messages and write them to the local socket; - // after local EOF keep draining for CLOSE_TIMEOUT. - let mut msg_buffer = MessageBuffer::new(); + // Incoming: reorder mixnet messages and write them to the local socket + // in strict id order; after local EOF keep draining for CLOSE_TIMEOUT. + let mut msg_buffer = OrderedMessageBuffer::new(); loop { tokio::select! { _ = &mut rx => break, Some(message) = client.next() => { let message = bincode1::deserialize::<ProxiedMessage>(&message.message)?; msg_buffer.push(message); - msg_buffer.tick(&mut write).await?; + if msg_buffer.flush(&mut write).await? { + tracing::debug!("nym-rpc session {session_id}: Close received"); + client.disconnect().await; + return Ok(()); + } last_in = started.elapsed().as_secs().max(1); }, _ = tokio::time::sleep(Duration::from_millis(100)) => { - msg_buffer.tick(&mut write).await?; // Stall: we sent a request after the last reply and the - // mixnet has returned nothing since. Drop the session so - // the caller gets an error instead of waiting forever. + // mixnet has returned nothing since, or replies keep + // arriving but a missing id has blocked writes for just as + // long. Drop the session so the caller gets an error + // instead of waiting forever. let out = last_out.load(Ordering::Relaxed); - if out > last_in + let request_stalled = out > last_in && started.elapsed().as_secs().saturating_sub(last_in.max(out)) - > STALL_TIMEOUT.as_secs() - { + > STALL_TIMEOUT.as_secs(); + let gap_stalled = msg_buffer + .blocked_for() + .is_some_and(|blocked| blocked > STALL_TIMEOUT); + if request_stalled || gap_stalled { tracing::warn!( - "nym-rpc session {session_id} stalled (no reply for {}s); closing", + "nym-rpc session {session_id} stalled ({} for {}s); closing", + if gap_stalled { "message gap unfilled" } else { "no reply" }, STALL_TIMEOUT.as_secs() ); client.disconnect().await; @@ -238,7 +302,11 @@ async fn run_session(stream: TcpStream, recipient: Recipient) -> Result<()> { Some(message) = client.next() => { let message = bincode1::deserialize::<ProxiedMessage>(&message.message)?; msg_buffer.push(message); - msg_buffer.tick(&mut write).await?; + if msg_buffer.flush(&mut write).await? { + tracing::debug!("nym-rpc session {session_id}: Close received"); + client.disconnect().await; + return Ok(()); + } }, _ = tokio::time::sleep(CLOSE_TIMEOUT) => { tracing::debug!("nym-rpc session {session_id} closed"); diff --git a/rust/src/sync.rs b/rust/src/sync.rs index 49aa2cbf9..46087d638 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -237,6 +237,10 @@ pub async fn synchronize_impl<S: Sink<SyncProgress> + Send + 'static>( ) .await?; + // Over the mixnet, download blocks in small chunks so each + // GetBlockRange stream fits in one nym-rpc session; elsewhere a + // single stream for the whole range is cheaper. + let chunk_size = c.is_mixnet().then_some(MIXNET_SYNC_CHUNK); shielded_sync( &network, &pool, @@ -245,6 +249,7 @@ pub async fn synchronize_impl<S: Sink<SyncProgress> + Send + 'static>( start_height, end_height, actions_per_sync, + chunk_size, tx_progress.clone(), tx_cancel.subscribe(), ) @@ -656,6 +661,13 @@ fn resolve_diversifier_index( } } +/// Blocks per `GetBlockRange` request when syncing over the Nym mixnet. +/// A single full-range stream starves the nym-rpc session of reply SURBs +/// and trips its 120s stall watchdog; small chunks keep each stream within +/// one session's budget and commit progress between chunks, so a dropped +/// session only costs the current chunk. +pub const MIXNET_SYNC_CHUNK: u32 = 1000; + #[allow(clippy::too_many_arguments)] pub async fn shielded_sync( network: &Network, @@ -665,8 +677,9 @@ pub async fn shielded_sync( start: u32, end: u32, actions_per_sync: u32, + chunk_size: Option<u32>, tx_progress: Sender<SyncProgress>, - rx_cancel: broadcast::Receiver<()>, + mut rx_cancel: broadcast::Receiver<()>, ) -> Result<()> { let activation_height: u32 = network .activation_height(NetworkUpgrade::Sapling) @@ -675,6 +688,52 @@ pub async fn shielded_sync( let start = start.max(activation_height); let end = end.max(activation_height); + let chunk_size = chunk_size.unwrap_or(u32::MAX).max(1); + let mut chunk_start = start; + loop { + let chunk_end = chunk_start.saturating_add(chunk_size - 1).min(end); + shielded_sync_range( + network, + pool, + client, + accounts, + chunk_start, + chunk_end, + actions_per_sync, + tx_progress.clone(), + rx_cancel.resubscribe(), + ) + .await?; + if chunk_end >= end { + break; + } + // A cancel delivered during the finished chunk was consumed by that + // chunk's resubscribed receiver; check ours before starting the next. + match rx_cancel.try_recv() { + Err(broadcast::error::TryRecvError::Empty) + | Err(broadcast::error::TryRecvError::Closed) => {} + _ => { + debug!("Sync cancelled between chunks"); + break; + } + } + chunk_start = chunk_end + 1; + } + Ok(()) +} + +#[allow(clippy::too_many_arguments)] +async fn shielded_sync_range( + network: &Network, + pool: &SqlitePool, + client: &mut Client, + accounts: &[(u32, bool)], + start: u32, + end: u32, + actions_per_sync: u32, + tx_progress: Sender<SyncProgress>, + rx_cancel: broadcast::Receiver<()>, +) -> Result<()> { let accounts = accounts.to_vec(); let db_writer_task = { let (s, o, i) = get_tree_state(network, client, start - 1).await?; From 1752e9de0cbb91d3e53d884ea8f536889e878291 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 27 Aug 2026 10:02:36 +0800 Subject: [PATCH 123/189] fix(proxy): pass SOCKS5 credentials from proxy URL to tokio-socks open_proxied_stream parsed the proxy URI for host/port but discarded the userinfo (user:pass@), so it always called Socks5Stream::connect() (no auth) even when credentials were present in the URL. Extract the userinfo from the authority and call connect_with_password() when credentials are found. Also remove unused tiu import (db.rs) and prefix unused _c parameter (voting.rs). --- build_number.txt | 2 +- rust/src/api/coin.rs | 48 ++++++++++++++++++++++++++++++++++-------- rust/src/api/voting.rs | 2 +- rust/src/db.rs | 2 +- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/build_number.txt b/build_number.txt index bc23f8ef5..8941db590 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -354 +355 diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 394de3d35..c6a5192a5 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -414,18 +414,38 @@ pub(crate) async fn open_proxied_stream( _ => 8080, }); + // Extract credentials from the authority (user:pass@host:port). + // http::Uri::host() already strips the userinfo, so phost/pport are fine; + // we only need the raw authority string to pull out the userinfo prefix. + let creds: Option<(String, String)> = puri + .authority() + .and_then(|a| a.as_str().rfind('@').map(|at| &a.as_str()[..at])) + .map(|userinfo| { + let (u, p) = userinfo.split_once(':').unwrap_or((userinfo, "")); + (u.to_string(), p.to_string()) + }); + match scheme.as_str() { // socks5h => resolve the target hostname *at the proxy* (remote DNS). // This is what allows .onion addresses to work and prevents DNS leaks, // so it is the recommended scheme for Tor. "socks5h" => { - let stream = tokio_socks::tcp::Socks5Stream::connect( - (phost, pport), - // Passing a &str target makes tokio-socks send the hostname to - // the proxy as a SOCKS5 DOMAINNAME request (proxy-side DNS). - (target_host, target_port), - ) - .await?; + let stream = match &creds { + Some((u, p)) => tokio_socks::tcp::Socks5Stream::connect_with_password( + (phost, pport), + // Passing a &str target makes tokio-socks send the hostname to + // the proxy as a SOCKS5 DOMAINNAME request (proxy-side DNS). + (target_host, target_port), + u.as_str(), + p.as_str(), + ) + .await?, + None => tokio_socks::tcp::Socks5Stream::connect( + (phost, pport), + (target_host, target_port), + ) + .await?, + }; Ok(stream.into_inner()) } // socks5 => resolve the target hostname locally and send the IP to the @@ -436,8 +456,18 @@ pub(crate) async fn open_proxied_stream( let target_addr = addrs .next() .ok_or_else(|| anyhow::anyhow!("could not resolve {target_host}"))?; - let stream = - tokio_socks::tcp::Socks5Stream::connect((phost, pport), target_addr).await?; + let stream = match &creds { + Some((u, p)) => tokio_socks::tcp::Socks5Stream::connect_with_password( + (phost, pport), + target_addr, + u.as_str(), + p.as_str(), + ) + .await?, + None => { + tokio_socks::tcp::Socks5Stream::connect((phost, pport), target_addr).await? + } + }; Ok(stream.into_inner()) } "http" | "https" => http_connect_tunnel(phost, pport, target_host, target_port).await, diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 48f6525ac..463c46d6f 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -1151,7 +1151,7 @@ pub async fn voting_share_plans( vote_end: u64, ceremony_start: u64, single_share: bool, - c: &Coin, + _c: &Coin, ) -> Result<Vec<VotingSharePlanItem>> { let buffer = zcash_voting::share_policy::last_moment_buffer_seconds(ceremony_start, vote_end); diff --git a/rust/src/db.rs b/rust/src/db.rs index 2bc213e38..91d510bc5 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -25,7 +25,7 @@ use crate::api::account::{Account, Memo, Tx}; use crate::api::coin::Network; use crate::api::sync::PoolBalance; use crate::sync::BlockHeader; -use crate::{api::account::TxNote, tiu}; +use crate::api::account::TxNote; /// Schema version. Bump only when the export format changes (IOAccount or any /// embedded struct gains/removes/changes a field). Do NOT bump for runtime-only From 545cf9b6742c15ee3e453fa16fcef4bb53a659c8 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Thu, 27 Aug 2026 19:56:40 +0800 Subject: [PATCH 124/189] chore(main): release zkool 6.28.1 (#1227) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3c57d9436..0f128e4fa 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.28.0" + ".": "6.28.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index ce49d4e2c..505b8cf4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [6.28.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.28.0...zkool-v6.28.1) (2026-08-27) + + +### Bug Fixes + +* **nym:** make large syncs over the mixnet reliable ([#1219](https://github.com/hhanh00/zkool2/issues/1219)) ([070ec89](https://github.com/hhanh00/zkool2/commit/070ec89b4368ff8c6241e1b19345abe04e680d89)) +* **proxy:** pass SOCKS5 credentials from proxy URL to tokio-socks ([1752e9d](https://github.com/hhanh00/zkool2/commit/1752e9de0cbb91d3e53d884ea8f536889e878291)) +* **voting:** remove sticky last-working server from share failover ([2b59628](https://github.com/hhanh00/zkool2/commit/2b59628f04f6fc46d9fc57494640af2670c3a77b)) + ## [6.28.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.27.0...zkool-v6.28.0) (2026-08-23) diff --git a/build_number.txt b/build_number.txt index 8941db590..53d5a5ad6 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -355 +356 diff --git a/pubspec.yaml b/pubspec.yaml index 91a011b1d..afdf99521 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.28.0 # x-release-please-version +version: 6.28.1 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 2ece8e17b..8993da977 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.28.0 +6.28.1 From 277929a6cb55cc266a694d3b4aa157f23f3513df Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 27 Aug 2026 21:53:29 +0800 Subject: [PATCH 125/189] feat(vault): sign out of Google when Cloud Vault is turned off Turning the Cloud Vault switch off now disconnects the Google account, so re-enabling shows the account picker and allows switching users. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- lib/settings.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/settings.dart b/lib/settings.dart index 5163c8e62..0202b20b3 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -799,6 +799,14 @@ class SettingsFormState extends ConsumerState<SettingsForm> { if (mounted) await showException(context, "Passkey error: ${e.message}"); return; } + } else { + // Vault is deactivating: sign out of Google so the next enable + // shows the account picker (allows switching to a different user). + try { + await ref.read(vaultProvider.notifier).signOut(); + } catch (e) { + logger.w("[Vault] disable: signOut failed: $e"); + } } setState(() { settings = settings.copyWith(vault: value); From deff307ce6312f26287d672111f7de5df8ea7fba Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Fri, 28 Aug 2026 03:46:44 +0800 Subject: [PATCH 126/189] fix(frost): report DKG round 0 and broadcast statuses in the UI (#1230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DKG page could never show round 2. `PublishRound1Pkg` and `PublishRound2Pkg` existed in `DKGStatus` and had branches in the UI, but nothing ever constructed them, so the only route to the round 2 step was `WaitRound2Pkg` — which is sent only when the peers' round 2 packages have not arrived yet. The app polls every 30s while the peers advance on every block, so their packages are usually already synced by the time the app processes round 1: it completed both rounds in a single pass and the stepper jumped from round 1 straight to the shared address. `run_round` publishes our own package only on the invocation where our secret does not exist yet, so checking `load_secret` before each round tells us whether this pass is a broadcast, and the matching status can be sent. `Finalize` is now emitted before deriving the shared key, and the UI handles it. Round 0 also reported itself as round 1 (it reused `WaitRound1Pkg`, with a TODO in place of the missing variant), so "waiting for round 1 packages" was shown while actually waiting for peer verifying keys, and "Broadcasting round 1 packages" appeared twice. Adds `PublishRound0Pkg` / `WaitRound0Pkg`, mapped in the UI to the Participants step. Observed sequence after the change: Broadcasting participant keys Waiting for other participants to send their keys Broadcasting round 1 packages Waiting for other participants to send their round 1 packages Broadcasting round 2 packages The shared address is: ... Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- lib/pages/dkg.dart | 18 +++++++ lib/src/rust/api/coin.dart | 2 +- lib/src/rust/api/frost.dart | 5 ++ lib/src/rust/api/frost.freezed.dart | 78 +++++++++++++++++++++++++++++ lib/src/rust/api/init.dart | 2 +- lib/src/rust/frb_generated.dart | 44 ++++++++++------ lib/store.g.dart | 4 +- rust/src/api/frost.rs | 4 ++ rust/src/frb_generated.rs | 52 ++++++++++++------- rust/src/frost/dkg.rs | 24 ++++++++- 10 files changed, 193 insertions(+), 40 deletions(-) diff --git a/lib/pages/dkg.dart b/lib/pages/dkg.dart index f400cfebb..3f039cf6e 100644 --- a/lib/pages/dkg.dart +++ b/lib/pages/dkg.dart @@ -352,6 +352,18 @@ class DKGPage3State extends ConsumerState<DKGPage3> { final status = doDkg(c: c); status.listen( (s) { + if (s is DKGStatus_PublishRound0Pkg) { + setState(() { + message = "Broadcasting participant keys"; + index = 0; + }); + } + if (s is DKGStatus_WaitRound0Pkg) { + setState(() { + message = "Waiting for other participants to send their keys"; + index = 0; + }); + } if (s is DKGStatus_PublishRound1Pkg) { setState(() { message = "Broadcasting round 1 packages"; @@ -376,6 +388,12 @@ class DKGPage3State extends ConsumerState<DKGPage3> { index = 2; }); } + if (s is DKGStatus_Finalize) { + setState(() { + message = "Deriving the shared key"; + index = 3; + }); + } if (s is DKGStatus_SharedAddress) { final sharedUA = s.field0; ref.invalidate(getAccountsProvider); diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index e0fd7cd80..87f2082ab 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -8,7 +8,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'coin.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_nym`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `network`, `open_proxied_stream`, `try_open` +// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_nym`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `is_mixnet`, `network`, `open_proxied_stream`, `try_open` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` Future<void> initDatadir({required String directory}) => diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index a4ed66a81..cc43cb4f6 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -76,6 +76,11 @@ sealed class DKGStatus with _$DKGStatus { const factory DKGStatus.waitAddresses( List<String> field0, ) = DKGStatus_WaitAddresses; + + /// Round 0 exchanges participant signing keys before the FROST rounds + /// proper; it needs its own status so the UI does not report it as round 1. + const factory DKGStatus.publishRound0Pkg() = DKGStatus_PublishRound0Pkg; + const factory DKGStatus.waitRound0Pkg() = DKGStatus_WaitRound0Pkg; const factory DKGStatus.publishRound1Pkg() = DKGStatus_PublishRound1Pkg; const factory DKGStatus.waitRound1Pkg() = DKGStatus_WaitRound1Pkg; const factory DKGStatus.publishRound2Pkg() = DKGStatus_PublishRound2Pkg; diff --git a/lib/src/rust/api/frost.freezed.dart b/lib/src/rust/api/frost.freezed.dart index 9a9a2e016..50b8b77b4 100644 --- a/lib/src/rust/api/frost.freezed.dart +++ b/lib/src/rust/api/frost.freezed.dart @@ -52,6 +52,8 @@ extension DKGStatusPatterns on DKGStatus { TResult maybeMap<TResult extends Object?>({ TResult Function(DKGStatus_WaitParams value)? waitParams, TResult Function(DKGStatus_WaitAddresses value)? waitAddresses, + TResult Function(DKGStatus_PublishRound0Pkg value)? publishRound0Pkg, + TResult Function(DKGStatus_WaitRound0Pkg value)? waitRound0Pkg, TResult Function(DKGStatus_PublishRound1Pkg value)? publishRound1Pkg, TResult Function(DKGStatus_WaitRound1Pkg value)? waitRound1Pkg, TResult Function(DKGStatus_PublishRound2Pkg value)? publishRound2Pkg, @@ -66,6 +68,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(_that); case DKGStatus_WaitAddresses() when waitAddresses != null: return waitAddresses(_that); + case DKGStatus_PublishRound0Pkg() when publishRound0Pkg != null: + return publishRound0Pkg(_that); + case DKGStatus_WaitRound0Pkg() when waitRound0Pkg != null: + return waitRound0Pkg(_that); case DKGStatus_PublishRound1Pkg() when publishRound1Pkg != null: return publishRound1Pkg(_that); case DKGStatus_WaitRound1Pkg() when waitRound1Pkg != null: @@ -100,6 +106,9 @@ extension DKGStatusPatterns on DKGStatus { TResult map<TResult extends Object?>({ required TResult Function(DKGStatus_WaitParams value) waitParams, required TResult Function(DKGStatus_WaitAddresses value) waitAddresses, + required TResult Function(DKGStatus_PublishRound0Pkg value) + publishRound0Pkg, + required TResult Function(DKGStatus_WaitRound0Pkg value) waitRound0Pkg, required TResult Function(DKGStatus_PublishRound1Pkg value) publishRound1Pkg, required TResult Function(DKGStatus_WaitRound1Pkg value) waitRound1Pkg, @@ -115,6 +124,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(_that); case DKGStatus_WaitAddresses(): return waitAddresses(_that); + case DKGStatus_PublishRound0Pkg(): + return publishRound0Pkg(_that); + case DKGStatus_WaitRound0Pkg(): + return waitRound0Pkg(_that); case DKGStatus_PublishRound1Pkg(): return publishRound1Pkg(_that); case DKGStatus_WaitRound1Pkg(): @@ -146,6 +159,8 @@ extension DKGStatusPatterns on DKGStatus { TResult? mapOrNull<TResult extends Object?>({ TResult? Function(DKGStatus_WaitParams value)? waitParams, TResult? Function(DKGStatus_WaitAddresses value)? waitAddresses, + TResult? Function(DKGStatus_PublishRound0Pkg value)? publishRound0Pkg, + TResult? Function(DKGStatus_WaitRound0Pkg value)? waitRound0Pkg, TResult? Function(DKGStatus_PublishRound1Pkg value)? publishRound1Pkg, TResult? Function(DKGStatus_WaitRound1Pkg value)? waitRound1Pkg, TResult? Function(DKGStatus_PublishRound2Pkg value)? publishRound2Pkg, @@ -159,6 +174,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(_that); case DKGStatus_WaitAddresses() when waitAddresses != null: return waitAddresses(_that); + case DKGStatus_PublishRound0Pkg() when publishRound0Pkg != null: + return publishRound0Pkg(_that); + case DKGStatus_WaitRound0Pkg() when waitRound0Pkg != null: + return waitRound0Pkg(_that); case DKGStatus_PublishRound1Pkg() when publishRound1Pkg != null: return publishRound1Pkg(_that); case DKGStatus_WaitRound1Pkg() when waitRound1Pkg != null: @@ -192,6 +211,8 @@ extension DKGStatusPatterns on DKGStatus { TResult maybeWhen<TResult extends Object?>({ TResult Function()? waitParams, TResult Function(List<String> field0)? waitAddresses, + TResult Function()? publishRound0Pkg, + TResult Function()? waitRound0Pkg, TResult Function()? publishRound1Pkg, TResult Function()? waitRound1Pkg, TResult Function()? publishRound2Pkg, @@ -206,6 +227,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(); case DKGStatus_WaitAddresses() when waitAddresses != null: return waitAddresses(_that.field0); + case DKGStatus_PublishRound0Pkg() when publishRound0Pkg != null: + return publishRound0Pkg(); + case DKGStatus_WaitRound0Pkg() when waitRound0Pkg != null: + return waitRound0Pkg(); case DKGStatus_PublishRound1Pkg() when publishRound1Pkg != null: return publishRound1Pkg(); case DKGStatus_WaitRound1Pkg() when waitRound1Pkg != null: @@ -240,6 +265,8 @@ extension DKGStatusPatterns on DKGStatus { TResult when<TResult extends Object?>({ required TResult Function() waitParams, required TResult Function(List<String> field0) waitAddresses, + required TResult Function() publishRound0Pkg, + required TResult Function() waitRound0Pkg, required TResult Function() publishRound1Pkg, required TResult Function() waitRound1Pkg, required TResult Function() publishRound2Pkg, @@ -253,6 +280,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(); case DKGStatus_WaitAddresses(): return waitAddresses(_that.field0); + case DKGStatus_PublishRound0Pkg(): + return publishRound0Pkg(); + case DKGStatus_WaitRound0Pkg(): + return waitRound0Pkg(); case DKGStatus_PublishRound1Pkg(): return publishRound1Pkg(); case DKGStatus_WaitRound1Pkg(): @@ -284,6 +315,8 @@ extension DKGStatusPatterns on DKGStatus { TResult? whenOrNull<TResult extends Object?>({ TResult? Function()? waitParams, TResult? Function(List<String> field0)? waitAddresses, + TResult? Function()? publishRound0Pkg, + TResult? Function()? waitRound0Pkg, TResult? Function()? publishRound1Pkg, TResult? Function()? waitRound1Pkg, TResult? Function()? publishRound2Pkg, @@ -297,6 +330,10 @@ extension DKGStatusPatterns on DKGStatus { return waitParams(); case DKGStatus_WaitAddresses() when waitAddresses != null: return waitAddresses(_that.field0); + case DKGStatus_PublishRound0Pkg() when publishRound0Pkg != null: + return publishRound0Pkg(); + case DKGStatus_WaitRound0Pkg() when waitRound0Pkg != null: + return waitRound0Pkg(); case DKGStatus_PublishRound1Pkg() when publishRound1Pkg != null: return publishRound1Pkg(); case DKGStatus_WaitRound1Pkg() when waitRound1Pkg != null: @@ -410,6 +447,47 @@ class _$DKGStatus_WaitAddressesCopyWithImpl<$Res> /// @nodoc +class DKGStatus_PublishRound0Pkg extends DKGStatus { + const DKGStatus_PublishRound0Pkg() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is DKGStatus_PublishRound0Pkg); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'DKGStatus.publishRound0Pkg()'; + } +} + +/// @nodoc + +class DKGStatus_WaitRound0Pkg extends DKGStatus { + const DKGStatus_WaitRound0Pkg() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is DKGStatus_WaitRound0Pkg); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'DKGStatus.waitRound0Pkg()'; + } +} + +/// @nodoc + class DKGStatus_PublishRound1Pkg extends DKGStatus { const DKGStatus_PublishRound1Pkg() : super._(); diff --git a/lib/src/rust/api/init.dart b/lib/src/rust/api/init.dart index bbc587bcb..2502df761 100644 --- a/lib/src/rust/api/init.dart +++ b/lib/src/rust/api/init.dart @@ -8,7 +8,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'init.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `frb_layer` +// These functions are ignored because they are not marked as `pub`: `base_filter`, `frb_layer` // These functions are ignored because they have generic arguments: `default_layer` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `FrbLogger` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `on_event` diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 75e00888e..f6cd94276 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -8699,16 +8699,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { dco_decode_list_String(raw[1]), ); case 2: - return DKGStatus_PublishRound1Pkg(); + return DKGStatus_PublishRound0Pkg(); case 3: - return DKGStatus_WaitRound1Pkg(); + return DKGStatus_WaitRound0Pkg(); case 4: - return DKGStatus_PublishRound2Pkg(); + return DKGStatus_PublishRound1Pkg(); case 5: - return DKGStatus_WaitRound2Pkg(); + return DKGStatus_WaitRound1Pkg(); case 6: - return DKGStatus_Finalize(); + return DKGStatus_PublishRound2Pkg(); case 7: + return DKGStatus_WaitRound2Pkg(); + case 8: + return DKGStatus_Finalize(); + case 9: return DKGStatus_SharedAddress( dco_decode_String(raw[1]), ); @@ -11069,16 +11073,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_field0 = sse_decode_list_String(deserializer); return DKGStatus_WaitAddresses(var_field0); case 2: - return DKGStatus_PublishRound1Pkg(); + return DKGStatus_PublishRound0Pkg(); case 3: - return DKGStatus_WaitRound1Pkg(); + return DKGStatus_WaitRound0Pkg(); case 4: - return DKGStatus_PublishRound2Pkg(); + return DKGStatus_PublishRound1Pkg(); case 5: - return DKGStatus_WaitRound2Pkg(); + return DKGStatus_WaitRound1Pkg(); case 6: - return DKGStatus_Finalize(); + return DKGStatus_PublishRound2Pkg(); case 7: + return DKGStatus_WaitRound2Pkg(); + case 8: + return DKGStatus_Finalize(); + case 9: var var_field0 = sse_decode_String(deserializer); return DKGStatus_SharedAddress(var_field0); default: @@ -13913,18 +13921,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case DKGStatus_WaitAddresses(field0: final field0): sse_encode_i_32(1, serializer); sse_encode_list_String(field0, serializer); - case DKGStatus_PublishRound1Pkg(): + case DKGStatus_PublishRound0Pkg(): sse_encode_i_32(2, serializer); - case DKGStatus_WaitRound1Pkg(): + case DKGStatus_WaitRound0Pkg(): sse_encode_i_32(3, serializer); - case DKGStatus_PublishRound2Pkg(): + case DKGStatus_PublishRound1Pkg(): sse_encode_i_32(4, serializer); - case DKGStatus_WaitRound2Pkg(): + case DKGStatus_WaitRound1Pkg(): sse_encode_i_32(5, serializer); - case DKGStatus_Finalize(): + case DKGStatus_PublishRound2Pkg(): sse_encode_i_32(6, serializer); - case DKGStatus_SharedAddress(field0: final field0): + case DKGStatus_WaitRound2Pkg(): sse_encode_i_32(7, serializer); + case DKGStatus_Finalize(): + sse_encode_i_32(8, serializer); + case DKGStatus_SharedAddress(field0: final field0): + sse_encode_i_32(9, serializer); sse_encode_String(field0, serializer); } } diff --git a/lib/store.g.dart b/lib/store.g.dart index b98bfc7f3..49d9f781d 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -2136,7 +2136,7 @@ final class VotingSubmissionJobProvider } String _$votingSubmissionJobHash() => - r'74833aa2e2d32c5e38e4b931309a4776a4cc3f57'; + r'1940c354beed580d30ec097e8e6f29a9e1d202e0'; /// Delegation execution job for one round. Runs the serialized chain: /// prepare (or resume) → setup → build submission (progress stream) → @@ -2261,7 +2261,7 @@ final class VotingShareTrackerProvider } String _$votingShareTrackerHash() => - r'fb64664f086a6d186faebbae65da843a83dec41e'; + r'a6d5dc955f1b45c75b0504403743b569ca5d93b4'; /// Session-independent helper-share tracking for one round. /// diff --git a/rust/src/api/frost.rs b/rust/src/api/frost.rs index 6f45c71f5..ab6de60ec 100644 --- a/rust/src/api/frost.rs +++ b/rust/src/api/frost.rs @@ -142,6 +142,10 @@ pub struct DKGParams { pub enum DKGStatus { WaitParams, WaitAddresses(Vec<String>), + /// Round 0 exchanges participant signing keys before the FROST rounds + /// proper; it needs its own status so the UI does not report it as round 1. + PublishRound0Pkg, + WaitRound0Pkg, PublishRound1Pkg, WaitRound1Pkg, PublishRound2Pkg, diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 6c4df0e52..a2cfddda1 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -8992,7 +8992,7 @@ fn wire__crate__api__voting__voting_share_plans_impl( let api_vote_end = <u64>::sse_decode(&mut deserializer); let api_ceremony_start = <u64>::sse_decode(&mut deserializer); let api_single_share = <bool>::sse_decode(&mut deserializer); - let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + let api__c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( @@ -9004,7 +9004,7 @@ fn wire__crate__api__voting__voting_share_plans_impl( api_vote_end, api_ceremony_start, api_single_share, - &api_c, + &api__c, ) .await?; Ok(output_ok) @@ -9873,21 +9873,27 @@ impl SseDecode for crate::api::frost::DKGStatus { return crate::api::frost::DKGStatus::WaitAddresses(var_field0); } 2 => { - return crate::api::frost::DKGStatus::PublishRound1Pkg; + return crate::api::frost::DKGStatus::PublishRound0Pkg; } 3 => { - return crate::api::frost::DKGStatus::WaitRound1Pkg; + return crate::api::frost::DKGStatus::WaitRound0Pkg; } 4 => { - return crate::api::frost::DKGStatus::PublishRound2Pkg; + return crate::api::frost::DKGStatus::PublishRound1Pkg; } 5 => { - return crate::api::frost::DKGStatus::WaitRound2Pkg; + return crate::api::frost::DKGStatus::WaitRound1Pkg; } 6 => { - return crate::api::frost::DKGStatus::Finalize; + return crate::api::frost::DKGStatus::PublishRound2Pkg; } 7 => { + return crate::api::frost::DKGStatus::WaitRound2Pkg; + } + 8 => { + return crate::api::frost::DKGStatus::Finalize; + } + 9 => { let mut var_field0 = <String>::sse_decode(deserializer); return crate::api::frost::DKGStatus::SharedAddress(var_field0); } @@ -13246,13 +13252,15 @@ impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { crate::api::frost::DKGStatus::WaitAddresses(field0) => { [1.into_dart(), field0.into_into_dart().into_dart()].into_dart() } - crate::api::frost::DKGStatus::PublishRound1Pkg => [2.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound1Pkg => [3.into_dart()].into_dart(), - crate::api::frost::DKGStatus::PublishRound2Pkg => [4.into_dart()].into_dart(), - crate::api::frost::DKGStatus::WaitRound2Pkg => [5.into_dart()].into_dart(), - crate::api::frost::DKGStatus::Finalize => [6.into_dart()].into_dart(), + crate::api::frost::DKGStatus::PublishRound0Pkg => [2.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound0Pkg => [3.into_dart()].into_dart(), + crate::api::frost::DKGStatus::PublishRound1Pkg => [4.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound1Pkg => [5.into_dart()].into_dart(), + crate::api::frost::DKGStatus::PublishRound2Pkg => [6.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitRound2Pkg => [7.into_dart()].into_dart(), + crate::api::frost::DKGStatus::Finalize => [8.into_dart()].into_dart(), crate::api::frost::DKGStatus::SharedAddress(field0) => { - [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() + [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() } _ => { unimplemented!(""); @@ -15550,23 +15558,29 @@ impl SseEncode for crate::api::frost::DKGStatus { <i32>::sse_encode(1, serializer); <Vec<String>>::sse_encode(field0, serializer); } - crate::api::frost::DKGStatus::PublishRound1Pkg => { + crate::api::frost::DKGStatus::PublishRound0Pkg => { <i32>::sse_encode(2, serializer); } - crate::api::frost::DKGStatus::WaitRound1Pkg => { + crate::api::frost::DKGStatus::WaitRound0Pkg => { <i32>::sse_encode(3, serializer); } - crate::api::frost::DKGStatus::PublishRound2Pkg => { + crate::api::frost::DKGStatus::PublishRound1Pkg => { <i32>::sse_encode(4, serializer); } - crate::api::frost::DKGStatus::WaitRound2Pkg => { + crate::api::frost::DKGStatus::WaitRound1Pkg => { <i32>::sse_encode(5, serializer); } - crate::api::frost::DKGStatus::Finalize => { + crate::api::frost::DKGStatus::PublishRound2Pkg => { <i32>::sse_encode(6, serializer); } - crate::api::frost::DKGStatus::SharedAddress(field0) => { + crate::api::frost::DKGStatus::WaitRound2Pkg => { <i32>::sse_encode(7, serializer); + } + crate::api::frost::DKGStatus::Finalize => { + <i32>::sse_encode(8, serializer); + } + crate::api::frost::DKGStatus::SharedAddress(field0) => { + <i32>::sse_encode(9, serializer); <String>::sse_encode(field0, serializer); } _ => { diff --git a/rust/src/frost/dkg.rs b/rust/src/frost/dkg.rs index c0d31383c..e0973e15d 100644 --- a/rust/src/frost/dkg.rs +++ b/rust/src/frost/dkg.rs @@ -676,7 +676,16 @@ pub async fn do_dkg_impl( }; // ── Round 0: broadcast signing public keys ──────────────────────────────── + // `run_round` publishes our own package only on the invocation where our + // secret does not exist yet, so checking for it first tells us whether this + // pass is a broadcast or just a poll for peer packages. let init = DkgInit { self_id, n, t }; + if <DkgRound0 as Round>::load_secret(connection, account) + .await? + .is_none() + { + status.send(DKGStatus::PublishRound0Pkg).await; + } let Some(state0) = run_round::<DkgRound0>( connection, account, @@ -693,7 +702,7 @@ pub async fn do_dkg_impl( ) .await? else { - status.send(DKGStatus::WaitRound1Pkg).await; // TODO: add WaitRound0Pkg status + status.send(DKGStatus::WaitRound0Pkg).await; return Ok(()); }; info!( @@ -702,6 +711,12 @@ pub async fn do_dkg_impl( ); // ── Round 1: everyone broadcasts one package to the shared address ──────── + if <DkgRound1 as Round>::load_secret(connection, account) + .await? + .is_none() + { + status.send(DKGStatus::PublishRound1Pkg).await; + } let Some(state1) = run_round::<DkgRound1>( connection, account, @@ -724,6 +739,12 @@ pub async fn do_dkg_impl( info!("Round 1 complete"); // ── Round 2: each sends a unique package to every peer's mailbox ────────── + if <DkgRound2 as Round>::load_secret(connection, account) + .await? + .is_none() + { + status.send(DKGStatus::PublishRound2Pkg).await; + } let Some(state2) = run_round::<DkgRound2>( connection, account, @@ -746,6 +767,7 @@ pub async fn do_dkg_impl( info!("Round 2 complete"); // ── Round 3: local only — derive the shared key ─────────────────────────── + status.send(DKGStatus::Finalize).await; let key_pkg = sqlx::query_as::<_, (Vec<u8>,)>( "SELECT key_pkg FROM dkg_state WHERE account = ? AND key_pkg IS NOT NULL", ) From 6ef0e7a259199a8ba2143cd6f671af8c8c3ae494 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 28 Aug 2026 03:50:04 +0800 Subject: [PATCH 127/189] test(dkg): add Flutter UI DKG integration test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `test_dkg.py` drives three headless zkool_graphql instances, so nothing exercised the DKG path a user actually takes. This adds a 3-of-3 DKG where participant #1 is the real Flutter app, driven through /dkg1 -> /dkg2 -> /dkg3, while #2 and #3 stay headless (they self-drive on every new block). The test passes when the shared address rendered on DKGPage3 matches the one both peers derive. Only one app instance can run per `flutter test` process — the macOS app is sandboxed under a single bundle id and shares one container — so the hybrid topology is the practical shape. pytest owns the chain, funding and peers, and spawns `flutter test` as a subprocess; the two sides exchange addresses through JSON files in the app's documents directory, since the sandboxed app cannot use /tmp. Blocks are mined on demand: `demand_miner` polls `getrawmempool` and mines one block whenever a transaction is waiting, with an idle fallback. A fixed-interval miner made runs non-deterministic by landing blocks at arbitrary points relative to the protocol. Production changes are limited to what the test needs to reuse the real widget tree: `router()` takes an optional `initialLocation` so the test can start on /dkg1 instead of /splash (which would reopen the user's own database), and `main()`'s tree moves into a `ZkoolApp` widget. Notes: - macOS only so far. `app_documents_dir()` and `flutter_device()` are platform-switched for Linux, but that path is untested; wallet.yml runs on ubuntu and would need a desktop build plus xvfb. - The test waits for the peers to finish after the UI participant is done; the app is usually a round ahead of them. - Never use pumpAndSettle on this route — DKGPage3's 30s timer and the synchronizer keep frames scheduled. Adds a dkg-ui-test skill documenting the stack, the run, the recording procedure and the failure modes worth knowing. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- .claude/skills/dkg-ui-test/SKILL.md | 177 ++++++++++++++ integration_test/dkg_ui_test.dart | 305 ++++++++++++++++++++++++ lib/main.dart | 22 +- lib/router.dart | 13 +- pubspec.lock | 39 +++ pubspec.yaml | 2 + tests/README.md | 33 +++ tests/pyproject.toml | 3 + tests/tests/dkg.py | 143 ++++++++++- tests/tests/test_dkg_ui.py | 356 ++++++++++++++++++++++++++++ 10 files changed, 1079 insertions(+), 14 deletions(-) create mode 100644 .claude/skills/dkg-ui-test/SKILL.md create mode 100644 integration_test/dkg_ui_test.dart create mode 100644 tests/tests/test_dkg_ui.py diff --git a/.claude/skills/dkg-ui-test/SKILL.md b/.claude/skills/dkg-ui-test/SKILL.md new file mode 100644 index 000000000..65887335a --- /dev/null +++ b/.claude/skills/dkg-ui-test/SKILL.md @@ -0,0 +1,177 @@ +--- +name: dkg-ui-test +description: "Run the Flutter-UI FROST DKG integration test (tests/test_dkg_ui.py) on a local zebra regtest chain, and optionally screen-record the app window. Use when asked to run, debug, or re-record the DKG UI test, or to bring up the local regtest + lightwalletd + zkool_graphql stack that it needs." +--- + +# Flutter UI DKG integration test + +`tests/tests/test_dkg_ui.py` runs a 3-of-3 FROST DKG where **participant #1 is the +real Flutter app**, driven through `/dkg1 → /dkg2 → /dkg3`, while participants #2 +and #3 are headless `zkool_graphql` instances. pytest owns the chain and the +peers and spawns `flutter test` as a subprocess; the two sides exchange addresses +through JSON files in the app's documents directory. + +Contrast with `tests/tests/test_dkg.py`, which is the same protocol with all three +participants headless — run that first to prove the stack before blaming the UI test. + +## Prerequisites + +Binaries not in the repo (this machine has them under `~/projects/tools/bin`): + +```bash +export PATH="$HOME/projects/tools/bin:$PATH" # zebrad, lightwalletd +``` + +Build the GraphQL server used for the peers (release; ~25 min from cold): + +```bash +cd rust +cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params +``` + +macOS: the app must have been launched at least once so its sandbox container +exists at `~/Library/Containers/cc.methyl.zkool/Data/Documents`. + +## 1. Bring up the regtest chain + +Blocks are **not** mined automatically — `misc/zebra.toml` sets only +`miner_address`, zebra's internal miner is off. Every block comes from an +explicit `generate` RPC call. + +```bash +cd ~/projects/zkool2 +export PATH="$HOME/projects/tools/bin:$PATH" + +# Full reset (chain + all test data) +pkill -9 zkool_graphql; pkill lightwalletd; pkill zebrad +rm -rf ~/Library/Caches/zebra ./data ./regtest.db +rm -f ~/Library/Containers/cc.methyl.zkool/Data/Documents/regtest_dkg_ui.db +rm -rf ~/Library/Containers/cc.methyl.zkool/Data/Documents/dkg_ui_rendezvous + +# zebra.toml needs a miner address (local edit, do not commit) +sed -i '' 's#miner_address = ""#miner_address = "tmQ1BiNRfsvT6eMkJ5n7nMZsbz1PGwCs1Zs"#' misc/zebra.toml + +nohup zebrad -c misc/zebra.toml start > zebrad.log 2>&1 & +until curl -sf -m 3 --data-binary '{"jsonrpc":"1.0","id":"p","method":"getinfo","params":[]}' \ + -H 'content-type: application/json' http://127.0.0.1:18232/ >/dev/null; do sleep 2; done + +mkdir -p ./data/regtest +nohup lightwalletd --no-tls-very-insecure --data-dir=./data/regtest \ + --grpc-bind-addr=127.0.0.1:8137 --zcash-conf-path=./misc/zebra.conf \ + --log-file=/dev/stdout > lightwalletd.log 2>&1 & +until nc -z -w 2 localhost 8137; do sleep 2; done + +# Mine past NU6.3 / Ironwood, which activates at height 250 on regtest +curl -s --data-binary '{"jsonrpc":"1.0","id":"g","method":"generate","params":[350]}' \ + -H 'Content-type: application/json' http://127.0.0.1:18232/ | jq '.result|length' +``` + +## 2. Fund the SEED wallet + +`example/sh/regtest_setup.sh` does chain bring-up *and* funding in one go. If the +chain is already up, run only the funding half: start `zkool_graphql` on :8000 +against `regtest.db`, create the `miner` (MINER_SEED) and `wallet` (SEED) +accounts at birth 1, sync both, take the miner's notes with +`height < tip-100`, pay the total to `DESTINATION_ADDRESS` with +`recipientPaysFee: true, confirmations: 100`, mine 10, sync, and check +`balanceByAccount.ironwood > 0` (expect ~62.5). + +Seeds and the destination UA are inlined at the top of `example/sh/regtest_setup.sh`. + +## 3. Run the test + +```bash +cd tests +SEED="invite couch cloud pave stuff cabbage usual rigid dragon warm cable price fame warfare next swallow worth opera suggest flame patch undo position arctic" \ + .venv/bin/python -m pytest tests/test_dkg_ui.py -v -s +``` + +Expect ~3.5 min warm; the first run adds a macOS debug build of the app plus the +Rust staticlib. Logs: `/tmp/dkg_ui_flutter.log` (Flutter side, dumped by pytest on +failure) and `/tmp/graphql_8002.log` / `/tmp/graphql_8003.log` (peers). + +Watch progress without touching the app's database: + +```bash +sed 's/\x1b\[[0-9;]*m//g' /tmp/dkg_ui_flutter.log | grep -a "dkg-ui] status" +``` + +Expected sequence: + +``` +Broadcasting participant keys +Waiting for other participants to send their keys +Broadcasting round 1 packages +Waiting for other participants to send their round 1 packages +Broadcasting round 2 packages +The shared address is: uregtest1... +``` + +## Things that will bite you + +- **Never query the app's SQLite file while the test runs.** It is in rollback-journal + mode, and a concurrent reader causes `database is locked` errors inside the app. +- **The db filename must contain `regtest`** — that substring is what selects + `Network::Regtest` (`rust/src/api/coin.rs:266`). Without it the app runs mainnet + parameters. +- **The macOS app is sandboxed** and cannot read or write `/tmp`; the rendezvous dir + and the UI participant's db must live in the container's Documents directory. +- **Do not `osascript -e 'tell application "zkool" to activate'`** — it launches + `/Applications/zkool.app` (the real mainnet wallet), which shares the bundle id + and container with the Debug build and breaks the run (`flutter test` exits 79). + Raise the test app by process only: `tell application "System Events" to set + frontmost of process "zkool" to true`, which needs Accessibility for Terminal. +- **Mining is on demand**, driven by `demand_miner()` in `tests/tests/dkg.py`: it + polls `getrawmempool` and mines one block whenever a transaction is waiting, with + a 60s idle fallback. Do not go back to a fixed-interval miner — it makes the run + non-deterministic. +- **The app polls every 30s** (`Timer.periodic` in `DKGPage3`, `lib/pages/dkg.dart`) + while the peers advance on every block, so the app is usually a round behind. The + test waits up to `PEER_COMPLETION_TIMEOUT` (600s) for the peers to finish *after* + the app is done — without that wait the test fails with "No FROST account for + participant 2". +- **Never use `pumpAndSettle`** on the DKG route; the 30s timer and the synchronizer + keep frames scheduled so it never settles. Use the `pumpUntil` / `pumpFor` helpers. + +## Screen-recording the run (macOS) + +Requires Accessibility for Terminal (System Settings → Privacy & Security → +Accessibility) so the window can be raised. A local, uncommitted block in +`macos/Runner/MainFlutterWindow.swift` forces the window to 1100x820 and sets +`isRestorable = false`; it must run **after** `super.awakeFromNib()`, or macOS +state restoration reapplies the old near-fullscreen frame. + +```bash +# once the app is up +osascript -e 'tell application "System Events" to set frontmost of process "zkool" to true' +osascript -e 'tell application "System Events" to tell process "zkool" to get {position, size} of front window' +# -> e.g. 305, 75, 1100, 850 (points, not pixels) + +screencapture -v -R305,75,1100,850 /tmp/rec.mp4 & # region capture: app window only +# re-raise every few seconds while the run proceeds, then: +kill -INT <screencapture pid> # SIGINT finalizes the mp4 + +ffmpeg -i /tmp/rec.mp4 -vf "scale=1100:-2,fps=12" -c:v libx264 -crf 30 \ + -pix_fmt yuv420p /tmp/dkg_ui.mp4 +``` + +Trim the tail: when the test ends the app closes and the recorded region exposes +whatever was behind it. The Dart test holds the finished screen for 6s +(`pumpFor`) so the Finalize step and shared address are visible. + +## Teardown + +```bash +pkill -f zkool_graphql; pkill lightwalletd; pkill zebrad +rm -rf ~/Library/Caches/zebra ./data ./regtest.db +git checkout misc/zebra.toml # drops the local miner_address edit +``` + +## CI + +`.github/workflows/wallet.yml` runs on `ubuntu-latest` and does not include this +test. Porting it needs a desktop Flutter build plus a display (`-d linux` under +`xvfb-run`, GTK dev packages) on top of the existing regtest stack. +`app_documents_dir()` and `flutter_device()` in `tests/tests/dkg.py` are already +platform-switched for this, but the Linux path is **untested** — only macOS has +been verified. diff --git a/integration_test/dkg_ui_test.dart b/integration_test/dkg_ui_test.dart new file mode 100644 index 000000000..88e81144e --- /dev/null +++ b/integration_test/dkg_ui_test.dart @@ -0,0 +1,305 @@ +/// Integration test: run the Flutter app as FROST DKG participant #1 against a +/// regtest chain, while the other participants run headless as `zkool_graphql` +/// instances driven by `tests/tests/test_dkg_ui.py`. +/// +/// The Python side owns the chain (funding, mining) and the peer participants. +/// Both sides exchange addresses through JSON files in a rendezvous directory +/// that lives inside the macOS app sandbox container — see +/// `tests/tests/dkg.py` for the other half of the protocol. +library; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/router.dart'; +import 'package:zkool/src/rust/api/account.dart'; +import 'package:zkool/src/rust/api/coin.dart' hide initDatadir; +import 'package:zkool/src/rust/api/db.dart'; +import 'package:zkool/src/rust/api/network.dart'; +import 'package:zkool/src/rust/frb_generated.dart'; +import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; + +/// Directory shared with the Python orchestrator, passed as +/// `--dart-define=ZKOOL_TEST_RENDEZVOUS=<dir>`. Defaults to +/// `<documents>/dkg_ui_rendezvous`, which is where the Python side puts it. +const rendezvousOverride = String.fromEnvironment("ZKOOL_TEST_RENDEZVOUS"); + +/// JSON file rendezvous with the Python orchestrator. +class Rendezvous { + final Directory dir; + + Rendezvous(this.dir); + + File get _config => File("${dir.path}/config.json"); + File get _ui => File("${dir.path}/ui.json"); + File get _peers => File("${dir.path}/peers.json"); + + Map<String, dynamic> readConfig() => + jsonDecode(_config.readAsStringSync()) as Map<String, dynamic>; + + Map<String, dynamic>? readPeers() { + if (!_peers.existsSync()) return null; + try { + return jsonDecode(_peers.readAsStringSync()) as Map<String, dynamic>; + } on FormatException { + return null; // partially written; the writer renames atomically but be safe + } + } + + final Map<String, dynamic> _uiState = {}; + + /// Publishes [key] to the orchestrator. Written to a temp file then renamed + /// so the reader never observes a partial document. + void publish(String key, String value) { + _uiState[key] = value; + final tmp = File("${_ui.path}.tmp"); + tmp.writeAsStringSync(jsonEncode(_uiState)); + tmp.renameSync(_ui.path); + } +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets("DKG participant #1 through the Flutter UI", (tester) async { + final docsDir = await getApplicationDocumentsDirectory(); + final rendezvous = Rendezvous(Directory( + rendezvousOverride.isNotEmpty ? rendezvousOverride : "${docsDir.path}/dkg_ui_rendezvous",),); + expect(rendezvous.dir.existsSync(), isTrue, + reason: "rendezvous dir ${rendezvous.dir.path} missing — start this test from test_dkg_ui.py",); + + final config = rendezvous.readConfig(); + final dbPath = config["db_path"] as String; + final lwd = config["lwd"] as String; + final n = config["n"] as int; + final t = config["t"] as int; + final myId = config["my_id"] as int; + final dkgName = config["name"] as String; + + // The database filename must contain "regtest": that substring is what + // selects Network::Regtest in rust/src/api/coin.rs. + expect(dbPath, contains("regtest")); + + final prefs = SharedPreferencesAsync(); + // Saved so the developer's own app settings survive the test run. + final savedPinLock = await prefs.getBool("pin_lock"); + final savedOffline = await prefs.getBool("offline"); + final savedVault = await prefs.getBool("vault"); + + try { + // ── Setup: Rust bridge, database, funding account ───────────────────── + await tester.runAsync(() async { + await RustLib.init(); + await initDatadir(directory: docsDir.path); + + final dbFile = File(dbPath); + if (dbFile.existsSync()) dbFile.deleteSync(); + + await prefs.setBool("pin_lock", false); + await prefs.setBool("offline", false); + await prefs.setBool("vault", false); + + var c = await Coin().openDatabase(dbFilepath: dbPath, password: null); + await putProp(key: "lwd", value: lwd, c: c); + await putProp(key: "is_light_node", value: "true", c: c); + c = c.setLwd(serverType: 0, url: lwd); + coinContext.set(coin: c); + + final account = await newAccount( + na: NewAccount( + name: "DKG-Fund", + restore: false, + key: "", + aindex: 0, + birth: 1, + folder: "", + useInternal: false, + internal: false, + ledger: false, + ), + c: coinContext.coin, + ); + await coinContext.setAccount(account: account); + // uaPools 6 = sapling|orchard, matching the GraphQL `ironwood` address. + final addresses = await getAddresses(uaPools: 6, c: coinContext.coin); + final fundingAddress = addresses.oaddr!; + debugPrint("[dkg-ui] funding account $account address $fundingAddress"); + rendezvous.publish("funding_address", fundingAddress); + }); + + // ── Start the app directly on the DKG wizard ────────────────────────── + await tester.pumpWidget( + ZkoolApp(router: router(true, false, initialLocation: "/dkg1")),); + await tester.pump(const Duration(seconds: 1)); + + final view = tester.view; + final logicalSize = view.physicalSize / view.devicePixelRatio; + debugPrint( + "[dkg-ui] window ${logicalSize.width.toStringAsFixed(0)}" + "x${logicalSize.height.toStringAsFixed(0)} logical " + "(dpr ${view.devicePixelRatio})", + ); + + // Splash normally does this; without it the settings provider stays in + // AsyncLoading and `startSynchronize`'s requireValue would throw. + final container = ProviderScope.containerOf(tester.element(find.byType(MaterialApp))); + // Read the settings first: it watches hasDbProvider, which keeps that + // (auto-dispose) notifier alive across the setHasDb call below. + container.read(appSettingsProvider); + container.read(hasDbProvider.notifier).setHasDb(); + await pumpUntil( + tester, + () => container.read(appSettingsProvider).hasValue, + timeout: const Duration(seconds: 30), + what: "app settings to load", + ); + + // ── Page 1: DKG parameters ──────────────────────────────────────────── + await pumpUntil(tester, () => find.text("Number of Participants").evaluate().isNotEmpty, + timeout: const Duration(seconds: 30), what: "DKG page 1",); + await tester.enterText(fieldNamed("name"), dkgName); + await tester.pump(); + await selectDropdown(tester, "Number of Participants", "$n"); + await selectDropdown(tester, "Your Participant ID", "$myId"); + await selectDropdown(tester, "Number of Signers Required (Threshold)", "$t"); + await selectDropdown(tester, "Funding Account for the DKG messages", "DKG-Fund"); + await tapNext(tester); + + // ── Page 2: exchange DKG addresses ──────────────────────────────────── + await pumpUntil(tester, () => find.text("DKG Addresses").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), what: "DKG page 2",); + await pumpUntil(tester, () => fieldNamed("${myId - 1}").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), what: "own DKG address field",); + + final myAddress = + tester.widget<FormBuilderTextField>(fieldNamed("${myId - 1}")).initialValue!; + expect(myAddress, isNotEmpty); + debugPrint("[dkg-ui] my DKG address $myAddress"); + rendezvous.publish("dkg_address", myAddress); + + Map<String, dynamic>? peers; + await pumpUntil(tester, () { + peers = rendezvous.readPeers(); + return peers != null && peers!.length == n - 1; + }, timeout: const Duration(minutes: 10), what: "peer DKG addresses",); + + for (final entry in peers!.entries) { + final index = int.parse(entry.key) - 1; + final field = fieldNamed("$index"); + await tester.ensureVisible(field); + await tester.enterText(field, entry.value as String); + await tester.pump(); + } + await tapNext(tester); + + // ── Page 3: run the DKG rounds ──────────────────────────────────────── + await pumpUntil(tester, () => find.text("Distributed Key Generation").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), what: "DKG page 3",); + + const sharedPrefix = "The shared address is: "; + CopyableText? status; + var lastStatus = ""; + await pumpUntil( + tester, + () { + final found = find.byType(CopyableText).evaluate(); + if (found.isEmpty) return false; + final w = found.first.widget as CopyableText; + // Publish every status change: it makes the round progression + // visible to the orchestrator and to anyone reading the log. + if (w.text.isNotEmpty && w.text != lastStatus) { + lastStatus = w.text; + debugPrint("[dkg-ui] status: ${w.text}"); + rendezvous.publish("status", w.text); + } + if (!w.text.startsWith(sharedPrefix)) return false; + status = w; + return true; + }, + timeout: const Duration(minutes: 15), + what: "the shared address", + ); + + final sharedAddress = status!.text.substring(sharedPrefix.length).trim(); + expect(sharedAddress, isNotEmpty); + debugPrint("[dkg-ui] shared address $sharedAddress"); + rendezvous.publish("shared_address", sharedAddress); + + // Hold the finished screen briefly so the "Finalize" step and the shared + // address are actually observable (on screen, and in a screen recording) + // instead of vanishing the instant the assertion passes. + await pumpFor(tester, const Duration(seconds: 6)); + } finally { + await restoreBool(prefs, "pin_lock", savedPinLock); + await restoreBool(prefs, "offline", savedOffline); + await restoreBool(prefs, "vault", savedVault); + } + }, timeout: const Timeout(Duration(minutes: 40)),); +} + +Future<void> restoreBool(SharedPreferencesAsync prefs, String key, bool? value) async { + if (value == null) { + await prefs.remove(key); + } else { + await prefs.setBool(key, value); + } +} + +Finder fieldNamed(String name) => + find.byWidgetPredicate((w) => w is FormBuilderTextField && w.name == name); + +/// Pumps real frames until [done] holds. `pumpAndSettle` is unusable on the DKG +/// route: DKGPage3 installs a 30s periodic timer and the synchronizer keeps +/// scheduling frames, so the tree never settles. +Future<void> pumpUntil( + WidgetTester tester, + bool Function() done, { + required Duration timeout, + required String what, +}) async { + final deadline = DateTime.now().add(timeout); + while (DateTime.now().isBefore(deadline)) { + if (done()) return; + await tester.pump(const Duration(milliseconds: 500)); + } + fail("timed out after $timeout waiting for $what"); +} + +/// Pumps real frames for [duration]. Used instead of `pumpAndSettle`, which +/// cannot be trusted anywhere on this route (see [pumpUntil]). +Future<void> pumpFor(WidgetTester tester, Duration duration) async { + final deadline = DateTime.now().add(duration); + while (DateTime.now().isBefore(deadline)) { + await tester.pump(const Duration(milliseconds: 100)); + } +} + +Future<void> selectDropdown(WidgetTester tester, String label, String value) async { + final dropdown = find.ancestor( + of: find.text(label), + matching: find.byType(FormBuilderDropdown<int>), + ); + await tester.ensureVisible(dropdown.first); + await tester.pump(); + await tester.tap(dropdown.first, warnIfMissed: false); + await pumpFor(tester, const Duration(seconds: 1)); + await tester.tap(find.text(value).last); + await pumpFor(tester, const Duration(seconds: 1)); +} + +Future<void> tapNext(WidgetTester tester) async { + final next = find.widgetWithText(ElevatedButton, "Next"); + await tester.ensureVisible(next); + await tester.pump(); + await tester.tap(next); + await pumpFor(tester, const Duration(seconds: 1)); +} diff --git a/lib/main.dart b/lib/main.dart index 869d8eaa6..261e0682a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flex_color_scheme/flex_color_scheme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; import 'package:logger/logger.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -33,8 +34,19 @@ Future<void> main() async { final r = router(disclaimerAccepted, recovery); - runApp( - ProviderScope( + runApp(ZkoolApp(router: r)); +} + +/// The application widget tree, extracted from [main] so that integration +/// tests can pump the exact same tree with a router of their own. +class ZkoolApp extends StatelessWidget { + final GoRouter router; + + const ZkoolApp({super.key, required this.router}); + + @override + Widget build(BuildContext context) { + return ProviderScope( child: ToastificationConfigProvider( config: ToastificationConfig( marginBuilder: (c, a) => const EdgeInsets.only(top: 76), @@ -54,7 +66,7 @@ Future<void> main() async { final darkTheme = FlexThemeData.dark(scheme: scheme).copyWith(useMaterial3: true); return MaterialApp.router( key: appKey, - routerConfig: r, + routerConfig: router, builder: (context, child) => SafeArea( top: false, left: false, @@ -69,8 +81,8 @@ Future<void> main() async { }), ), ), - ), - ); + ); + } } class PinLock extends ConsumerStatefulWidget { diff --git a/lib/router.dart b/lib/router.dart index 189d1e8a2..c62ef7648 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -46,12 +46,13 @@ import 'package:zkool/widgets/scanner.dart'; final navigatorKey = GlobalKey<NavigatorState>(); final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>(); -GoRouter router(bool disclaimerAccepted, bool recoveryMode) => GoRouter( - initialLocation: !disclaimerAccepted - ? '/disclaimer' - : recoveryMode - ? '/database_manager' - : '/splash', +GoRouter router(bool disclaimerAccepted, bool recoveryMode, {String? initialLocation}) => GoRouter( + initialLocation: initialLocation ?? + (!disclaimerAccepted + ? '/disclaimer' + : recoveryMode + ? '/database_manager' + : '/splash'), observers: [routeObserver], navigatorKey: navigatorKey, routes: [ diff --git a/pubspec.lock b/pubspec.lock index 5a7fbd589..cfd1e9b8b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -470,6 +470,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.1" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_form_builder: dependency: "direct main" description: @@ -662,6 +667,11 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" gap: dependency: "direct main" description: @@ -878,6 +888,11 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.2" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" intl: dependency: "direct main" description: @@ -1206,6 +1221,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.3" + process: + dependency: transitive + description: + name: process + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 + url: "https://pub.dev" + source: hosted + version: "5.0.5" pub_semver: dependency: transitive description: @@ -1474,6 +1497,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" term_glyph: dependency: transitive description: @@ -1674,6 +1705,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + url: "https://pub.dev" + source: hosted + version: "3.1.0" webkit_inspection_protocol: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index afdf99521..2380b296a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -80,6 +80,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + integration_test: + sdk: flutter flutter_lints: ^5.0.0 build_runner: ^2.1.2 diff --git a/tests/README.md b/tests/README.md index 042ef8471..989789f3e 100644 --- a/tests/README.md +++ b/tests/README.md @@ -40,3 +40,36 @@ source .venv/bin/activate pip install -e ".[dev]" pytest ``` + +## Flutter UI DKG test + +`tests/test_dkg_ui.py` runs the same 3-of-3 FROST DKG as `test_dkg.py`, but +participant #1 is the **real Flutter app** instead of a headless +`zkool_graphql` instance: pytest starts the funding instance and participants +#2/#3, then spawns + +```bash +flutter test integration_test/dkg_ui_test.dart -d <macos|linux> \ + --dart-define=ZKOOL_TEST_RENDEZVOUS=<dir> +``` + +and drives the app's `/dkg1 → /dkg2 → /dkg3` pages. Both sides exchange addresses through JSON +files in the app's documents directory — on macOS +`~/Library/Containers/cc.methyl.zkool/Data/Documents/dkg_ui_rendezvous`, since +the sandboxed app cannot use `/tmp`; on Linux `~/Documents/dkg_ui_rendezvous`. + +```bash +.venv/bin/uv run pytest tests/test_dkg_ui.py -v -s +``` + +Requirements beyond the usual regtest stack: +- a desktop session — `flutter test -d macos|linux` opens a window (under CI on + Linux this needs `xvfb-run`) +- the app's documents directory must exist; on macOS that means the app has + been launched at least once so its sandbox container is created +- the first run builds the desktop app and the Rust staticlib in debug (slow) + +The test writes `regtest_dkg_ui.db` into the app's Documents directory and +temporarily overrides the `pin_lock`, `offline` and `vault` preferences, +restoring them when it finishes. It never touches the developer's own wallet +database. diff --git a/tests/pyproject.toml b/tests/pyproject.toml index bebf16a3e..aab08f254 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -36,3 +36,6 @@ select = ["E", "F", "I", "N", "W"] [tool.pytest.ini_options] asyncio_mode = "auto" +markers = [ + "dkg_ui: DKG test driving the Flutter UI; needs a GUI session and a long macOS build", +] diff --git a/tests/tests/dkg.py b/tests/tests/dkg.py index 4fdc07eb0..12cf6d405 100644 --- a/tests/tests/dkg.py +++ b/tests/tests/dkg.py @@ -1,23 +1,27 @@ """DKG participant class and utilities for FROST testing.""" +import asyncio +import json import os +import shutil import sqlite3 import subprocess +import sys import httpx -from gql import Client, GraphQLRequest, gql +from gql import Client, GraphQLRequest from gql.transport.httpx import HTTPXAsyncTransport - from utils import mine_blocks class DkgParticipant: """Represents a participant in a FROST DKG protocol.""" - def __init__(self, port: int, db_path: str, lwd_url: str): + def __init__(self, port: int, db_path: str, lwd_url: str, id: int | None = None): self.port = port self.db_path = db_path self.lwd_url = lwd_url + self.id = id self.url = f"http://localhost:{port}/graphql" self.process: subprocess.Popen | None = None self.funding_account: int | None = None @@ -137,3 +141,136 @@ async def poll_with_block_mining( elapsed += interval return False + + +MACOS_BUNDLE_ID = "cc.methyl.zkool" + + +def app_documents_dir() -> str: + """Whatever `getApplicationDocumentsDirectory()` returns for the app. + + On macOS the app is sandboxed (com.apple.security.app-sandbox), so it can + neither read nor write /tmp: the UI participant's database and the + rendezvous files have to live inside its container. On Linux there is no + sandbox and path_provider returns ~/Documents. + """ + if sys.platform == "darwin": + return os.path.expanduser(f"~/Library/Containers/{MACOS_BUNDLE_ID}/Data/Documents") + return os.path.expanduser("~/Documents") + + +def flutter_device() -> str: + """The `flutter test -d <device>` desktop target for this platform.""" + return {"darwin": "macos", "linux": "linux", "win32": "windows"}[sys.platform] + + +class Rendezvous: + """File-based handshake with the Flutter integration test. + + pytest cannot talk to the app over GraphQL, and both sides need addresses + from the other while the `flutter test` subprocess is running, so they + exchange JSON documents in a shared directory. Every write goes to a temp + file and is renamed, so a reader never sees a partial document. + """ + + def __init__(self, directory: str): + self.dir = directory + + @property + def config_path(self) -> str: + return os.path.join(self.dir, "config.json") + + @property + def ui_path(self) -> str: + return os.path.join(self.dir, "ui.json") + + @property + def peers_path(self) -> str: + return os.path.join(self.dir, "peers.json") + + def setup(self): + shutil.rmtree(self.dir, ignore_errors=True) + os.makedirs(self.dir, exist_ok=True) + + def cleanup(self): + shutil.rmtree(self.dir, ignore_errors=True) + + def _write(self, path: str, payload: dict): + tmp = path + ".tmp" + with open(tmp, "w") as f: + json.dump(payload, f) + os.replace(tmp, path) + + def write_config(self, **payload): + self._write(self.config_path, payload) + + def write_peers(self, peers: dict[int, str]): + self._write(self.peers_path, {str(k): v for k, v in peers.items()}) + + def read_ui(self) -> dict: + if not os.path.exists(self.ui_path): + return {} + try: + with open(self.ui_path) as f: + return json.load(f) + except json.JSONDecodeError: + return {} + + async def poll_ui(self, key: str, timeout: int = 600, interval: int = 2, process=None): + """Wait until the Flutter test publishes `key`, or fail loudly. + + If `process` is given and it exits before the key shows up, raise + immediately instead of waiting out the whole timeout. + """ + elapsed = 0 + while elapsed < timeout: + value = self.read_ui().get(key) + if value: + return value + if process is not None and process.returncode is not None: + raise RuntimeError( + f"flutter test exited with {process.returncode} before publishing '{key}'" + ) + await asyncio.sleep(interval) + elapsed += interval + raise TimeoutError(f"timed out waiting for the UI participant to publish '{key}'") + + +async def get_raw_mempool(rpc_url: str) -> list: + """Transaction ids currently sitting in the node's mempool.""" + payload = {"jsonrpc": "1.0", "id": "mempool", "method": "getrawmempool", "params": []} + async with httpx.AsyncClient() as client: + response = await client.post(rpc_url, json=payload) + response.raise_for_status() + return response.json().get("result") or [] + + +async def demand_miner(rpc_url: str, poll: int = 2, idle_fallback: int = 60): + """Mine a block whenever there is something to confirm, until cancelled. + + The DKG advances by passing packages in transaction memos, so a round only + completes once the sender's transaction is mined. Mining on a fixed timer + makes the run non-deterministic — blocks land at arbitrary points relative + to the protocol. Watching the mempool instead ties each block to the + broadcast that needs it, so the chain moves exactly when the protocol does. + + `idle_fallback` is a safety valve only: if nothing has been broadcast for + that long the tip is nudged forward once, so a participant waiting on a new + tip (rather than on a transaction) cannot wedge the run. + """ + loop = asyncio.get_running_loop() + last_mine = loop.time() + try: + while True: + try: + if await get_raw_mempool(rpc_url): + await mine_blocks(rpc_url, 1) + last_mine = loop.time() + elif loop.time() - last_mine > idle_fallback: + await mine_blocks(rpc_url, 1) + last_mine = loop.time() + except Exception as e: # a transient RPC hiccup must not kill the run + print(f"[miner] {e}") + await asyncio.sleep(poll) + except asyncio.CancelledError: + pass diff --git a/tests/tests/test_dkg_ui.py b/tests/tests/test_dkg_ui.py new file mode 100644 index 000000000..dc7fb6b9f --- /dev/null +++ b/tests/tests/test_dkg_ui.py @@ -0,0 +1,356 @@ +"""FROST DKG where participant #1 is the real Flutter app. + +Same protocol as test_dkg.py, but instead of three headless zkool_graphql +instances, participant #1 is the macOS app driven through its DKG pages by +`integration_test/dkg_ui_test.dart`. This test owns the chain (funding, block +mining) and the two headless peers; it talks to the app through a JSON file +rendezvous inside the app's sandbox container. + +Requires an interactive GUI session — `flutter test -d macos` opens a window. +The first run also builds the app in debug, which takes several minutes. +""" + +import asyncio +import contextlib +import os +import shutil + +import pytest +from dkg import DkgParticipant, Rendezvous, app_documents_dir, demand_miner, flutter_device +from gql import GraphQLRequest, gql +from utils import ( + dump_server_log, + get_current_height, + kill_existing_zkool_processes, + mine_blocks, + wait_for_blocks, +) + +N = 3 +T = 3 +DEFAULT_PORT = 8000 +PORT_BASE = 8002 # peers are participants #2 and #3 +LWD_URL = "http://localhost:8137" +DKG_NAME_PREFIX = "Dkg-Test-UI" +FLUTTER_LOG = "/tmp/dkg_ui_flutter.log" +# How long the headless peers get to finish after the UI participant is done. +PEER_COMPLETION_TIMEOUT = 600 + +CREATE_ACCOUNT = gql( + """ + mutation ($name: String!, $key: String!) { + createAccount(newAccount: { + name: $name + key: $key + aindex: 0 + useInternal: false + birth: 1 + }) + } + """ +) + +ADDRESS_QUERY = gql( + """ + query ($account: Int!) { + addressByAccount(idAccount: $account) { ironwood } + } + """ +) + +BALANCE_QUERY = gql( + """ + query ($account: Int!) { + balanceByAccount(idAccount: $account) { ironwood } + } + """ +) + +SYNC_MUTATION = gql( + """ + mutation ($account: Int!) { + synchronizeAccount(idAccount: $account) + } + """ +) + +DKG_START = gql( + """ + mutation ($name: String!, $t: Int!, $n: Int!, $funding: Int!, $id: Int!) { + dkgStart( + name: $name + threshold: $t + participants: $n + messageAccount: $funding + idParticipant: $id + ) + } + """ +) + +DKG_SET_ADDRESS = gql( + """ + mutation ($id: Int!, $address: String!) { + dkgSetAddress(idParticipant: $id, address: $address) + } + """ +) + +DO_DKG = gql("mutation { doDkg }") + +PAY = gql( + """ + mutation ($account: Int!, $recipients: [Recipient!]!) { + pay(idAccount: $account, payment: {recipients: $recipients}) + } + """ +) + + +def repo_root() -> str: + return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) + + +@pytest.mark.dkg_ui +@pytest.mark.asyncio +async def test_dkg_3_of_3_flutter_ui(graphql_url, rpc_url, seed, zkool_binary, gql_client_factory): + """3-out-of-3 DKG with the Flutter app as participant #1.""" + if not seed: + pytest.skip("SEED not set") + if not os.path.exists(zkool_binary): + pytest.skip(f"zkool_graphql binary not found at {zkool_binary}") + + docs_dir = app_documents_dir() + if not os.path.isdir(docs_dir): + pytest.skip( + f"app documents directory {docs_dir} not found — " + "launch the app once before running this test" + ) + if shutil.which(os.getenv("FLUTTER_BIN", "flutter")) is None: + pytest.skip("flutter not on PATH") + + # The db filename must contain "regtest": that is what selects + # Network::Regtest in rust/src/api/coin.rs. + ui_db_path = os.path.join(docs_dir, "regtest_dkg_ui.db") + rendezvous = Rendezvous(os.path.join(docs_dir, "dkg_ui_rendezvous")) + + participants: list[DkgParticipant] = [] + default_participant = None + flutter = None + miner = None + + try: + await kill_existing_zkool_processes() + rendezvous.setup() + for stale in (ui_db_path, FLUTTER_LOG): + if os.path.exists(stale): + os.remove(stale) + + print("=== Step 1: Start the default (funding) instance and the headless peers ===") + default_participant = DkgParticipant( + DEFAULT_PORT, "/tmp/regtest_dkg_ui_default.db", LWD_URL + ) + default_participant.start(zkool_binary) + await asyncio.sleep(2) + + for i in range(2, N + 1): + port = PORT_BASE + i - 2 + participant = DkgParticipant(port, f"/tmp/regtest_dkg_ui_{i}.db", LWD_URL, id=i) + participant.start(zkool_binary) + participants.append(participant) + print(f"Started participant {i} on port {port}") + await asyncio.sleep(2) + + print("\n=== Step 2: Create the funded wallet on the default instance ===") + async with gql_client_factory(graphql_url) as client: + result = await client.execute_async( + GraphQLRequest(CREATE_ACCOUNT, variable_values={"name": "Main", "key": seed}) + ) + main_wallet = int(result["createAccount"]) + await client.execute_async( + GraphQLRequest(SYNC_MUTATION, variable_values={"account": main_wallet}) + ) + result = await client.execute_async( + GraphQLRequest(BALANCE_QUERY, variable_values={"account": main_wallet}) + ) + print(f"Funding wallet {main_wallet} balance: {result['balanceByAccount']['ironwood']}") + + print("\n=== Step 3: Initialize DKG on the headless peers ===") + for participant in participants: + i = participant.id + result = await participant.execute( + GraphQLRequest(CREATE_ACCOUNT, variable_values={"name": "DKG-Fund", "key": ""}) + ) + participant.funding_account = int(result["createAccount"]) + result = await participant.execute( + GraphQLRequest( + ADDRESS_QUERY, variable_values={"account": participant.funding_account} + ) + ) + participant.funding_address = result["addressByAccount"]["ironwood"] + result = await participant.execute( + GraphQLRequest( + DKG_START, + variable_values={ + "name": f"{DKG_NAME_PREFIX}-{i}", + "t": T, + "n": N, + "funding": participant.funding_account, + "id": i, + }, + ) + ) + participant.dkg_address = result["dkgStart"] + print(f"Participant {i} funding {participant.funding_address}") + print(f"Participant {i} DKG address {participant.dkg_address}") + + print("\n=== Step 4: Launch the Flutter integration test ===") + rendezvous.write_config( + db_path=ui_db_path, + lwd=LWD_URL, + n=N, + t=T, + my_id=1, + name=f"{DKG_NAME_PREFIX}-1", + ) + flutter_log = open(FLUTTER_LOG, "w") + flutter = await asyncio.create_subprocess_exec( + os.getenv("FLUTTER_BIN", "flutter"), + "test", + "integration_test/dkg_ui_test.dart", + "-d", + flutter_device(), + f"--dart-define=ZKOOL_TEST_RENDEZVOUS={rendezvous.dir}", + cwd=repo_root(), + stdout=flutter_log, + stderr=asyncio.subprocess.STDOUT, + ) + print(f"flutter test pid {flutter.pid}, log {FLUTTER_LOG}") + + print("\n=== Step 5: Wait for the UI participant's funding address ===") + # Generous: the first run builds the macOS app and the Rust staticlib. + ui_funding_address = await rendezvous.poll_ui( + "funding_address", timeout=2400, process=flutter + ) + print(f"UI funding address {ui_funding_address}") + + print("\n=== Step 6: Fund every participant ===") + recipients = [{"address": ui_funding_address, "amount": "0.01"}] + recipients += [{"address": p.funding_address, "amount": "0.01"} for p in participants] + async with gql_client_factory(graphql_url) as client: + result = await client.execute_async( + GraphQLRequest( + PAY, variable_values={"account": main_wallet, "recipients": recipients} + ) + ) + print(f"Funding transaction: {result['pay']}") + + print("\n=== Step 7: Mine and synchronize the peers ===") + peer_client = await participants[0].get_client() + height = await get_current_height(peer_client) + await mine_blocks(rpc_url, 5) + await wait_for_blocks(peer_client, height, 5) + for participant in participants: + await participant.execute( + GraphQLRequest( + SYNC_MUTATION, variable_values={"account": participant.funding_account} + ) + ) + result = await participant.execute( + GraphQLRequest( + BALANCE_QUERY, variable_values={"account": participant.funding_account} + ) + ) + balance = result["balanceByAccount"]["ironwood"] + print(f"Participant {participant.id} funding balance: {balance}") + assert balance and balance != "0", f"Participant {participant.id} was not funded" + + print("\n=== Step 8: Exchange DKG addresses ===") + ui_dkg_address = await rendezvous.poll_ui("dkg_address", timeout=900, process=flutter) + print(f"UI DKG address {ui_dkg_address}") + + all_addresses = {1: ui_dkg_address} + all_addresses.update({p.id: p.dkg_address for p in participants}) + for participant in participants: + for other_id, address in all_addresses.items(): + if other_id == participant.id: + continue + await participant.execute( + GraphQLRequest( + DKG_SET_ADDRESS, variable_values={"id": other_id, "address": address} + ) + ) + print(f"Participant {participant.id} knows every peer address") + + rendezvous.write_peers({p.id: p.dkg_address for p in participants}) + + print("\n=== Step 9: Run the DKG ===") + miner = asyncio.create_task(demand_miner(rpc_url)) + for participant in participants: + await participant.execute(GraphQLRequest(DO_DKG)) + print(f"Initiated DKG on participant {participant.id}") + + shared_address = await rendezvous.poll_ui("shared_address", timeout=1800, process=flutter) + print(f"UI shared address: {shared_address}") + + print("\n=== Step 10: Wait for the Flutter test to finish ===") + returncode = await asyncio.wait_for(flutter.wait(), timeout=300) + assert returncode == 0, f"flutter test failed with {returncode}, see {FLUTTER_LOG}" + + print("\n=== Step 11: Wait for the headless peers to finish their rounds ===") + # The UI participant can reach the shared address a round ahead of the + # peers: they still need its round-2 packages to be mined and synced. + # The background miner is still running, so just wait them out. + elapsed = 0 + while elapsed < PEER_COMPLETION_TIMEOUT: + if all(p.get_frost_account_id() for p in participants): + break + await asyncio.sleep(10) + elapsed += 10 + else: + pending = [p.id for p in participants if not p.get_frost_account_id()] + pytest.fail( + f"participants {pending} did not complete the DKG within " + f"{PEER_COMPLETION_TIMEOUT}s of the UI participant finishing" + ) + + print("\n=== Step 12: Verify every participant derived the same shared address ===") + for participant in participants: + participant.frost_account = participant.get_frost_account_id() + assert participant.frost_account, f"No FROST account for participant {participant.id}" + result = await participant.execute( + GraphQLRequest( + ADDRESS_QUERY, variable_values={"account": participant.frost_account} + ) + ) + peer_address = result["addressByAccount"]["ironwood"] + print(f"Participant {participant.id} shared address: {peer_address}") + assert peer_address == shared_address, ( + f"Participant {participant.id} derived a different shared address! " + f"{peer_address} != {shared_address}" + ) + + print("\n=== ✅ Flutter UI DKG Test Passed! ===") + print(f"Shared FROST address: {shared_address}") + + except Exception: + dump_server_log(FLUTTER_LOG, "FLUTTER TEST LOG") + for participant in participants: + dump_server_log(f"/tmp/graphql_{participant.port}.log", f"PARTICIPANT {participant.id}") + raise + + finally: + if miner is not None: + miner.cancel() + await asyncio.gather(miner, return_exceptions=True) + if flutter is not None and flutter.returncode is None: + flutter.terminate() + with contextlib.suppress(asyncio.TimeoutError): + await asyncio.wait_for(flutter.wait(), timeout=30) + for participant in participants: + await participant.stop() + if default_participant: + await default_participant.stop() + rendezvous.cleanup() + if os.path.exists(ui_db_path): + os.remove(ui_db_path) From 381bb1d8a4d367518da5aabd8a569dd94a22c2b2 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 28 Aug 2026 07:18:50 +0800 Subject: [PATCH 128/189] fix(pay): serialize PCZTs with bincode standard() for interop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pack_transaction` / `unpack_transaction` used bincode `legacy()` while zkool_graphql's `prepareSend` and `frostSign` use `standard()`. The two disagree on length prefixes, so a PCZT could not cross between them: an app user and a zkool_graphql user could not co-sign a FROST transaction, even though both implement the protocol correctly. Aligns the app on `standard()`. The `legacy()` uses in frost/sign.rs and frost/protocol.rs are left alone — those are the on-disk signing state and the memo wire format, symmetric on both sides. A PCZT is an ephemeral signing artifact rather than persisted state, so the only exposure is a signing session in flight between two app versions: a blob exported by an older build (QR, file) will not import into this one. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- rust/src/api/pay.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 3bc00448e..03cca3ffc 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use bincode::{config::legacy, Decode, Encode}; +use bincode::{config::standard, Decode, Encode}; use crate::{ api::coin::Coin, @@ -120,14 +120,20 @@ pub struct PcztPackage { } #[cfg_attr(feature = "flutter", frb)] +/// Serialize a PCZT for transport between participants. +/// +/// Uses bincode's `standard()` config so the bytes are interchangeable with +/// zkool_graphql, whose `prepareSend` / `frostSign` use the same config. The +/// two used to disagree (`legacy()` here), which made it impossible for an app +/// user and a zkool_graphql user to co-sign a FROST transaction. pub fn pack_transaction(pczt: &PcztPackage) -> Result<Vec<u8>> { - let pkg = bincode::encode_to_vec(pczt, legacy())?; + let pkg = bincode::encode_to_vec(pczt, standard())?; Ok(pkg) } #[cfg_attr(feature = "flutter", frb)] pub fn unpack_transaction(bytes: &[u8]) -> Result<PcztPackage> { - let (pkg, _) = bincode::decode_from_slice(bytes, legacy())?; + let (pkg, _) = bincode::decode_from_slice(bytes, standard())?; Ok(pkg) } From f7d18ac259fff31817209765cb4d52a699ab727e Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 28 Aug 2026 07:20:07 +0800 Subject: [PATCH 129/189] test(frost): add Flutter UI FROST signing integration test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends the DKG UI test to a full multisig spend. The app runs the DKG wizard for a shared key, then drives the signing pages — /frost1 to choose the coordinator and the funding account, /frost2 for the rounds — while participants #2 and #3 stay headless and #2 coordinates, mirroring test_frost.py. The test asserts the receiver is actually paid 0.05 out of the multisig, so it covers a real spend rather than UI states alone. This only works now that both sides serialize PCZTs the same way: the coordinator's `prepareSend` output is handed to the app through the rendezvous and opened with `unpackTransaction`. Extracts the parts both UI tests share into support.dart — the rendezvous, the pumping helpers, wallet setup, and the DKG flow itself — and rewrites dkg_ui_test.dart on top of it. Behaviour is unchanged; the DKG flow is exercised by both tests now. The signing test navigates away from the DKG page (`go`, not `push`) once the DKG finishes. DKGPage3 only cancels its 30s timer in dispose, so a page left mounted keeps calling doDkg and throws `get_funding_account: no rows` as soon as the selected account moves to the FROST account. Verified end to end on regtest: 1 passed in 323s, receiver balance 0.05000000. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- integration_test/dkg_ui_test.dart | 270 +++----------------- integration_test/frost_ui_test.dart | 195 +++++++++++++++ integration_test/support.dart | 355 ++++++++++++++++++++++++++ tests/tests/dkg.py | 4 + tests/tests/test_frost_ui.py | 371 ++++++++++++++++++++++++++++ 5 files changed, 953 insertions(+), 242 deletions(-) create mode 100644 integration_test/frost_ui_test.dart create mode 100644 integration_test/support.dart create mode 100644 tests/tests/test_frost_ui.py diff --git a/integration_test/dkg_ui_test.dart b/integration_test/dkg_ui_test.dart index 88e81144e..2ee313845 100644 --- a/integration_test/dkg_ui_test.dart +++ b/integration_test/dkg_ui_test.dart @@ -4,141 +4,58 @@ /// /// The Python side owns the chain (funding, mining) and the peer participants. /// Both sides exchange addresses through JSON files in a rendezvous directory -/// that lives inside the macOS app sandbox container — see -/// `tests/tests/dkg.py` for the other half of the protocol. +/// that lives inside the macOS app sandbox container — see `tests/tests/dkg.py` +/// for the other half of the protocol. library; -import 'dart:convert'; -import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:zkool/main.dart'; import 'package:zkool/router.dart'; import 'package:zkool/src/rust/api/account.dart'; -import 'package:zkool/src/rust/api/coin.dart' hide initDatadir; -import 'package:zkool/src/rust/api/db.dart'; -import 'package:zkool/src/rust/api/network.dart'; -import 'package:zkool/src/rust/frb_generated.dart'; import 'package:zkool/store.dart'; -import 'package:zkool/utils.dart'; -/// Directory shared with the Python orchestrator, passed as -/// `--dart-define=ZKOOL_TEST_RENDEZVOUS=<dir>`. Defaults to -/// `<documents>/dkg_ui_rendezvous`, which is where the Python side puts it. -const rendezvousOverride = String.fromEnvironment("ZKOOL_TEST_RENDEZVOUS"); - -/// JSON file rendezvous with the Python orchestrator. -class Rendezvous { - final Directory dir; - - Rendezvous(this.dir); - - File get _config => File("${dir.path}/config.json"); - File get _ui => File("${dir.path}/ui.json"); - File get _peers => File("${dir.path}/peers.json"); - - Map<String, dynamic> readConfig() => - jsonDecode(_config.readAsStringSync()) as Map<String, dynamic>; - - Map<String, dynamic>? readPeers() { - if (!_peers.existsSync()) return null; - try { - return jsonDecode(_peers.readAsStringSync()) as Map<String, dynamic>; - } on FormatException { - return null; // partially written; the writer renames atomically but be safe - } - } - - final Map<String, dynamic> _uiState = {}; - - /// Publishes [key] to the orchestrator. Written to a temp file then renamed - /// so the reader never observes a partial document. - void publish(String key, String value) { - _uiState[key] = value; - final tmp = File("${_ui.path}.tmp"); - tmp.writeAsStringSync(jsonEncode(_uiState)); - tmp.renameSync(_ui.path); - } -} +import 'support.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); testWidgets("DKG participant #1 through the Flutter UI", (tester) async { - final docsDir = await getApplicationDocumentsDirectory(); - final rendezvous = Rendezvous(Directory( - rendezvousOverride.isNotEmpty ? rendezvousOverride : "${docsDir.path}/dkg_ui_rendezvous",),); + final docsDir = await appDocumentsDir(); + final rendezvous = Rendezvous.fromEnvironment(docsDir); expect(rendezvous.dir.existsSync(), isTrue, - reason: "rendezvous dir ${rendezvous.dir.path} missing — start this test from test_dkg_ui.py",); + reason: "rendezvous dir ${rendezvous.dir.path} missing — " + "start this test from test_dkg_ui.py",); final config = rendezvous.readConfig(); final dbPath = config["db_path"] as String; - final lwd = config["lwd"] as String; - final n = config["n"] as int; - final t = config["t"] as int; - final myId = config["my_id"] as int; - final dkgName = config["name"] as String; - // The database filename must contain "regtest": that substring is what // selects Network::Regtest in rust/src/api/coin.rs. expect(dbPath, contains("regtest")); final prefs = SharedPreferencesAsync(); - // Saved so the developer's own app settings survive the test run. - final savedPinLock = await prefs.getBool("pin_lock"); - final savedOffline = await prefs.getBool("offline"); - final savedVault = await prefs.getBool("vault"); + final savedPrefs = await SavedPrefs.forceTestValues(prefs); try { - // ── Setup: Rust bridge, database, funding account ───────────────────── await tester.runAsync(() async { - await RustLib.init(); - await initDatadir(directory: docsDir.path); - - final dbFile = File(dbPath); - if (dbFile.existsSync()) dbFile.deleteSync(); - - await prefs.setBool("pin_lock", false); - await prefs.setBool("offline", false); - await prefs.setBool("vault", false); - - var c = await Coin().openDatabase(dbFilepath: dbPath, password: null); - await putProp(key: "lwd", value: lwd, c: c); - await putProp(key: "is_light_node", value: "true", c: c); - c = c.setLwd(serverType: 0, url: lwd); - coinContext.set(coin: c); - - final account = await newAccount( - na: NewAccount( - name: "DKG-Fund", - restore: false, - key: "", - aindex: 0, - birth: 1, - folder: "", - useInternal: false, - internal: false, - ledger: false, - ), - c: coinContext.coin, + final account = await setUpTestWallet( + dbPath: dbPath, + lwd: config["lwd"] as String, + docsDir: docsDir.path, ); - await coinContext.setAccount(account: account); // uaPools 6 = sapling|orchard, matching the GraphQL `ironwood` address. final addresses = await getAddresses(uaPools: 6, c: coinContext.coin); - final fundingAddress = addresses.oaddr!; - debugPrint("[dkg-ui] funding account $account address $fundingAddress"); - rendezvous.publish("funding_address", fundingAddress); + debugPrint("[dkg-ui] funding account $account address ${addresses.oaddr}"); + rendezvous.publish("funding_address", addresses.oaddr!); }); - // ── Start the app directly on the DKG wizard ────────────────────────── await tester.pumpWidget( - ZkoolApp(router: router(true, false, initialLocation: "/dkg1")),); + ZkoolApp(router: router(true, false, initialLocation: "/dkg1")), + ); await tester.pump(const Duration(seconds: 1)); final view = tester.view; @@ -149,157 +66,26 @@ void main() { "(dpr ${view.devicePixelRatio})", ); - // Splash normally does this; without it the settings provider stays in - // AsyncLoading and `startSynchronize`'s requireValue would throw. - final container = ProviderScope.containerOf(tester.element(find.byType(MaterialApp))); - // Read the settings first: it watches hasDbProvider, which keeps that - // (auto-dispose) notifier alive across the setHasDb call below. - container.read(appSettingsProvider); - container.read(hasDbProvider.notifier).setHasDb(); - await pumpUntil( - tester, - () => container.read(appSettingsProvider).hasValue, - timeout: const Duration(seconds: 30), - what: "app settings to load", - ); - - // ── Page 1: DKG parameters ──────────────────────────────────────────── - await pumpUntil(tester, () => find.text("Number of Participants").evaluate().isNotEmpty, - timeout: const Duration(seconds: 30), what: "DKG page 1",); - await tester.enterText(fieldNamed("name"), dkgName); - await tester.pump(); - await selectDropdown(tester, "Number of Participants", "$n"); - await selectDropdown(tester, "Your Participant ID", "$myId"); - await selectDropdown(tester, "Number of Signers Required (Threshold)", "$t"); - await selectDropdown(tester, "Funding Account for the DKG messages", "DKG-Fund"); - await tapNext(tester); - - // ── Page 2: exchange DKG addresses ──────────────────────────────────── - await pumpUntil(tester, () => find.text("DKG Addresses").evaluate().isNotEmpty, - timeout: const Duration(minutes: 2), what: "DKG page 2",); - await pumpUntil(tester, () => fieldNamed("${myId - 1}").evaluate().isNotEmpty, - timeout: const Duration(minutes: 2), what: "own DKG address field",); - - final myAddress = - tester.widget<FormBuilderTextField>(fieldNamed("${myId - 1}")).initialValue!; - expect(myAddress, isNotEmpty); - debugPrint("[dkg-ui] my DKG address $myAddress"); - rendezvous.publish("dkg_address", myAddress); - - Map<String, dynamic>? peers; - await pumpUntil(tester, () { - peers = rendezvous.readPeers(); - return peers != null && peers!.length == n - 1; - }, timeout: const Duration(minutes: 10), what: "peer DKG addresses",); - - for (final entry in peers!.entries) { - final index = int.parse(entry.key) - 1; - final field = fieldNamed("$index"); - await tester.ensureVisible(field); - await tester.enterText(field, entry.value as String); - await tester.pump(); - } - await tapNext(tester); + final container = + ProviderScope.containerOf(tester.element(find.byType(MaterialApp))); + await primeProviders(tester, container); - // ── Page 3: run the DKG rounds ──────────────────────────────────────── - await pumpUntil(tester, () => find.text("Distributed Key Generation").evaluate().isNotEmpty, - timeout: const Duration(minutes: 2), what: "DKG page 3",); - - const sharedPrefix = "The shared address is: "; - CopyableText? status; - var lastStatus = ""; - await pumpUntil( + final sharedAddress = await driveDkg( tester, - () { - final found = find.byType(CopyableText).evaluate(); - if (found.isEmpty) return false; - final w = found.first.widget as CopyableText; - // Publish every status change: it makes the round progression - // visible to the orchestrator and to anyone reading the log. - if (w.text.isNotEmpty && w.text != lastStatus) { - lastStatus = w.text; - debugPrint("[dkg-ui] status: ${w.text}"); - rendezvous.publish("status", w.text); - } - if (!w.text.startsWith(sharedPrefix)) return false; - status = w; - return true; - }, - timeout: const Duration(minutes: 15), - what: "the shared address", + rendezvous, + name: config["name"] as String, + n: config["n"] as int, + t: config["t"] as int, + myId: config["my_id"] as int, ); - - final sharedAddress = status!.text.substring(sharedPrefix.length).trim(); - expect(sharedAddress, isNotEmpty); - debugPrint("[dkg-ui] shared address $sharedAddress"); rendezvous.publish("shared_address", sharedAddress); // Hold the finished screen briefly so the "Finalize" step and the shared - // address are actually observable (on screen, and in a screen recording) - // instead of vanishing the instant the assertion passes. + // address are observable (on screen, and in a screen recording) instead + // of vanishing the instant the assertion passes. await pumpFor(tester, const Duration(seconds: 6)); } finally { - await restoreBool(prefs, "pin_lock", savedPinLock); - await restoreBool(prefs, "offline", savedOffline); - await restoreBool(prefs, "vault", savedVault); + await savedPrefs.restore(prefs); } }, timeout: const Timeout(Duration(minutes: 40)),); } - -Future<void> restoreBool(SharedPreferencesAsync prefs, String key, bool? value) async { - if (value == null) { - await prefs.remove(key); - } else { - await prefs.setBool(key, value); - } -} - -Finder fieldNamed(String name) => - find.byWidgetPredicate((w) => w is FormBuilderTextField && w.name == name); - -/// Pumps real frames until [done] holds. `pumpAndSettle` is unusable on the DKG -/// route: DKGPage3 installs a 30s periodic timer and the synchronizer keeps -/// scheduling frames, so the tree never settles. -Future<void> pumpUntil( - WidgetTester tester, - bool Function() done, { - required Duration timeout, - required String what, -}) async { - final deadline = DateTime.now().add(timeout); - while (DateTime.now().isBefore(deadline)) { - if (done()) return; - await tester.pump(const Duration(milliseconds: 500)); - } - fail("timed out after $timeout waiting for $what"); -} - -/// Pumps real frames for [duration]. Used instead of `pumpAndSettle`, which -/// cannot be trusted anywhere on this route (see [pumpUntil]). -Future<void> pumpFor(WidgetTester tester, Duration duration) async { - final deadline = DateTime.now().add(duration); - while (DateTime.now().isBefore(deadline)) { - await tester.pump(const Duration(milliseconds: 100)); - } -} - -Future<void> selectDropdown(WidgetTester tester, String label, String value) async { - final dropdown = find.ancestor( - of: find.text(label), - matching: find.byType(FormBuilderDropdown<int>), - ); - await tester.ensureVisible(dropdown.first); - await tester.pump(); - await tester.tap(dropdown.first, warnIfMissed: false); - await pumpFor(tester, const Duration(seconds: 1)); - await tester.tap(find.text(value).last); - await pumpFor(tester, const Duration(seconds: 1)); -} - -Future<void> tapNext(WidgetTester tester) async { - final next = find.widgetWithText(ElevatedButton, "Next"); - await tester.ensureVisible(next); - await tester.pump(); - await tester.tap(next); - await pumpFor(tester, const Duration(seconds: 1)); -} diff --git a/integration_test/frost_ui_test.dart b/integration_test/frost_ui_test.dart new file mode 100644 index 000000000..08a0c8e1e --- /dev/null +++ b/integration_test/frost_ui_test.dart @@ -0,0 +1,195 @@ +/// Integration test: run the Flutter app as a FROST *signing* participant. +/// +/// Signing needs a shared key, so the test runs the DKG wizard first (the app +/// as participant #1, two headless `zkool_graphql` peers), then drives the +/// signing pages: /frost1 to pick the coordinator and the funding account, and +/// /frost2 for the signing rounds. `tests/tests/test_frost_ui.py` owns the +/// chain, funds the shared address, prepares the PCZT on the coordinator and +/// verifies that the receiver is actually paid. +library; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:zkool/main.dart'; +import 'package:zkool/router.dart'; +import 'package:zkool/src/rust/api/account.dart'; +import 'package:zkool/src/rust/api/pay.dart'; +import 'package:zkool/store.dart'; + +import 'support.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets("FROST signing participant through the Flutter UI", (tester) async { + final docsDir = await appDocumentsDir(); + final rendezvous = Rendezvous.fromEnvironment(docsDir); + expect(rendezvous.dir.existsSync(), isTrue, + reason: "rendezvous dir ${rendezvous.dir.path} missing — " + "start this test from test_frost_ui.py",); + + final config = rendezvous.readConfig(); + final dbPath = config["db_path"] as String; + final myId = config["my_id"] as int; + final coordinator = config["coordinator"] as int; + expect(dbPath, contains("regtest")); + expect(coordinator, isNot(myId), + reason: "this test drives a non-coordinator participant",); + + final prefs = SharedPreferencesAsync(); + final savedPrefs = await SavedPrefs.forceTestValues(prefs); + + try { + // ── Phase 1: DKG, to get a shared key to sign with ──────────────────── + await tester.runAsync(() async { + final account = await setUpTestWallet( + dbPath: dbPath, + lwd: config["lwd"] as String, + docsDir: docsDir.path, + ); + final addresses = await getAddresses(uaPools: 6, c: coinContext.coin); + debugPrint("[dkg-ui] funding account $account address ${addresses.oaddr}"); + rendezvous.publish("funding_address", addresses.oaddr!); + }); + + final appRouter = router(true, false, initialLocation: "/dkg1"); + await tester.pumpWidget(ZkoolApp(router: appRouter)); + await tester.pump(const Duration(seconds: 1)); + + final container = + ProviderScope.containerOf(tester.element(find.byType(MaterialApp))); + await primeProviders(tester, container); + + final sharedAddress = await driveDkg( + tester, + rendezvous, + name: config["name"] as String, + n: config["n"] as int, + t: config["t"] as int, + myId: myId, + ); + rendezvous.publish("shared_address", sharedAddress); + + // Leave the DKG page so it is disposed. Its 30s timer keeps calling + // doDkg, which starts throwing `get_funding_account: no rows` once the + // DKG is finished and the selected account moves to the FROST one. + appRouter.go("/accounts"); + await pumpFor(tester, const Duration(seconds: 2)); + + // ── Phase 2: wait for the orchestrator to fund the shared address and + // hand us the PCZT the coordinator prepared ─────────────────────────── + Map<String, dynamic>? fromOrchestrator; + await pumpUntil( + tester, + () { + fromOrchestrator = rendezvous.readOrchestrator(); + return fromOrchestrator?["pczt"] != null; + }, + timeout: const Duration(minutes: 15), + what: "the PCZT from the coordinator", + ); + final pcztHex = fromOrchestrator!["pczt"] as String; + debugPrint("[dkg-ui] received PCZT (${pcztHex.length ~/ 2} bytes)"); + + // The FROST account has to be the selected one: FrostPage1 reads + // `frostParams` off the current account, and the Rust side keys the + // signing state off the coin's account. + // DKGPage3 invalidates the account list when it finishes, but make sure + // we read it after the FROST account was created. + container.invalidate(getAccountsProvider); + late final PcztPackage pczt; + await tester.runAsync(() async { + final accounts = await container.read(getAccountsProvider.future); + final frostAccount = accounts.firstWhere( + (a) => a.name == config["name"] as String, + orElse: () => throw StateError( + "no FROST account named ${config["name"]} after the DKG", + ), + ); + debugPrint("[dkg-ui] FROST account ${frostAccount.id}"); + await coinContext.setAccount(account: frostAccount.id); + await container.read(selectedAccountIdProvider.notifier).set(frostAccount.id); + // Interchangeable with zkool_graphql now that both use bincode + // standard() — see rust/src/api/pay.rs. + pczt = await unpackTransaction(bytes: _hexToBytes(pcztHex)); + }); + container.invalidate(selectedAccountProvider); + await pumpFor(tester, const Duration(seconds: 2)); + + // ── Phase 3: the signing pages ──────────────────────────────────────── + // /frost1 takes the PCZT as a route `extra`, so navigate there on the + // router we built rather than starting the app on that route. + appRouter.go("/frost1", extra: pczt); + await pumpUntil( + tester, + () => find.text("ID of the coordinator").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), + what: "FROST page 1", + ); + + await selectDropdown(tester, "ID of the coordinator", "$coordinator"); + await selectDropdown( + tester, + "Funding Account for the FROST messages", + "DKG-Fund", + ); + await tapNext(tester); + + await pumpUntil( + tester, + () => find.text("Frost Multi Party Signature").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), + what: "FROST page 2", + ); + + // FrostPage2 renders its status in a plain Text, not a CopyableText. + const completed = "Signing completed"; + await awaitStatus( + tester, + rendezvous, + readStatus: () { + final found = find + .byWidgetPredicate( + (w) => w is Text && (w.data ?? "").isNotEmpty && _isSigningStatus(w.data!), + ) + .evaluate(); + if (found.isEmpty) return ""; + return (found.first.widget as Text).data!; + }, + isDone: (s) => s == completed, + timeout: const Duration(minutes: 20), + what: "signing to complete", + ); + rendezvous.publish("signing_status", completed); + + await pumpFor(tester, const Duration(seconds: 6)); + } finally { + await savedPrefs.restore(prefs); + } + }, timeout: const Timeout(Duration(minutes: 60))); +} + +/// The messages FrostPage2 can show; used to pick the status Text out of the +/// page without matching the AppBar title or the stepper labels. +const _signingStatuses = [ + "Waiting for other participants to send their commitments", + "Sending our commitments to the coordinator", + "Broadcasting the signing package to all participants", + "Waiting for the signing package from the coordinator", + "Sending our signature share to the coordinator", + "Signing completed", + "Waiting for the signature share from the other participants", + "Assembling the transaction", + "Sending the transaction to the network", +]; + +bool _isSigningStatus(String s) => + _signingStatuses.contains(s) || s.startsWith("TX ID: "); + +List<int> _hexToBytes(String hex) => [ + for (var i = 0; i < hex.length; i += 2) + int.parse(hex.substring(i, i + 2), radix: 16), + ]; diff --git a/integration_test/support.dart b/integration_test/support.dart new file mode 100644 index 000000000..1f6533508 --- /dev/null +++ b/integration_test/support.dart @@ -0,0 +1,355 @@ +/// Shared scaffolding for the Flutter-side FROST integration tests. +/// +/// Both `dkg_ui_test.dart` and `frost_ui_test.dart` run the real app as one +/// participant while `zkool_graphql` instances play the others, orchestrated by +/// pytest. This file holds the parts they have in common: the JSON-file +/// rendezvous with the orchestrator, pumping helpers that work on a route with +/// live timers, and the DKG flow itself (signing needs a completed DKG first). +library; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:zkool/src/rust/api/account.dart'; +import 'package:zkool/src/rust/api/coin.dart' hide initDatadir; +import 'package:zkool/src/rust/api/db.dart'; +import 'package:zkool/src/rust/api/network.dart'; +import 'package:zkool/src/rust/frb_generated.dart'; +import 'package:zkool/store.dart'; +import 'package:zkool/utils.dart'; + +/// Directory shared with the Python orchestrator, passed as +/// `--dart-define=ZKOOL_TEST_RENDEZVOUS=<dir>`. +const rendezvousOverride = String.fromEnvironment("ZKOOL_TEST_RENDEZVOUS"); + +/// JSON file rendezvous with the Python orchestrator. +/// +/// pytest cannot reach the app over the network, and both sides need values +/// from the other while `flutter test` is running, so they exchange JSON +/// documents in a shared directory. Writes go to a temp file and are renamed so +/// a reader never sees a partial document. +class Rendezvous { + final Directory dir; + + Rendezvous(this.dir); + + factory Rendezvous.fromEnvironment(Directory docsDir) => Rendezvous( + Directory( + rendezvousOverride.isNotEmpty + ? rendezvousOverride + : "${docsDir.path}/dkg_ui_rendezvous", + ), + ); + + File get _config => File("${dir.path}/config.json"); + File get _ui => File("${dir.path}/ui.json"); + File get _peers => File("${dir.path}/peers.json"); + + Map<String, dynamic> readConfig() => + jsonDecode(_config.readAsStringSync()) as Map<String, dynamic>; + + Map<String, dynamic>? readPeers() => _readJson(_peers); + + /// Values the orchestrator publishes for us, e.g. the PCZT to sign. + Map<String, dynamic>? readOrchestrator() => + _readJson(File("${dir.path}/orchestrator.json")); + + Map<String, dynamic>? _readJson(File f) { + if (!f.existsSync()) return null; + try { + return jsonDecode(f.readAsStringSync()) as Map<String, dynamic>; + } on FormatException { + return null; // renamed atomically, but be safe + } + } + + final Map<String, dynamic> _uiState = {}; + + /// Publishes [key] to the orchestrator. + void publish(String key, String value) { + _uiState[key] = value; + final tmp = File("${_ui.path}.tmp"); + tmp.writeAsStringSync(jsonEncode(_uiState)); + tmp.renameSync(_ui.path); + } +} + +/// Preference values the tests force, and their originals, so a run does not +/// leave the developer's own app settings changed. +class SavedPrefs { + final bool? pinLock; + final bool? offline; + final bool? vault; + + SavedPrefs(this.pinLock, this.offline, this.vault); + + static Future<SavedPrefs> forceTestValues(SharedPreferencesAsync prefs) async { + final saved = SavedPrefs( + await prefs.getBool("pin_lock"), + await prefs.getBool("offline"), + await prefs.getBool("vault"), + ); + await prefs.setBool("pin_lock", false); + await prefs.setBool("offline", false); + await prefs.setBool("vault", false); + return saved; + } + + Future<void> restore(SharedPreferencesAsync prefs) async { + await _restore(prefs, "pin_lock", pinLock); + await _restore(prefs, "offline", offline); + await _restore(prefs, "vault", vault); + } + + static Future<void> _restore( + SharedPreferencesAsync prefs, + String key, + bool? value, + ) async { + if (value == null) { + await prefs.remove(key); + } else { + await prefs.setBool(key, value); + } + } +} + +/// Opens the test database and creates the account that pays for the protocol +/// memos. Must run inside `tester.runAsync` — it is all real async I/O. +/// +/// Returns the id of the funding account. +Future<int> setUpTestWallet({ + required String dbPath, + required String lwd, + required String docsDir, +}) async { + await RustLib.init(); + await initDatadir(directory: docsDir); + + final dbFile = File(dbPath); + if (dbFile.existsSync()) dbFile.deleteSync(); + + var c = await Coin().openDatabase(dbFilepath: dbPath, password: null); + await putProp(key: "lwd", value: lwd, c: c); + await putProp(key: "is_light_node", value: "true", c: c); + c = c.setLwd(serverType: 0, url: lwd); + coinContext.set(coin: c); + + final account = await newAccount( + na: NewAccount( + name: "DKG-Fund", + restore: false, + key: "", + aindex: 0, + birth: 1, + folder: "", + useInternal: false, + internal: false, + ledger: false, + ), + c: coinContext.coin, + ); + await coinContext.setAccount(account: account); + return account; +} + +/// Splash normally initialises these; without it `appSettingsProvider` stays in +/// AsyncLoading and `startSynchronize`'s `requireValue` throws. +Future<void> primeProviders(WidgetTester tester, ProviderContainer container) async { + // Read the settings first: it watches hasDbProvider, which keeps that + // (auto-dispose) notifier alive across the setHasDb call below. + container.read(appSettingsProvider); + container.read(hasDbProvider.notifier).setHasDb(); + await pumpUntil( + tester, + () => container.read(appSettingsProvider).hasValue, + timeout: const Duration(seconds: 30), + what: "app settings to load", + ); +} + +Finder fieldNamed(String name) => + find.byWidgetPredicate((w) => w is FormBuilderTextField && w.name == name); + +/// Pumps real frames until [done] holds. `pumpAndSettle` is unusable on the +/// FROST routes: both DKGPage3 and FrostPage2 install a 30s periodic timer and +/// the synchronizer keeps scheduling frames, so the tree never settles. +Future<void> pumpUntil( + WidgetTester tester, + bool Function() done, { + required Duration timeout, + required String what, +}) async { + final deadline = DateTime.now().add(timeout); + while (DateTime.now().isBefore(deadline)) { + if (done()) return; + await tester.pump(const Duration(milliseconds: 500)); + } + fail("timed out after $timeout waiting for $what"); +} + +/// Pumps real frames for [duration]; see [pumpUntil] for why not pumpAndSettle. +Future<void> pumpFor(WidgetTester tester, Duration duration) async { + final deadline = DateTime.now().add(duration); + while (DateTime.now().isBefore(deadline)) { + await tester.pump(const Duration(milliseconds: 100)); + } +} + +Future<void> selectDropdown(WidgetTester tester, String label, String value) async { + final dropdown = find.ancestor( + of: find.text(label), + matching: find.byType(FormBuilderDropdown<int>), + ); + await tester.ensureVisible(dropdown.first); + await tester.pump(); + await tester.tap(dropdown.first, warnIfMissed: false); + await pumpFor(tester, const Duration(seconds: 1)); + await tester.tap(find.text(value).last); + await pumpFor(tester, const Duration(seconds: 1)); +} + +Future<void> tapNext(WidgetTester tester) async { + final next = find.widgetWithText(ElevatedButton, "Next"); + await tester.ensureVisible(next); + await tester.pump(); + await tester.tap(next); + await pumpFor(tester, const Duration(seconds: 1)); +} + +/// Watches a status line, publishing every change so the run is observable from +/// the orchestrator and the log, and returns once [isDone] accepts one. +/// +/// [readStatus] pulls the current message out of whatever widget the page uses +/// (DKGPage3 renders a CopyableText, FrostPage2 a plain Text). +Future<String> awaitStatus( + WidgetTester tester, + Rendezvous rendezvous, { + required String Function() readStatus, + required bool Function(String) isDone, + required Duration timeout, + required String what, +}) async { + var last = ""; + String? finalStatus; + await pumpUntil( + tester, + () { + final text = readStatus(); + if (text.isNotEmpty && text != last) { + last = text; + debugPrint("[dkg-ui] status: $text"); + rendezvous.publish("status", text); + } + if (!isDone(text)) return false; + finalStatus = text; + return true; + }, + timeout: timeout, + what: what, + ); + return finalStatus!; +} + +/// Current message on DKGPage3, which renders it in a [CopyableText]. +String readCopyableStatus() { + final found = find.byType(CopyableText).evaluate(); + if (found.isEmpty) return ""; + return (found.first.widget as CopyableText).text; +} + +const sharedAddressPrefix = "The shared address is: "; + +/// Drives the DKG wizard: parameters, address exchange, then the rounds. +/// Returns the shared address rendered on the final page. +Future<String> driveDkg( + WidgetTester tester, + Rendezvous rendezvous, { + required String name, + required int n, + required int t, + required int myId, +}) async { + await pumpUntil( + tester, + () => find.text("Number of Participants").evaluate().isNotEmpty, + timeout: const Duration(seconds: 30), + what: "DKG page 1", + ); + await tester.enterText(fieldNamed("name"), name); + await tester.pump(); + await selectDropdown(tester, "Number of Participants", "$n"); + await selectDropdown(tester, "Your Participant ID", "$myId"); + await selectDropdown(tester, "Number of Signers Required (Threshold)", "$t"); + await selectDropdown(tester, "Funding Account for the DKG messages", "DKG-Fund"); + await tapNext(tester); + + await pumpUntil( + tester, + () => find.text("DKG Addresses").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), + what: "DKG page 2", + ); + await pumpUntil( + tester, + () => fieldNamed("${myId - 1}").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), + what: "own DKG address field", + ); + + final myAddress = + tester.widget<FormBuilderTextField>(fieldNamed("${myId - 1}")).initialValue!; + expect(myAddress, isNotEmpty); + debugPrint("[dkg-ui] my DKG address $myAddress"); + rendezvous.publish("dkg_address", myAddress); + + Map<String, dynamic>? peers; + await pumpUntil( + tester, + () { + peers = rendezvous.readPeers(); + return peers != null && peers!.length == n - 1; + }, + timeout: const Duration(minutes: 10), + what: "peer DKG addresses", + ); + + for (final entry in peers!.entries) { + final field = fieldNamed("${int.parse(entry.key) - 1}"); + await tester.ensureVisible(field); + await tester.enterText(field, entry.value as String); + await tester.pump(); + } + await tapNext(tester); + + await pumpUntil( + tester, + () => find.text("Distributed Key Generation").evaluate().isNotEmpty, + timeout: const Duration(minutes: 2), + what: "DKG page 3", + ); + + final status = await awaitStatus( + tester, + rendezvous, + readStatus: readCopyableStatus, + isDone: (s) => s.startsWith(sharedAddressPrefix), + timeout: const Duration(minutes: 15), + what: "the shared address", + ); + + final sharedAddress = status.substring(sharedAddressPrefix.length).trim(); + expect(sharedAddress, isNotEmpty); + debugPrint("[dkg-ui] shared address $sharedAddress"); + return sharedAddress; +} + +/// Documents directory the app actually uses, which is where the rendezvous and +/// the test database live (the macOS app is sandboxed and cannot use /tmp). +Future<Directory> appDocumentsDir() => getApplicationDocumentsDirectory(); diff --git a/tests/tests/dkg.py b/tests/tests/dkg.py index 12cf6d405..783d26a4f 100644 --- a/tests/tests/dkg.py +++ b/tests/tests/dkg.py @@ -207,6 +207,10 @@ def write_config(self, **payload): def write_peers(self, peers: dict[int, str]): self._write(self.peers_path, {str(k): v for k, v in peers.items()}) + def write_orchestrator(self, **payload): + """Publish values the Flutter side waits on, e.g. the PCZT to sign.""" + self._write(os.path.join(self.dir, "orchestrator.json"), payload) + def read_ui(self) -> dict: if not os.path.exists(self.ui_path): return {} diff --git a/tests/tests/test_frost_ui.py b/tests/tests/test_frost_ui.py new file mode 100644 index 000000000..3cb873eb7 --- /dev/null +++ b/tests/tests/test_frost_ui.py @@ -0,0 +1,371 @@ +"""FROST signing where one signer is the real Flutter app. + +Extends test_dkg_ui.py: the app (participant #1) runs the DKG wizard to get a +shared key, then drives the signing pages while participants #2 and #3 stay +headless. Participant #2 coordinates, mirroring test_frost.py. + +The shared PCZT crosses the app/zkool_graphql boundary, which only works +because both now serialize it with bincode `standard()` (rust/src/api/pay.rs). +""" + +import asyncio +import contextlib +import os +import shutil + +import pytest +from dkg import DkgParticipant, Rendezvous, app_documents_dir, demand_miner, flutter_device +from gql import GraphQLRequest, gql +from test_dkg_ui import ( + ADDRESS_QUERY, + BALANCE_QUERY, + CREATE_ACCOUNT, + DKG_NAME_PREFIX, + DKG_SET_ADDRESS, + DKG_START, + DO_DKG, + LWD_URL, + PAY, + PEER_COMPLETION_TIMEOUT, + SYNC_MUTATION, + N, + T, + repo_root, +) +from utils import ( + dump_server_log, + get_current_height, + kill_existing_zkool_processes, + mine_blocks, + wait_for_blocks, +) + +DEFAULT_PORT = 8000 +PORT_BASE = 8002 +COORDINATOR_ID = 2 +FLUTTER_LOG = "/tmp/frost_ui_flutter.log" +SHARED_FUNDING = "0.1" +SEND_AMOUNT = "0.05" +EXPECTED_RECEIVED = "0.05000000" + +PREPARE_SEND = gql( + """ + query ($account: Int!, $address: String!, $amount: BigDecimal!) { + prepareSend( + idAccount: $account + payment: {recipients: [{address: $address, amount: $amount}]} + ) + } + """ +) + +FROST_SIGN = gql( + """ + mutation ($account: Int!, $coordinator: Int!, $funding: Int!, $pczt: String!) { + frostSign( + idAccount: $account + idCoordinator: $coordinator + messageAccount: $funding + pczt: $pczt + ) + } + """ +) + + +@pytest.mark.dkg_ui +@pytest.mark.asyncio +async def test_frost_sign_flutter_ui(graphql_url, rpc_url, seed, zkool_binary, gql_client_factory): + """3-of-3 FROST signing with the Flutter app as a signer.""" + if not seed: + pytest.skip("SEED not set") + if not os.path.exists(zkool_binary): + pytest.skip(f"zkool_graphql binary not found at {zkool_binary}") + + docs_dir = app_documents_dir() + if not os.path.isdir(docs_dir): + pytest.skip(f"app documents directory {docs_dir} not found") + if shutil.which(os.getenv("FLUTTER_BIN", "flutter")) is None: + pytest.skip("flutter not on PATH") + + ui_db_path = os.path.join(docs_dir, "regtest_frost_ui.db") + rendezvous = Rendezvous(os.path.join(docs_dir, "dkg_ui_rendezvous")) + + participants: list[DkgParticipant] = [] + default_participant = None + flutter = None + miner = None + + try: + await kill_existing_zkool_processes() + rendezvous.setup() + for stale in (ui_db_path, FLUTTER_LOG): + if os.path.exists(stale): + os.remove(stale) + + print("=== Step 1: Start the funding instance and the headless peers ===") + default_participant = DkgParticipant( + DEFAULT_PORT, "/tmp/regtest_frost_ui_default.db", LWD_URL + ) + default_participant.start(zkool_binary) + await asyncio.sleep(2) + + for i in range(2, N + 1): + participant = DkgParticipant( + PORT_BASE + i - 2, f"/tmp/regtest_frost_ui_{i}.db", LWD_URL, id=i + ) + participant.start(zkool_binary) + participants.append(participant) + print(f"Started participant {i} on port {participant.port}") + await asyncio.sleep(2) + + print("\n=== Step 2: Create the funded wallet ===") + async with gql_client_factory(graphql_url) as client: + result = await client.execute_async( + GraphQLRequest(CREATE_ACCOUNT, variable_values={"name": "Main", "key": seed}) + ) + main_wallet = int(result["createAccount"]) + await client.execute_async( + GraphQLRequest(SYNC_MUTATION, variable_values={"account": main_wallet}) + ) + + print("\n=== Step 3: Initialize DKG on the headless peers ===") + for participant in participants: + result = await participant.execute( + GraphQLRequest(CREATE_ACCOUNT, variable_values={"name": "DKG-Fund", "key": ""}) + ) + participant.funding_account = int(result["createAccount"]) + result = await participant.execute( + GraphQLRequest( + ADDRESS_QUERY, variable_values={"account": participant.funding_account} + ) + ) + participant.funding_address = result["addressByAccount"]["ironwood"] + result = await participant.execute( + GraphQLRequest( + DKG_START, + variable_values={ + "name": f"{DKG_NAME_PREFIX}-{participant.id}", + "t": T, + "n": N, + "funding": participant.funding_account, + "id": participant.id, + }, + ) + ) + participant.dkg_address = result["dkgStart"] + + print("\n=== Step 4: Launch the Flutter integration test ===") + rendezvous.write_config( + db_path=ui_db_path, + lwd=LWD_URL, + n=N, + t=T, + my_id=1, + coordinator=COORDINATOR_ID, + name=f"{DKG_NAME_PREFIX}-1", + ) + flutter_log = open(FLUTTER_LOG, "w") + flutter = await asyncio.create_subprocess_exec( + os.getenv("FLUTTER_BIN", "flutter"), + "test", + "integration_test/frost_ui_test.dart", + "-d", + flutter_device(), + f"--dart-define=ZKOOL_TEST_RENDEZVOUS={rendezvous.dir}", + cwd=repo_root(), + stdout=flutter_log, + stderr=asyncio.subprocess.STDOUT, + ) + print(f"flutter test pid {flutter.pid}, log {FLUTTER_LOG}") + + print("\n=== Step 5: Fund every participant ===") + ui_funding_address = await rendezvous.poll_ui( + "funding_address", timeout=2400, process=flutter + ) + recipients = [{"address": ui_funding_address, "amount": "0.01"}] + recipients += [{"address": p.funding_address, "amount": "0.01"} for p in participants] + async with gql_client_factory(graphql_url) as client: + await client.execute_async( + GraphQLRequest( + PAY, variable_values={"account": main_wallet, "recipients": recipients} + ) + ) + + peer_client = await participants[0].get_client() + height = await get_current_height(peer_client) + await mine_blocks(rpc_url, 5) + await wait_for_blocks(peer_client, height, 5) + for participant in participants: + await participant.execute( + GraphQLRequest( + SYNC_MUTATION, variable_values={"account": participant.funding_account} + ) + ) + + print("\n=== Step 6: Exchange DKG addresses and run the DKG ===") + ui_dkg_address = await rendezvous.poll_ui("dkg_address", timeout=900, process=flutter) + all_addresses = {1: ui_dkg_address} + all_addresses.update({p.id: p.dkg_address for p in participants}) + for participant in participants: + for other_id, address in all_addresses.items(): + if other_id == participant.id: + continue + await participant.execute( + GraphQLRequest( + DKG_SET_ADDRESS, variable_values={"id": other_id, "address": address} + ) + ) + rendezvous.write_peers({p.id: p.dkg_address for p in participants}) + + miner = asyncio.create_task(demand_miner(rpc_url)) + for participant in participants: + await participant.execute(GraphQLRequest(DO_DKG)) + + shared_address = await rendezvous.poll_ui("shared_address", timeout=1800, process=flutter) + print(f"Shared FROST address: {shared_address}") + + elapsed = 0 + while elapsed < PEER_COMPLETION_TIMEOUT: + if all(p.get_frost_account_id() for p in participants): + break + await asyncio.sleep(10) + elapsed += 10 + else: + pytest.fail("the headless peers did not complete the DKG") + + for participant in participants: + participant.frost_account = participant.get_frost_account_id() + result = await participant.execute( + GraphQLRequest( + ADDRESS_QUERY, variable_values={"account": participant.frost_account} + ) + ) + assert result["addressByAccount"]["ironwood"] == shared_address + + print("\n=== Step 7: Fund the shared FROST address ===") + async with gql_client_factory(graphql_url) as client: + await client.execute_async( + GraphQLRequest(SYNC_MUTATION, variable_values={"account": main_wallet}) + ) + await client.execute_async( + GraphQLRequest( + PAY, + variable_values={ + "account": main_wallet, + "recipients": [{"address": shared_address, "amount": SHARED_FUNDING}], + }, + ) + ) + height = await get_current_height(peer_client) + await mine_blocks(rpc_url, 5) + await wait_for_blocks(peer_client, height, 5) + + coordinator = next(p for p in participants if p.id == COORDINATOR_ID) + await coordinator.execute( + GraphQLRequest( + SYNC_MUTATION, variable_values={"account": coordinator.frost_account} + ) + ) + result = await coordinator.execute( + GraphQLRequest( + BALANCE_QUERY, variable_values={"account": coordinator.frost_account} + ) + ) + print(f"Shared account balance: {result['balanceByAccount']['ironwood']}") + + print("\n=== Step 8: Coordinator prepares the payment ===") + result = await coordinator.execute( + GraphQLRequest(CREATE_ACCOUNT, variable_values={"name": "FROST-Receiver", "key": ""}) + ) + receiver_account = int(result["createAccount"]) + result = await coordinator.execute( + GraphQLRequest(ADDRESS_QUERY, variable_values={"account": receiver_account}) + ) + receiver_address = result["addressByAccount"]["ironwood"] + + result = await coordinator.execute( + GraphQLRequest( + PREPARE_SEND, + variable_values={ + "account": coordinator.frost_account, + "address": receiver_address, + "amount": SEND_AMOUNT, + }, + ) + ) + pczt = result["prepareSend"] + print(f"PCZT prepared ({len(pczt) // 2} bytes)") + + # Hand the same PCZT to the app; it decodes with unpackTransaction. + rendezvous.write_orchestrator(pczt=pczt) + + print("\n=== Step 9: Sign on the headless participants ===") + for participant in participants: + funding_account = participant.get_funding_account_id() + result = await participant.execute( + GraphQLRequest( + FROST_SIGN, + variable_values={ + "account": participant.frost_account, + "coordinator": COORDINATOR_ID, + "funding": funding_account, + "pczt": pczt, + }, + ) + ) + assert result["frostSign"], f"participant {participant.id} failed to sign" + print(f"Participant {participant.id} signed") + + print("\n=== Step 10: Wait for the app to report signing complete ===") + await rendezvous.poll_ui("signing_status", timeout=1800, process=flutter) + returncode = await asyncio.wait_for(flutter.wait(), timeout=300) + assert returncode == 0, f"flutter test failed with {returncode}, see {FLUTTER_LOG}" + + print("\n=== Step 11: Verify the receiver was paid ===") + elapsed = 0 + receiver_balance = "0" + while elapsed < 600: + await coordinator.execute( + GraphQLRequest(SYNC_MUTATION, variable_values={"account": receiver_account}) + ) + result = await coordinator.execute( + GraphQLRequest(BALANCE_QUERY, variable_values={"account": receiver_account}) + ) + receiver_balance = result["balanceByAccount"]["ironwood"] + print(f"Receiver balance: {receiver_balance} (want {EXPECTED_RECEIVED})") + if receiver_balance == EXPECTED_RECEIVED: + break + await asyncio.sleep(10) + elapsed += 10 + else: + pytest.fail( + f"transaction did not land; receiver balance {receiver_balance}, " + f"expected {EXPECTED_RECEIVED}" + ) + + print("\n=== ✅ FROST UI signing test passed ===") + print(f"Shared address: {shared_address}") + print(f"Receiver received {receiver_balance} from the multisig") + + except Exception: + dump_server_log(FLUTTER_LOG, "FLUTTER TEST LOG") + for participant in participants: + dump_server_log(f"/tmp/graphql_{participant.port}.log", f"PARTICIPANT {participant.id}") + raise + + finally: + if miner is not None: + miner.cancel() + await asyncio.gather(miner, return_exceptions=True) + if flutter is not None and flutter.returncode is None: + flutter.terminate() + with contextlib.suppress(asyncio.TimeoutError): + await asyncio.wait_for(flutter.wait(), timeout=30) + for participant in participants: + await participant.stop() + if default_participant: + await default_participant.stop() + rendezvous.cleanup() + if os.path.exists(ui_db_path): + os.remove(ui_db_path) From 11a66aa94f295510ce7cf6e63955c148c8f68409 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 28 Aug 2026 08:09:36 +0800 Subject: [PATCH 130/189] docs(skills): cover the FROST signing UI test, rename to frost-ui-tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The skill documented only the DKG UI test, but there are now two: DKG, and signing on top of it. Renames dkg-ui-test -> frost-ui-tests to match, and adds what the signing test needs. New notes, all learned by hitting them: - Leave the DKG page with `go`, not `push`. DKGPage3 cancels its timer only in dispose, so a mounted page keeps calling doDkg and throws `get_funding_account: no rows` once the selected account moves to the FROST account. - A PCZT must be byte-identical for every signer and crosses the app/zkool_graphql boundary, which only works now that both use bincode standard() — the first thing to check if unpackTransaction starts failing. - FrostPage1 reads frostParams off the current account, so it has to be selected before navigating, and the PCZT goes in as the route `extra`. - FrostPage2 renders its status in a plain Text, not the CopyableText DKGPage3 uses. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- .../{dkg-ui-test => frost-ui-tests}/SKILL.md | 77 +++++++++++++++---- 1 file changed, 61 insertions(+), 16 deletions(-) rename .claude/skills/{dkg-ui-test => frost-ui-tests}/SKILL.md (64%) diff --git a/.claude/skills/dkg-ui-test/SKILL.md b/.claude/skills/frost-ui-tests/SKILL.md similarity index 64% rename from .claude/skills/dkg-ui-test/SKILL.md rename to .claude/skills/frost-ui-tests/SKILL.md index 65887335a..8b5fbdbf6 100644 --- a/.claude/skills/dkg-ui-test/SKILL.md +++ b/.claude/skills/frost-ui-tests/SKILL.md @@ -1,18 +1,30 @@ --- -name: dkg-ui-test -description: "Run the Flutter-UI FROST DKG integration test (tests/test_dkg_ui.py) on a local zebra regtest chain, and optionally screen-record the app window. Use when asked to run, debug, or re-record the DKG UI test, or to bring up the local regtest + lightwalletd + zkool_graphql stack that it needs." +name: frost-ui-tests +description: "Run the Flutter-UI FROST integration tests (tests/test_dkg_ui.py for DKG, tests/test_frost_ui.py for signing) on a local zebra regtest chain, and optionally screen-record the app window. Use when asked to run, debug, or re-record either UI test, or to bring up the local regtest + lightwalletd + zkool_graphql stack they need." --- -# Flutter UI DKG integration test +# Flutter UI FROST integration tests -`tests/tests/test_dkg_ui.py` runs a 3-of-3 FROST DKG where **participant #1 is the -real Flutter app**, driven through `/dkg1 → /dkg2 → /dkg3`, while participants #2 -and #3 are headless `zkool_graphql` instances. pytest owns the chain and the -peers and spawns `flutter test` as a subprocess; the two sides exchange addresses -through JSON files in the app's documents directory. +Two tests run the **real Flutter app** as one FROST participant while the others +are headless `zkool_graphql` instances: -Contrast with `tests/tests/test_dkg.py`, which is the same protocol with all three -participants headless — run that first to prove the stack before blaming the UI test. +| test | what it covers | runtime (warm) | +|---|---|---| +| `tests/tests/test_dkg_ui.py` | 3-of-3 DKG through `/dkg1 → /dkg2 → /dkg3` | ~3.5 min | +| `tests/tests/test_frost_ui.py` | DKG, then signing through `/frost1 → /frost2`, asserting the receiver is actually paid | ~5.5 min | + +The Dart halves live in `integration_test/`, sharing `support.dart` (rendezvous, +pumping helpers, wallet setup, and `driveDkg` — signing needs a shared key +before it can start). + +`test_dkg.py` / `test_frost.py` are the all-headless equivalents; run those +first to prove the stack before blaming the UI tests. + +In both, the app is participant #1 and pytest owns everything else: the chain, +the funding wallet, and the peers. It spawns `flutter test` as a subprocess and +the two sides exchange values through JSON files in the app's documents +directory. In the signing test participant #2 coordinates, so the app exercises +the plain-signer path. ## Prerequisites @@ -46,6 +58,7 @@ export PATH="$HOME/projects/tools/bin:$PATH" pkill -9 zkool_graphql; pkill lightwalletd; pkill zebrad rm -rf ~/Library/Caches/zebra ./data ./regtest.db rm -f ~/Library/Containers/cc.methyl.zkool/Data/Documents/regtest_dkg_ui.db +rm -f ~/Library/Containers/cc.methyl.zkool/Data/Documents/regtest_frost_ui.db rm -rf ~/Library/Containers/cc.methyl.zkool/Data/Documents/dkg_ui_rendezvous # zebra.toml needs a miner address (local edit, do not commit) @@ -82,8 +95,9 @@ Seeds and the destination UA are inlined at the top of `example/sh/regtest_setup ```bash cd tests -SEED="invite couch cloud pave stuff cabbage usual rigid dragon warm cable price fame warfare next swallow worth opera suggest flame patch undo position arctic" \ - .venv/bin/python -m pytest tests/test_dkg_ui.py -v -s +export SEED="invite couch cloud pave stuff cabbage usual rigid dragon warm cable price fame warfare next swallow worth opera suggest flame patch undo position arctic" +.venv/bin/python -m pytest tests/test_dkg_ui.py -v -s # DKG only +.venv/bin/python -m pytest tests/test_frost_ui.py -v -s # DKG + signing ``` Expect ~3.5 min warm; the first run adds a macOS debug build of the app plus the @@ -96,7 +110,7 @@ Watch progress without touching the app's database: sed 's/\x1b\[[0-9;]*m//g' /tmp/dkg_ui_flutter.log | grep -a "dkg-ui] status" ``` -Expected sequence: +Expected DKG sequence: ``` Broadcasting participant keys @@ -107,6 +121,20 @@ Broadcasting round 2 packages The shared address is: uregtest1... ``` +`test_frost_ui.py` continues past that into the signing rounds. Participant #2 +coordinates, so the app is a plain signer: + +``` +Sending our commitments to the coordinator +Waiting for the signing package from the coordinator +Sending our signature share to the coordinator +Signing completed +``` + +It ends by polling the receiver's balance until it reads `0.05000000`, i.e. the +multisig actually spent — not just UI states. The `flutter test` log for signing +is `/tmp/frost_ui_flutter.log`. + ## Things that will bite you - **Never query the app's SQLite file while the test runs.** It is in rollback-journal @@ -130,8 +158,25 @@ The shared address is: uregtest1... test waits up to `PEER_COMPLETION_TIMEOUT` (600s) for the peers to finish *after* the app is done — without that wait the test fails with "No FROST account for participant 2". -- **Never use `pumpAndSettle`** on the DKG route; the 30s timer and the synchronizer - keep frames scheduled so it never settles. Use the `pumpUntil` / `pumpFor` helpers. +- **Never use `pumpAndSettle`** on the DKG or signing routes; DKGPage3 and + FrostPage2 both run a 30s timer and the synchronizer keeps frames scheduled, so + the tree never settles. Use the `pumpUntil` / `pumpFor` helpers. +- **Leave the DKG page with `go`, not `push`.** DKGPage3 cancels its timer only in + `dispose`, so a page left mounted keeps calling `doDkg` and throws + `get_funding_account: no rows` as soon as the selected account moves to the + FROST account. This is why the signing test does `appRouter.go("/accounts")` + after the DKG finishes. +- **A PCZT must be byte-identical for every signer**, and it crosses the + app/zkool_graphql boundary in the signing test. That only works because both + now use bincode `standard()` — the app used `legacy()` until + `fix(pay): serialize PCZTs with bincode standard() for interop`. If a signing + test starts failing at `unpackTransaction`, check that first. +- **FrostPage1 reads `frostParams` off the *current* account**, so the FROST + account has to be selected (`coinContext.setAccount` plus + `selectedAccountIdProvider`) before navigating to `/frost1`, and the PCZT is + passed as the route `extra`. +- **FrostPage2 renders its status in a plain `Text`**, not the `CopyableText` + DKGPage3 uses, so the two tests read the status differently. ## Screen-recording the run (macOS) @@ -169,7 +214,7 @@ git checkout misc/zebra.toml # drops the local miner_address edit ## CI -`.github/workflows/wallet.yml` runs on `ubuntu-latest` and does not include this +`.github/workflows/wallet.yml` runs on `ubuntu-latest` and includes neither test. Porting it needs a desktop Flutter build plus a display (`-d linux` under `xvfb-run`, GTK dev packages) on top of the existing regtest stack. `app_documents_dir()` and `flutter_device()` in `tests/tests/dkg.py` are already From f44c220406f190ae6789f337b61653f179bf73a5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 29 Aug 2026 00:37:34 +0800 Subject: [PATCH 131/189] fix(sync): guard fetch_tx_details with the SYNCING lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `startSynchronize` fires `fetchTxDetails` in an unawaited future once the sync stream ends (lib/store.dart), so it overlaps whatever runs next. On the DKG page that is `doDkg`, which takes SYNCING successfully because the sync proper has already released it — and the two then write on separate connections, producing Error fetching tx details: (code: 5) database is locked rlz::memo::store_output -> decrypt_memo -> fetch_tx_details `fetch_tx_details` was the only writer not taking the lock: `synchronize`, `do_dkg_impl` and `do_sign_impl` all guard on it. Uses `try_lock` with an early return rather than awaiting the lock, matching the other writers. Queueing instead would let a slow detail fetch hold SYNCING long enough for `do_dkg`'s own `try_lock` to fail on every 30s tick and stall the DKG, which is worse than the race being fixed. Detail fetching is best effort — the next sync cycle picks it up. Found by the Flutter UI DKG integration test, which hit the error on most runs. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- rust/src/api/sync.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rust/src/api/sync.rs b/rust/src/api/sync.rs index 9a5d3faa1..734701599 100644 --- a/rust/src/api/sync.rs +++ b/rust/src/api/sync.rs @@ -68,8 +68,25 @@ pub async fn get_db_height(c: &Coin) -> Result<SyncHeight> { crate::sync::get_db_height(&mut *connection, c.account).await } +/// Decrypt memos and store transaction details for `account`. +/// +/// Takes SYNCING like the other writers (`crate::sync::synchronize`, +/// `frost::dkg::do_dkg_impl`, `frost::sign::do_sign_impl`) because this writes +/// on its own connection. `startSynchronize` kicks this off in an unawaited +/// future once the sync stream ends, so it overlaps whatever runs next — on the +/// DKG page that is `do_dkg`, and the two writers collided with +/// `database is locked`. +/// +/// Best-effort: if another writer holds the lock this is skipped rather than +/// queued, so it can never block a sync or a FROST round. The next sync cycle +/// picks the details up again. #[cfg_attr(feature = "flutter", frb)] pub async fn fetch_tx_details(account: u32, c: &Coin) -> Result<()> { + let Ok(_guard) = SYNCING.try_lock() else { + tracing::info!("fetch_tx_details: another writer is active, skipping"); + return Ok(()); + }; + let mut connection = c.get_connection().await?; let mut client = c.client().await?; crate::memo::fetch_tx_details(&c.network(), &mut *connection, &mut client, account).await?; From 0d0bbe3875417099e9e3d0755bade5dbf81a37c5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 29 Aug 2026 01:24:51 +0800 Subject: [PATCH 132/189] fix(frost): sync inside doDkg/doSign and hold off autosync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reworks 03a73a86, which made things worse. That commit gave `fetch_tx_details` the SYNCING lock to stop it colliding with `do_dkg`, but holding the lock there starved the next sync — and `synchronize_impl` reports a skipped sync as success, so the rounds went on to build a transaction from stale notes: ironwood double-spend: duplicate nullifier Reverts that guard and fixes the ordering properly instead: - `do_dkg` and `do_sign` now sync the accounts they need (the funding account plus the internal frost-* mailbox and broadcast accounts) before running the rounds, so a round can never see notes a sync has not caught up on. This is what the headless path already did in `graphql::frost::new_block`. - DKGPage3 and FrostPage2 no longer call `startSynchronize`, and set `frostInProgress` on the synchronizer while they are mounted, which makes `_queueAutoSync` a no-op. Background syncing was the other writer, and each of its cycles spawns an unawaited `fetchTxDetails`. The notifier is held in a field rather than read from `ref` in `dispose`, which riverpod rejects. Verified on regtest, both UI integration tests, with zero `database is locked`, zero double-spends and zero Dart exceptions: test_dkg_ui.py passed in 142s test_frost_ui.py passed in 206s (receiver paid 0.05000000) Both are also faster than before, since a tick no longer runs a page sync and a background sync against the same lock. Claude-Session: https://claude.ai/code/session_01UakqwY9NBmYGFNCurrcQCL --- lib/pages/dkg.dart | 15 +++++++----- lib/pages/frost.dart | 12 ++++++---- lib/store.dart | 6 +++++ rust/src/api/frost.rs | 55 ++++++++++++++++++++++++++++++++++++++++++- rust/src/api/sync.rs | 21 +++++------------ 5 files changed, 83 insertions(+), 26 deletions(-) diff --git a/lib/pages/dkg.dart b/lib/pages/dkg.dart index 3f039cf6e..1fae93699 100644 --- a/lib/pages/dkg.dart +++ b/lib/pages/dkg.dart @@ -319,6 +319,7 @@ class DKGPage3 extends ConsumerStatefulWidget { class DKGPage3State extends ConsumerState<DKGPage3> { late final c = coinContext.coin; + late final SynchronizerNotifier _synchronizer; String message = ""; int index = 0; Timer? runTimer; @@ -327,6 +328,11 @@ class DKGPage3State extends ConsumerState<DKGPage3> { @override void initState() { super.initState(); + // doDkg syncs the DKG accounts itself; keep autosync off the same database + // while the rounds run. The notifier is held in a field because `ref` is + // unsafe to use from dispose(). + _synchronizer = ref.read(synchronizerProvider.notifier); + _synchronizer.frostInProgress = true; runTimer = Timer.periodic(const Duration(seconds: 30), (_) async { await runDkg(); }); @@ -336,19 +342,16 @@ class DKGPage3State extends ConsumerState<DKGPage3> { @override void dispose() { runTimer?.cancel(); + _synchronizer.frostInProgress = false; super.dispose(); } Future<void> runDkg() async { try { await ref.read(currentHeightProvider.notifier).fetch(); - final as = await ref.read(getAccountsProvider.future); - final accounts = as.where((e) => e.enabled).toList(); - final synchronizer = ref.read(synchronizerProvider.notifier); - await synchronizer.startSynchronize( - accounts, - ); + // No startSynchronize here: doDkg syncs the accounts it needs itself, so + // the rounds cannot run on notes a separate sync has not caught up on. final status = doDkg(c: c); status.listen( (s) { diff --git a/lib/pages/frost.dart b/lib/pages/frost.dart index b0bbcaedb..8c08156c4 100644 --- a/lib/pages/frost.dart +++ b/lib/pages/frost.dart @@ -188,6 +188,7 @@ class FrostPage2 extends ConsumerStatefulWidget { class FrostPage2State extends ConsumerState<FrostPage2> { late final c = coinContext.coin; + late final SynchronizerNotifier _synchronizer; String message = ""; Timer? timer; int currentIndex = 0; @@ -196,6 +197,11 @@ class FrostPage2State extends ConsumerState<FrostPage2> { @override void initState() { super.initState(); + // doSign syncs the accounts it needs; keep autosync off the same database + // while the rounds run. The notifier is held in a field because `ref` is + // unsafe to use from dispose(). + _synchronizer = ref.read(synchronizerProvider.notifier); + _synchronizer.frostInProgress = true; runFrost(); timer = Timer.periodic(Duration(seconds: 30), (_) async { runFrost(); @@ -205,6 +211,7 @@ class FrostPage2State extends ConsumerState<FrostPage2> { @override void dispose() { timer?.cancel(); + _synchronizer.frostInProgress = false; super.dispose(); } @@ -223,11 +230,8 @@ class FrostPage2State extends ConsumerState<FrostPage2> { void runFrost() async { try { await ref.read(currentHeightProvider.notifier).fetch(); - final as = await ref.read(getAccountsProvider.future); - final accounts = as.where((e) => e.enabled).toList(); - final synchronizer = ref.read(synchronizerProvider.notifier); - await synchronizer.startSynchronize(accounts); + // No startSynchronize here: doSign syncs the accounts it needs itself. final status = doSign(c: c); status.listen( (s) { diff --git a/lib/store.dart b/lib/store.dart index b905bdd6c..583ed1a83 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -757,6 +757,11 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { StreamSubscription<int>? _autoSyncSubscription; bool _handlingAutoSyncHeight = false; bool _forceNextAutoSync = false; + /// While a FROST round is running, autosync must not fire: doDkg/doSign sync + /// the accounts they need themselves, and a background sync racing them + /// spawns an unawaited fetchTxDetails that writes while the rounds are + /// building a transaction — which produced double-spends from stale notes. + bool frostInProgress = false; int? _pendingAutoSyncHeight; StreamSubscription<SyncProgress>? syncProgressSubscription; int retryCount = 0; @@ -933,6 +938,7 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } void _queueAutoSync(int height, {required bool force}) { + if (frostInProgress) return; _pendingAutoSyncHeight = max(_pendingAutoSyncHeight ?? height, height); _forceNextAutoSync |= force; if (_handlingAutoSyncHeight) return; diff --git a/rust/src/api/frost.rs b/rust/src/api/frost.rs index ab6de60ec..249842781 100644 --- a/rust/src/api/frost.rs +++ b/rust/src/api/frost.rs @@ -4,11 +4,12 @@ use anyhow::{Ok, Result}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; use serde::{Deserialize, Serialize}; -use sqlx::SqliteConnection; +use sqlx::{query, sqlite::SqliteRow, Row, SqliteConnection}; use crate::{ api::coin::Coin, frost::dkg::{get_dkg_params, get_mailbox_account}, + sync::{synchronize_impl, DEFAULT_ACTIONS_PER_SYNC}, }; use std::str::FromStr; @@ -77,12 +78,39 @@ pub async fn has_dkg_addresses(c: &Coin) -> Result<bool> { #[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] +/// Advance the DKG by one step, syncing first. +/// +/// The sync is done here rather than by the caller so the rounds can never run +/// on stale notes. The UI used to sync separately before calling this, and that +/// sync spawned an unawaited `fetch_tx_details` which raced the rounds — see +/// `api::sync::fetch_tx_details`. This mirrors the headless path, where +/// `graphql::frost::new_block` syncs and then calls `do_dkg_impl`. pub async fn do_dkg(status: StreamSink<DKGStatus>, c: &Coin) -> Result<()> { let mut connection = c.get_connection().await?; let mut client = c.client().await?; let height = client.latest_height().await?; let account = get_funding_account(&mut connection).await?; + // The funding account pays for the memos; the internal frost-* accounts are + // the mailbox and broadcast addresses the packages arrive on. + let mut accounts = + query("SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1") + .map(|r: SqliteRow| r.get::<u32, _>(0)) + .fetch_all(&mut *connection) + .await?; + accounts.push(account); + let height = synchronize_impl( + (), + accounts, + height, + DEFAULT_ACTIONS_PER_SYNC, + 1, + 100, + false, + c, + ) + .await?; + let r = crate::frost::dkg::do_dkg( &c.network(), &mut connection, @@ -186,10 +214,35 @@ pub async fn is_signing_in_progress(c: &Coin) -> Result<bool> { #[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] +/// Advance the signing rounds by one step, syncing first. +/// +/// Syncs here for the same reason as [`do_dkg`]: the rounds must not run on +/// stale notes, and a caller-side sync spawns an unawaited `fetch_tx_details` +/// that races them. pub async fn do_sign(status: StreamSink<SigningStatus>, c: &Coin) -> Result<()> { let mut connection = c.get_connection().await?; let mut client = c.client().await?; let height = client.latest_height().await?; + + let account = get_funding_account(&mut connection).await?; + let mut accounts = + query("SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1") + .map(|r: SqliteRow| r.get::<u32, _>(0)) + .fetch_all(&mut *connection) + .await?; + accounts.push(account); + let height = synchronize_impl( + (), + accounts, + height, + DEFAULT_ACTIONS_PER_SYNC, + 1, + 100, + false, + c, + ) + .await?; + let r = crate::frost::sign::do_sign( &c.network(), &mut *connection, diff --git a/rust/src/api/sync.rs b/rust/src/api/sync.rs index 734701599..75396d877 100644 --- a/rust/src/api/sync.rs +++ b/rust/src/api/sync.rs @@ -70,23 +70,14 @@ pub async fn get_db_height(c: &Coin) -> Result<SyncHeight> { /// Decrypt memos and store transaction details for `account`. /// -/// Takes SYNCING like the other writers (`crate::sync::synchronize`, -/// `frost::dkg::do_dkg_impl`, `frost::sign::do_sign_impl`) because this writes -/// on its own connection. `startSynchronize` kicks this off in an unawaited -/// future once the sync stream ends, so it overlaps whatever runs next — on the -/// DKG page that is `do_dkg`, and the two writers collided with -/// `database is locked`. -/// -/// Best-effort: if another writer holds the lock this is skipped rather than -/// queued, so it can never block a sync or a FROST round. The next sync cycle -/// picks the details up again. +/// Deliberately does NOT take SYNCING. It did briefly, to stop it colliding +/// with `do_dkg` — but holding the lock here let it starve the next sync, and +/// `synchronize_impl` reports a skipped sync as success, so the DKG went on to +/// build a transaction from stale notes and double-spent. Detail fetching is +/// best effort and its `database is locked` failures are self-healing; a +/// starved sync is not. #[cfg_attr(feature = "flutter", frb)] pub async fn fetch_tx_details(account: u32, c: &Coin) -> Result<()> { - let Ok(_guard) = SYNCING.try_lock() else { - tracing::info!("fetch_tx_details: another writer is active, skipping"); - return Ok(()); - }; - let mut connection = c.get_connection().await?; let mut client = c.client().await?; crate::memo::fetch_tx_details(&c.network(), &mut *connection, &mut client, account).await?; From f80f27a7e248456e9e1e1a04e50e3483192e5839 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 29 Aug 2026 16:29:41 +0800 Subject: [PATCH 133/189] fix(frost): lock spent notes at broadcast to stop duplicate-nullifier double-spends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pay::send only posts a transaction; the local `spends` table is populated by sync, which only sees mined blocks. Rapid FROST funding broadcasts — DKG and signing rounds advancing on the app's 30s poll — could re-select a note that an earlier, still-unmined broadcast already spent, and the node rejected the second transaction as a duplicate nullifier. Lock a transaction's input notes right after a successful broadcast so note selection skips them until the spend is mined and sync clears the flag. Inputs are matched against `notes.nullifier` the same way `mempool::decode_raw_transaction` does (transparent, sapling, orchard and ironwood). Applied at every app-side broadcast: the shared FROST `publish` (covers DKG and both signing rounds), the final aggregated signing tx, normal payments, and migration. Release is idempotent — the sync spend handlers clear `locked` when the spend is mined. Also surface the transient, self-recovering DKG/signing errors as a warning snackbar showing the anyhow context chain (compactAnyhowError) instead of a modal dialog with a backtrace. Verified on regtest: test_dkg_ui.py and test_frost_ui.py pass with zero duplicate-nullifier; the warning was observed to fire and recover. --- lib/pages/dkg.dart | 6 +-- lib/pages/frost.dart | 6 +-- lib/utils.dart | 70 ++++++++++++++++++++++++++ rust/src/api/pay.rs | 4 ++ rust/src/frost/protocol.rs | 3 ++ rust/src/frost/sign.rs | 2 + rust/src/migrate/mod.rs | 2 + rust/src/pay/mod.rs | 77 +++++++++++++++++++++++++++++ rust/src/sync.rs | 13 +++++ test/compact_anyhow_error_test.dart | 57 +++++++++++++++++++++ 10 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 test/compact_anyhow_error_test.dart diff --git a/lib/pages/dkg.dart b/lib/pages/dkg.dart index 1fae93699..5156aa96c 100644 --- a/lib/pages/dkg.dart +++ b/lib/pages/dkg.dart @@ -14,7 +14,6 @@ import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/frost.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; -import 'package:zkool/widgets/error_display.dart'; import 'package:zkool/validators.dart'; Widget buildDKGPage( @@ -410,12 +409,13 @@ class DKGPage3State extends ConsumerState<DKGPage3> { onError: (Object e) async { final exc = e as AnyhowException; if (!context.mounted) return; - await showException(context, exc.message); + // Transient: the 30s timer retries, so warn instead of a modal error. + showWarningSnackbar(exc.message); }, ); } on AnyhowException catch (e) { if (!context.mounted) return; - await showException(context, e.message); + showWarningSnackbar(e.message); } } diff --git a/lib/pages/frost.dart b/lib/pages/frost.dart index 8c08156c4..30d29e781 100644 --- a/lib/pages/frost.dart +++ b/lib/pages/frost.dart @@ -15,7 +15,6 @@ import 'package:zkool/src/rust/api/frost.dart'; import 'package:zkool/src/rust/api/pay.dart'; import 'package:zkool/store.dart'; import 'package:zkool/utils.dart'; -import 'package:zkool/widgets/error_display.dart'; class FrostPage1 extends ConsumerStatefulWidget { final PcztPackage pczt; @@ -292,12 +291,13 @@ class FrostPage2State extends ConsumerState<FrostPage2> { onError: (e) async { final exc = e as AnyhowException; if (!context.mounted) return; - await showException(context, exc.message); + // Transient: the 30s timer retries, so warn instead of a modal error. + showWarningSnackbar(exc.message); }, ); } on AnyhowException catch (e) { if (!context.mounted) return; - await showException(context, e.message); + showWarningSnackbar(e.message); } } } diff --git a/lib/utils.dart b/lib/utils.dart index 1a4ad4bf8..ed5a126e8 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -301,6 +301,76 @@ void showSnackbar(String message) => ScaffoldMessenger.of(navigatorKey.currentCo ), ); +/// Condense an anyhow error's Debug output — what flutter_rust_bridge stores in +/// [AnyhowException.message] — into a single informative line. anyhow formats as: +/// +/// <top context> +/// +/// Caused by: +/// <cause> // or "0: ..", "1: .." when there are several +/// +/// Stack backtrace: // dropped: too noisy for a warning +/// 0: .. +/// +/// Returns the context chain joined by ": ", e.g. +/// "plan_transaction in DKG publish: No feasible note selection found", so the +/// warning shows both where it failed and why — without the backtrace frames. +String compactAnyhowError(String message) { + final lines = message.split('\n'); + final parts = <String>[]; + if (lines.isNotEmpty && lines.first.trim().isNotEmpty) { + parts.add(lines.first.trim()); + } + final numbered = RegExp(r'^\s*\d+:\s+(.*)$'); + var inCauses = false; + for (final line in lines.skip(1)) { + final trimmed = line.trim(); + if (trimmed.toLowerCase().startsWith('stack backtrace')) break; + if (trimmed.toLowerCase().startsWith('caused by')) { + inCauses = true; + continue; + } + if (trimmed.isEmpty) { + inCauses = false; // a blank line ends the "Caused by" block + continue; + } + if (inCauses) { + final m = numbered.firstMatch(line); + parts.add(m != null ? m.group(1)!.trim() : trimmed); + } + } + return parts.join(': '); +} + +/// Show a transient warning in a snackbar. Used for errors we recover from +/// automatically — e.g. a DKG or signing round that will retry on the next +/// tick — so they should not interrupt with a modal error dialog. Shows the +/// error's context chain (via [compactAnyhowError]), not the backtrace. +void showWarningSnackbar(String message) { + final text = compactAnyhowError(message); + logger.i("[warn] $text"); + final context = navigatorKey.currentContext!; + final scheme = Theme.of(context).colorScheme; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + behavior: SnackBarBehavior.floating, + backgroundColor: scheme.tertiaryContainer, + content: Row( + children: [ + Icon(Icons.warning_amber_rounded, color: scheme.onTertiaryContainer), + const Gap(8), + Expanded( + child: Text( + text, + style: TextStyle(color: scheme.onTertiaryContainer), + ), + ), + ], + ), + ), + ); +} + Future<bool> confirmDialog(BuildContext context, {required String title, required String message, Widget? body}) async { final confirmed = await AwesomeDialog( context: context, diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 03cca3ffc..f23f8a620 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -142,6 +142,8 @@ pub async fn broadcast_transaction(height: u32, tx_bytes: &[u8], c: &Coin) -> Re let mut client = c.client().await?; let tx = crate::pay::send(&mut client, height, tx_bytes).await?; + let mut connection = c.get_connection().await?; + crate::pay::lock_spent_notes(&mut connection, c.account, tx_bytes).await?; Ok(tx) } @@ -155,6 +157,8 @@ pub async fn send(height: u32, data: &[u8], c: &Coin) -> Result<String> { let mut client = c.client().await?; let tx = crate::pay::send(&mut client, height, data).await?; + let mut connection = c.get_connection().await?; + crate::pay::lock_spent_notes(&mut connection, c.account, data).await?; Ok(tx) } diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index 33153f658..5ab86629b 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -558,6 +558,9 @@ pub async fn publish( if hex::decode(&result).is_err() { anyhow::bail!(result); } + // Lock the funding notes this broadcast spent so the next round does not + // re-select them before the spend is mined and synced (duplicate nullifier). + crate::pay::lock_spent_notes(connection, account, &txb).await?; Ok(result) } diff --git a/rust/src/frost/sign.rs b/rust/src/frost/sign.rs index 2a398a68e..1caacac08 100644 --- a/rust/src/frost/sign.rs +++ b/rust/src/frost/sign.rs @@ -740,6 +740,8 @@ pub async fn do_sign_impl( status.send(SigningStatus::SendingTransaction).await; let txid = send(client, height, &tx_bytes).await?; info!("Transaction sent: {}", txid); + // Lock the shared-account notes this spend consumed until it is mined. + crate::pay::lock_spent_notes(connection, account, &tx_bytes).await?; status.send(SigningStatus::TransactionSent(txid)).await; } diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 74200285e..968891036 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -340,6 +340,7 @@ pub async fn step( let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; let tx_bytes = extract_transaction(&pczt).await?; let _txid = send(client, height, &tx_bytes).await?; + crate::pay::lock_spent_notes(&mut *connection, account, &tx_bytes).await?; return Ok(MigrationEvent::SplitComplete { fee }); } @@ -432,6 +433,7 @@ pub async fn step( let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; let tx_bytes = extract_transaction(&pczt).await?; let _txid = send(client, height, &tx_bytes).await?; + crate::pay::lock_spent_notes(&mut *connection, account, &tx_bytes).await?; return Ok(MigrationEvent::MigrateComplete { fee }); } diff --git a/rust/src/pay/mod.rs b/rust/src/pay/mod.rs index 7f7113be3..b6e5d4d0f 100644 --- a/rust/src/pay/mod.rs +++ b/rust/src/pay/mod.rs @@ -8,9 +8,11 @@ use orchard::note::AssetBase; use pczt::{roles::verifier::Verifier, Pczt}; use pool::PoolMask; use serde::{Deserialize, Serialize}; +use sqlx::SqliteConnection; use tracing::{info, span, Level}; use zcash_keys::encoding::AddressCodec as _; use zcash_note_encryption::Domain; +use zcash_primitives::transaction::{OrchardBundle, Transaction}; use zcash_protocol::consensus::BranchId; use zcash_transparent::address::TransparentAddress; @@ -321,3 +323,78 @@ pub async fn send(client: &mut Client, height: u32, data: &[u8]) -> Result<Strin }); Ok(txid) } + +/// After a successful broadcast, mark the notes the transaction spends as +/// `locked` so note selection will not pick them again until the spend is mined +/// and synced (which clears the flag — see the spend handlers in `sync.rs`). +/// +/// This closes the window where a second transaction is built from a note that +/// an earlier, still-unmined broadcast already spent — the "duplicate nullifier" +/// the node would otherwise reject (seen in rapid-fire DKG funding rounds). +/// +/// Best-effort: a transaction we cannot parse simply locks nothing, and it never +/// fails a broadcast that already succeeded. Nullifiers are matched against +/// `notes.nullifier` exactly as [`crate::mempool::decode_raw_transaction`] does, +/// which already covers every pool including ironwood. +pub async fn lock_spent_notes( + conn: &mut SqliteConnection, + account: u32, + tx_bytes: &[u8], +) -> Result<()> { + let Some(tx) = [ + BranchId::Nu6_3, + BranchId::Nu6_2, + BranchId::Nu6, + BranchId::Nu5, + ] + .into_iter() + .find_map(|branch| Transaction::read(&mut &tx_bytes[..], branch).ok()) else { + info!("lock_spent_notes: could not parse transaction; locking nothing"); + return Ok(()); + }; + let tx_data = tx.into_data(); + + // Every input's key (transparent outpoint or shielded nullifier) is stored + // in the `nullifier` column, so collect them all and lock the matches. + let mut nullifiers: Vec<Vec<u8>> = vec![]; + if let Some(tbundle) = tx_data.transparent_bundle() { + for v in tbundle.vin.iter() { + let mut nf = vec![]; + v.prevout().write(&mut nf)?; + nullifiers.push(nf); + } + } + if let Some(sbundle) = tx_data.sapling_bundle() { + for v in sbundle.shielded_spends().iter() { + nullifiers.push(v.nullifier().to_vec()); + } + } + if let Some(obundle) = tx_data.orchard_bundle() { + match obundle { + OrchardBundle::OrchardVanilla(b) => { + for v in b.actions().iter() { + nullifiers.push(v.nullifier().to_bytes().to_vec()); + } + } + OrchardBundle::OrchardZSA(b) => { + for v in b.actions().iter() { + nullifiers.push(v.nullifier().to_bytes().to_vec()); + } + } + } + } + if let Some(iwbundle) = tx_data.ironwood_bundle() { + for v in iwbundle.actions().iter() { + nullifiers.push(v.nullifier().to_bytes().to_vec()); + } + } + + for nf in nullifiers.iter() { + sqlx::query("UPDATE notes SET locked = TRUE WHERE account = ? AND nullifier = ?") + .bind(account) + .bind(nf) + .execute(&mut *conn) + .await?; + } + Ok(()) +} diff --git a/rust/src/sync.rs b/rust/src/sync.rs index 46087d638..c8ae2b0f5 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -454,6 +454,12 @@ pub(crate) async fn transparent_sync( .bind(account) .execute(&mut *db_tx) .await?; + // Release any broadcast-time lock now that the + // spend is mined (noop if it was not locked). + sqlx::query("UPDATE notes SET locked = FALSE WHERE id_note = ?") + .bind(id) + .execute(&mut *db_tx) + .await?; } } @@ -983,6 +989,13 @@ async fn handle_message( .bind(&utxo.txid) .execute(&mut **db_tx) .await?; + // Release any broadcast-time lock now that the spend is mined + // (noop if it was not locked). + sqlx::query("UPDATE notes SET locked = FALSE WHERE account = ?1 AND cmx = ?2") + .bind(utxo.account) + .bind(&utxo.cmx) + .execute(&mut **db_tx) + .await?; debug!("Processing Spend: {:?}", &utxo); assert_eq!(r.rows_affected(), 1); } diff --git a/test/compact_anyhow_error_test.dart b/test/compact_anyhow_error_test.dart new file mode 100644 index 000000000..96583bcb7 --- /dev/null +++ b/test/compact_anyhow_error_test.dart @@ -0,0 +1,57 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zkool/utils.dart'; + +void main() { + group('compactAnyhowError', () { + test('joins the context chain and drops the stack backtrace', () { + const error = ''' +transport error + +Caused by: + 0: connection error + 1: peer closed connection + +Stack backtrace: + 0: <unknown> + 12: resolved_function +'''; + expect( + compactAnyhowError(error), + 'transport error: connection error: peer closed connection', + ); + }); + + test('handles a single unnumbered cause (the DKG locked-note case)', () { + const error = ''' +plan_transaction in DKG publish + +Caused by: + No feasible note selection found + +Stack backtrace: + 0: <unknown> +'''; + expect( + compactAnyhowError(error), + 'plan_transaction in DKG publish: No feasible note selection found', + ); + }); + + test('returns a single-line message unchanged', () { + expect(compactAnyhowError('No feasible note selection found'), + 'No feasible note selection found'); + }); + + test('ignores stray backtrace frames when there is no Caused by block', () { + const error = ''' +no rows returned by a query that expected to return at least one row + 1: anyhow::error::from + 2: rlz::frost::do_dkg +'''; + expect( + compactAnyhowError(error), + 'no rows returned by a query that expected to return at least one row', + ); + }); + }); +} From ef4db48157d545420936a9ee1903a3ff5972d3f5 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sun, 30 Aug 2026 08:14:27 +0800 Subject: [PATCH 134/189] fix(migrate): stop migration stalling on Orchard totals of 0.005-0.0062 ZEC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The split planner subtracted a flat MIN_SD fee reserve before denominating. decompose_to_sd always leaves a remainder below the smallest denomination (120_000), so the `remainder < MIN_SD / 2` guard was always true and the reserve always applied. For a non-SD Orchard total in [500_000, 620_000) zats that removed every planned output: no split was broadcast, no note was spent, and the runner span forever while reporting the splitting phase. This was the terminal state of a normal run rather than a rare balance. The reserve left change of MIN_SD + r - fee on every split, so the last split of a migration deposits the wallet into that window or just below it. The reserve was redundant too: the trim loop below it already computes the exact fee from a FeeManager mirroring what plan_transaction builds, and drops the lowest denomination until it fits. Restructure so the class of bug is not expressible: state.rs observe() one note query, replacing two divergent ones plan.rs next_task() pure; sole authority on what happens next task.rs MigrationTask plain data, with preconditions exec.rs effects only step.rs one step, shared by the FRB and GraphQL front ends has_split_transaction predicted what step() would do and could disagree with it. That disagreement drove loop termination, the anchor-boundary wait, and the progress bar, and step() never even received allow_migrate — the only thing preventing an off-boundary O->I was a phase string plus an ensure! that is vacuous at anchor_bucket_size 1. It is gone: the displayed phase, the loop's termination and the executed action now all derive from next_task, and boundary discipline is a task precondition. Migration no longer synchronizes. The wallet's autosync advances the checkpoint and migration observes where it got to; a sync started here was unreliable anyway, since synchronize_impl takes SYNCING with try_lock and returns silently when autosync holds it. The migrate page refuses to start when the wallet is offline or autosync is off, because the checkpoint would then never reach an anchor boundary and the migration would wait forever. Also fix stepMigration ignoring its idAccount argument. It ran against context.coin.account, which has no sync rows, so get_db_height failed with "no rows returned by a query that expected to return at least one row". Every other mutation threads id_account; this one now calls the internal step_once directly, as synchronize_account calls synchronize_impl. Claude-Session: https://claude.ai/code/session_01TppXvnfqGTBNJWEtv6e2ix --- lib/pages/migrate.dart | 44 ++- rust/src/api/migrate.rs | 449 ++++++++++------------------ rust/src/graphql/mutation.rs | 15 +- rust/src/migrate/exec.rs | 160 ++++++++++ rust/src/migrate/mod.rs | 379 +----------------------- rust/src/migrate/plan.rs | 557 +++++++++++++++++++++++++++++++++++ rust/src/migrate/state.rs | 146 +++++++++ rust/src/migrate/step.rs | 80 +++++ rust/src/migrate/task.rs | 107 +++++++ 9 files changed, 1272 insertions(+), 665 deletions(-) create mode 100644 rust/src/migrate/exec.rs create mode 100644 rust/src/migrate/plan.rs create mode 100644 rust/src/migrate/state.rs create mode 100644 rust/src/migrate/step.rs create mode 100644 rust/src/migrate/task.rs diff --git a/lib/pages/migrate.dart b/lib/pages/migrate.dart index c9ed63069..1761a63ef 100644 --- a/lib/pages/migrate.dart +++ b/lib/pages/migrate.dart @@ -1,11 +1,12 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; -import 'package:zkool/main.dart' show logger; +import 'package:zkool/main.dart' show appKey, logger; import 'package:zkool/src/rust/api/account.dart'; import 'package:zkool/src/rust/api/migrate.dart'; import 'package:zkool/store.dart'; @@ -118,9 +119,42 @@ class _MigratePageState extends State<MigratePage> with WidgetsBindingObserver { WidgetsBinding.instance.addObserver(this); } - void _startMigration() { + /// Migration does not synchronize. It observes the checkpoint the wallet's + /// autosync advances, and can only build the Orchard→Ironwood transaction + /// once that checkpoint lands on a shared anchor block. With autosync off, + /// or the wallet offline, the checkpoint never moves and the migration would + /// wait indefinitely — so say why instead of starting. + Future<String?> _syncPrerequisiteError() async { + final scope = ProviderScope.containerOf(appKey.currentContext!); + final settings = await scope.read(appSettingsProvider.future); + + if (settings.offline) { + return "Migration needs the wallet online. It waits for automatic " + "synchronization to reach a shared anchor block, and does not " + "synchronize by itself.\n\nTurn off Offline mode in Settings and " + "try again."; + } + if ((int.tryParse(settings.syncInterval) ?? 0) <= 0) { + return "Migration needs automatic synchronization enabled. It waits for " + "the wallet to sync to a shared anchor block, and does not " + "synchronize by itself.\n\nSet a sync interval in Settings and try " + "again."; + } + return null; + } + + Future<void> _startMigration() async { + final prerequisite = await _syncPrerequisiteError(); + if (prerequisite != null) { + if (!mounted) return; + setState(() => _started = false); + await showException(context, prerequisite); + return; + } + if (!mounted) return; + try { - _sub?.cancel(); + await _sub?.cancel(); final meanDelayMs = BigInt.from(_speedMeanMs[_speedIndex.round()]); final stream = _runCancellableMigration(meanDelayMs: meanDelayMs); _sub = stream.listen( @@ -168,7 +202,7 @@ class _MigratePageState extends State<MigratePage> with WidgetsBindingObserver { }, ); } on AnyhowException catch (e) { - if (!context.mounted) return; + if (!mounted) return; unawaited(showException(context, e.message)); } } @@ -380,7 +414,7 @@ class _MigratePageState extends State<MigratePage> with WidgetsBindingObserver { child: FilledButton.icon( onPressed: () { setState(() => _started = true); - _startMigration(); + unawaited(_startMigration()); }, icon: const Icon(Icons.play_arrow), label: const Text("Start Migration"), diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index 60a9bdafa..c8c1b59eb 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -5,7 +5,16 @@ use tokio_util::sync::CancellationToken; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; -use crate::{api::coin::Coin, frb_generated::StreamSink}; +use crate::{ + api::coin::Coin, + frb_generated::StreamSink, + migrate::{ + plan::next_task, + state::MigrationState, + step::StepOutcome, + task::{MigrationTask, Pacing, TaskKind}, + }, +}; /// Current migration status — streamed to Flutter by run_migration(). #[cfg_attr(feature = "flutter", frb)] @@ -81,23 +90,23 @@ impl NoteMigration { /// Single-shot step (kept for FRB generated-code compatibility). #[cfg_attr(feature = "flutter", frb)] pub async fn step_migration(c: &Coin) -> Result<MigrationEvent> { - let (event, _status) = do_step(c, 0, 0, true, true, crate::migrate::ANCHOR_BUCKET_SIZE).await?; - Ok(match event { - crate::migrate::MigrationEvent::SplitComplete { fee } => { - MigrationEvent::SplitComplete { fee } - } - crate::migrate::MigrationEvent::MigrateComplete { fee } => { - MigrationEvent::MigrateComplete { fee } - } - crate::migrate::MigrationEvent::Complete => MigrationEvent::Complete, - crate::migrate::MigrationEvent::NothingToDo => MigrationEvent::NothingToDo, + Ok(match crate::migrate::step::step_once(c, c.account).await? { + StepOutcome::Split { fee } => MigrationEvent::SplitComplete { fee }, + StepOutcome::Migrated { fee } => MigrationEvent::MigrateComplete { fee }, + StepOutcome::Complete => MigrationEvent::Complete, + StepOutcome::NothingToDo => MigrationEvent::NothingToDo, }) } /// Run migration to completion, streaming MigrationStatus to Flutter. /// +/// The loop is deliberately thin: observe the wallet, ask `next_task` what to +/// do, re-check that the answer still holds, execute it. Every decision lives +/// in `crate::migrate::plan`, so what the user is shown and what actually +/// happens are derived from one function and cannot drift apart. +/// /// `mean_delay_ms` controls the mean wait time (in milliseconds) of the -/// exponential random delay before migration steps. O→I steps additionally +/// exponential random delay that paces every cycle. O→I steps additionally /// wait for the next anchor bucket boundary before syncing, preparing, and /// broadcasting. #[cfg(feature = "flutter")] @@ -108,7 +117,6 @@ async fn run_migration( cancellation_token: CancellationToken, block_height_tx: watch::Sender<Option<u32>>, ) -> Result<()> { - use rand_core::{OsRng, RngCore}; use zcash_protocol::consensus::{BlockHeight, NetworkUpgrade, Parameters}; // Migration only makes sense when Ironwood (NU6.3) is active. @@ -134,37 +142,44 @@ async fn run_migration( let mut acc_split = 0u64; let mut acc_migrate = 0u64; - let mut last_action_height: Option<u32> = None; + let mut pacing = Pacing::default(); let anchor_bucket_size = crate::migrate::migration_anchor_bucket_size(mean_delay_ms); tracing::info!( "Migration anchor interval: {} blocks for mean delay {}ms", anchor_bucket_size, mean_delay_ms, ); - let mut status = current_migration_status(c, acc_split, acc_migrate).await?; - sink.add(status.clone()).ok(); loop { - if status.phase == "complete" { + // Draw this cycle's delay before planning. The value is an input to + // the decision, never something the decision computes: a durable + // engine replays control flow, and a re-rolled random number would + // replay differently. + pacing.sampled_delay_ms = sample_delay(mean_delay_ms); + + let state = observe_state(c, anchor_bucket_size).await?; + let task = next_task(&state, &pacing); + let status = status_from(&state, &task, acc_split, acc_migrate); + sink.add(status.clone()).ok(); + + if matches!(task, MigrationTask::Done) { break; } - // Delay before doing any migration-specific network activity. This - // also applies to the first transaction. - let mean = mean_delay_ms as f64; - let u = (OsRng.next_u32() as f64 + 1.0) / (u32::MAX as f64 + 2.0); - let delay_ms = ((-mean * u.ln()) as u64).min(mean_delay_ms * 4); - let delay_secs = delay_ms / 1000; - - tracing::info!( - "Migration delay: {}ms (mean={}ms, u={:.6})", - delay_ms, - mean_delay_ms, - u - ); - - status.next_action = format!("Waiting {}s...", delay_secs); - sink.add(status.clone()).ok(); + // Re-validate before spending anything. The snapshot the task was + // planned from is a round-trip old, and a concurrent sync or an + // earlier broadcast may have moved the notes underneath it — so an + // effect is checked against state read immediately before it runs. + // A stale task is re-planned, never executed. + if matches!(task.kind(), TaskKind::Effect) { + let fresh = observe_state(c, anchor_bucket_size).await?; + if !task.is_satisfied_by(&fresh) { + tracing::info!("Migration task {:?} no longer applies; replanning", task); + // Pace the retry, so a task that stays stale cannot spin. + pacing.restart(); + continue; + } + } let cancelled = tokio::select! { biased; @@ -172,87 +187,82 @@ async fn run_migration( tracing::info!("Note migration cancelled"); true } - _ = tokio::time::sleep(std::time::Duration::from_millis(delay_ms)) => false, + result = execute(c, &task, &block_height_tx) => { + match result? { + Executed::Waited => pacing.delay_served = true, + Executed::Split { fee } => { + acc_split += fee; + pacing.after_effect(client.latest_height().await?); + } + Executed::Migrated { fee } => { + acc_migrate += fee; + pacing.after_effect(client.latest_height().await?); + } + } + false + } }; if cancelled { break; } + } - if let Some(height) = last_action_height { - if client.latest_height().await? <= height { - continue; - } - } + Ok(()) +} - // O→I transactions are prepared only when the wallet checkpoint and - // the current anchor are the same shared bucket boundary. Until then, - // only query the tip height; do not fetch or synchronize tree state. - let align_to_boundary = status.phase == "migrating"; - if align_to_boundary { - block_height_tx.send_replace(None); - let reached_boundary = tokio::select! { - biased; - _ = cancellation_token.cancelled() => { - tracing::info!("Note migration cancelled"); - false - } - result = wait_for_anchor_boundary( - &sink, - c, - block_height_tx.subscribe(), - &status, - anchor_bucket_size, - ) => { - result?; - true - } - }; - if !reached_boundary { - break; - } +/// What running a task changed, so the driver can advance its pacing. +#[cfg(feature = "flutter")] +enum Executed { + Waited, + Split { fee: u64 }, + Migrated { fee: u64 }, +} - status.next_action = "Preparing migration transaction...".into(); - sink.add(status.clone()).ok(); +/// Carry out one task. Everything that touches the wallet or the chain lives +/// in `crate::migrate::exec`; what remains here is waiting — on the clock, or +/// on the block heights Dart supplies — which decides nothing. +#[cfg(feature = "flutter")] +async fn execute( + c: &Coin, + task: &MigrationTask, + block_height_tx: &watch::Sender<Option<u32>>, +) -> Result<Executed> { + Ok(match task { + MigrationTask::WaitDelay { ms } => { + tracing::info!("Migration delay: {}ms", ms); + tokio::time::sleep(std::time::Duration::from_millis(*ms)).await; + Executed::Waited } - - let (event, next_status) = tokio::select! { - biased; - _ = cancellation_token.cancelled() => { - tracing::info!("Note migration cancelled"); - break; - } - result = do_step( - c, - acc_split, - acc_migrate, - align_to_boundary, - !align_to_boundary, - anchor_bucket_size, - ) => result?, - }; - - match event { - crate::migrate::MigrationEvent::SplitComplete { fee } => { - acc_split += fee; - last_action_height = Some(client.latest_height().await?); - } - crate::migrate::MigrationEvent::MigrateComplete { fee } => { - acc_migrate += fee; - last_action_height = Some(client.latest_height().await?); - } - _ => {} + MigrationTask::WaitBoundary { .. } => { + block_height_tx.send_replace(None); + wait_for_next_height(&mut block_height_tx.subscribe()).await?; + // Waiting changes no wallet state. The next cycle re-plans and + // sees where autosync has taken the checkpoint by then. + Executed::Waited } + MigrationTask::Split { inputs, outputs } => Executed::Split { + fee: crate::migrate::exec::split(c, inputs, outputs).await?, + }, + MigrationTask::Migrate { + note, + amount, + anchor, + } => Executed::Migrated { + fee: crate::migrate::exec::migrate(c, *note, *amount, *anchor).await?, + }, + MigrationTask::Done => Executed::Waited, + }) +} - status = MigrationStatus { - split_fees: acc_split, - migrate_fees: acc_migrate, - total_fees: acc_split + acc_migrate, - ..next_status - }; - sink.add(status.clone()).ok(); - } +/// Exponentially distributed delay, capped at four times the mean. Drawn once +/// per cycle; the caller logs it if and when it is actually served. +#[cfg(feature = "flutter")] +fn sample_delay(mean_delay_ms: u64) -> u64 { + use rand_core::{OsRng, RngCore}; - Ok(()) + let mean = mean_delay_ms as f64; + let u = (OsRng.next_u32() as f64 + 1.0) / (u32::MAX as f64 + 2.0); + ((-mean * u.ln()) as u64).min(mean_delay_ms * 4) } /// Stub kept for FRB generated-code compatibility. @@ -272,220 +282,85 @@ pub async fn get_migration_status(_c: &Coin) -> Result<MigrationStatus> { }) } -/// Shared step logic. Returns the internal event + a MigrationStatus -/// built from the current wallet state and accumulated fees. -async fn do_step( - c: &Coin, - acc_split: u64, - acc_migrate: u64, - allow_migrate: bool, - sync_before: bool, - anchor_bucket_size: u32, -) -> Result<(crate::migrate::MigrationEvent, MigrationStatus)> { +async fn observe_state(c: &Coin, anchor_bucket_size: u32) -> Result<MigrationState> { let network = c.network(); let mut connection = c.get_connection().await?; let mut client = c.client().await?; - - if sync_before { - let current_height = client.latest_height().await?; - let _ = synchronize_to(c, current_height).await; - } - - let before = current_migration_status(c, acc_split, acc_migrate).await?; - let event = if before.phase == "complete" { - crate::migrate::MigrationEvent::Complete - } else if before.phase == "migrating" && !allow_migrate { - // A normal sync may finish the splitting phase at a non-boundary - // height. Return to the runner so it can delay and align the O→I - // transaction instead of broadcasting it immediately. - crate::migrate::MigrationEvent::NothingToDo - } else { - crate::migrate::step( - &network, - &mut connection, - &mut client, - c.account, - anchor_bucket_size, - ) - .await - .map_err(|e| anyhow::anyhow!("step: {e}"))? - }; - - let status = current_migration_status(c, acc_split, acc_migrate).await?; - Ok((event, status)) + crate::migrate::state::observe( + &network, + &mut connection, + &mut client, + c.account, + anchor_bucket_size, + ) + .await } -async fn current_migration_status( - c: &Coin, +/// Build the UI status from the same snapshot and task the runner is acting +/// on, so the phase shown can never claim work that will not be attempted. +fn status_from( + state: &MigrationState, + task: &MigrationTask, acc_split: u64, acc_migrate: u64, -) -> Result<MigrationStatus> { - let mut connection = c.get_connection().await?; - let all_notes = - crate::pay::plan::fetch_unspent_notes_grouped_by_pool(&mut connection, c.account).await?; - let orchard_zec: Vec<&crate::pay::InputNote> = all_notes - .iter() - .filter(|n| n.pool == 2 && n.asset_base == vec![0u8; 32]) - .collect(); - let sd_count = orchard_zec - .iter() - .filter(|n| crate::migrate::is_sd(n.amount)) - .count() as u32; - let non_sd_vals: Vec<u64> = orchard_zec - .iter() - .filter(|n| !crate::migrate::is_sd(n.amount)) - .map(|n| n.amount) - .collect(); - let has_split = crate::migrate::has_split_transaction(non_sd_vals.clone()); - let effective_non_sd = if has_split { - non_sd_vals.len() as u32 +) -> MigrationStatus { + let phase = crate::migrate::plan::phase(state); + let sd_count = state.orchard_sd.len() as u32; + let ironwood_sd = state.ironwood_sd_count; + // Non-SD notes only count as outstanding work while a split is actually + // available; below the threshold they are dust the migration leaves alone. + let non_sd_count = if phase == "splitting" { + state.orchard_non_sd.len() as u32 } else { 0 }; - - // Count Ironwood SD notes for phase 2 progress (amount is value - SD_FEE_PAD). - let ironwood_sd = all_notes - .iter() - .filter(|n| { - n.pool == 3 && n.asset_base == vec![0u8; 32] && crate::migrate::is_iw_sd(n.amount) - }) - .count() as u32; let total_sd = sd_count + ironwood_sd; - let phase = match () { - _ if has_split => "splitting", - _ if sd_count > 0 => "migrating", - _ => "complete", - }; - let progress = match phase { - "splitting" if sd_count + effective_non_sd > 0 => { - sd_count as f64 / (sd_count + effective_non_sd) as f64 + "splitting" if sd_count + non_sd_count > 0 => { + sd_count as f64 / (sd_count + non_sd_count) as f64 } "migrating" if total_sd > 0 => ironwood_sd as f64 / total_sd as f64, _ => 1.0, }; - Ok(MigrationStatus { + let next_action = match task { + MigrationTask::WaitDelay { ms } => format!("Waiting {}s...", ms / 1000), + MigrationTask::WaitBoundary { target } => format!("Waiting for anchor block {}...", target), + MigrationTask::Split { .. } | MigrationTask::Migrate { .. } => { + "Preparing migration transaction...".into() + } + MigrationTask::Done => String::new(), + }; + + MigrationStatus { phase: phase.to_string(), split_fees: acc_split, migrate_fees: acc_migrate, total_fees: acc_split + acc_migrate, sd_notes_count: sd_count, - non_sd_notes_count: effective_non_sd, + non_sd_notes_count: non_sd_count, ironwood_sd_count: ironwood_sd, progress, - next_action: String::new(), - work_summary: format!("SD: {}, non-SD: {}", sd_count, effective_non_sd), - }) -} - -async fn synchronize_to(c: &Coin, height: u32) -> Result<u32> { - crate::sync::synchronize_impl( - (), - vec![c.account], - height, - 100_000, - 10_000, - 10_000, - false, - c, - ) - .await + next_action, + work_summary: format!("SD: {}, non-SD: {}", sd_count, non_sd_count), + } } -/// Wait for heights supplied by Dart's shared block-height service. Tree state -/// is synchronized exactly once, while the boundary is the current tip. +/// Block until the block-height service reports another height. +/// +/// No protocol logic lives here: which boundary the migration needs, and +/// whether the wallet has reached one, are decided by `crate::migrate::plan`. +/// This waits for the next height Dart supplies — the same stream that drives +/// autosync, so by the following cycle the checkpoint reflects it — and then +/// returns so the migration can re-plan against what it finds. #[cfg(feature = "flutter")] -async fn wait_for_anchor_boundary( - sink: &StreamSink<MigrationStatus>, - c: &Coin, - mut block_heights: watch::Receiver<Option<u32>>, - status: &MigrationStatus, - anchor_bucket_size: u32, -) -> Result<()> { - let mut waiting = status.clone(); - waiting.next_action = "Waiting for anchor block...".into(); - sink.add(waiting).ok(); - - let mut boundary = None; +async fn wait_for_next_height(block_heights: &mut watch::Receiver<Option<u32>>) -> Result<()> { loop { block_heights.changed().await?; - let Some(tip) = *block_heights.borrow_and_update() else { - continue; - }; - - let target = match boundary { - Some(boundary) => boundary, - None => { - let db_height = wallet_height(c).await?; - let boundary = crate::migrate::next_anchor_bucket_height( - tip.max(db_height), - anchor_bucket_size, - ); - let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", boundary); - sink.add(waiting).ok(); - boundary - } - }; - - if tip > target { - // If height polling missed the boundary, do not fetch its - // historical tree state. Wait for a boundary that is observed as - // the current tip. - let next_boundary = crate::migrate::next_anchor_bucket_height( - tip.saturating_add(1), - anchor_bucket_size, - ); - boundary = Some(next_boundary); - let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", next_boundary); - sink.add(waiting).ok(); - continue; - } - - boundary = Some(target); - if tip == target { - tracing::info!( - "Migration anchor boundary reached: tip={}, boundary={}", - tip, - target, - ); - synchronize_to(c, target).await?; - let synced_height = wallet_height(c).await?; - if synced_height == target { - return Ok(()); - } - - if synced_height > target { - // Another sync advanced the wallet while we were waiting. - // Move to a future boundary instead of preparing from a - // checkpoint that no longer represents the current tip. - let next_boundary = crate::migrate::next_anchor_bucket_height( - tip.max(synced_height).saturating_add(1), - anchor_bucket_size, - ); - boundary = Some(next_boundary); - let mut waiting = status.clone(); - waiting.next_action = format!("Waiting for anchor block {}...", next_boundary); - sink.add(waiting).ok(); - continue; - } - - anyhow::bail!( - "Migration boundary sync did not advance: wallet={}, boundary={}", - synced_height, - target, - ); + if let Some(tip) = *block_heights.borrow_and_update() { + tracing::info!("Migration observed height {}", tip); + return Ok(()); } } } - -#[cfg(feature = "flutter")] -async fn wallet_height(c: &Coin) -> Result<u32> { - let mut connection = c.get_connection().await?; - Ok(crate::sync::get_db_height(&mut connection, c.account) - .await? - .height) -} diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index 6bde0d8de..b1bb3dc13 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -324,35 +324,30 @@ impl Mutation { /// Complete. async fn step_migration(id_account: i32, context: &Context) -> FieldResult<MigrationEvent> { check_auth(context, id_account, true)?; - let event = crate::api::migrate::step_migration(&context.coin) + let event = crate::migrate::step::step_once(&context.coin, id_account as u32) .await .map_err(|e| format!("Migration error: {e}"))?; Ok(match event { - crate::api::migrate::MigrationEvent::SplitComplete { fee } => MigrationEvent { + crate::migrate::step::StepOutcome::Split { fee } => MigrationEvent { event: "SplitComplete".to_string(), fee: Some(fee as i32), message: None, }, - crate::api::migrate::MigrationEvent::MigrateComplete { fee } => MigrationEvent { + crate::migrate::step::StepOutcome::Migrated { fee } => MigrationEvent { event: "MigrateComplete".to_string(), fee: Some(fee as i32), message: None, }, - crate::api::migrate::MigrationEvent::Complete => MigrationEvent { + crate::migrate::step::StepOutcome::Complete => MigrationEvent { event: "Complete".to_string(), fee: None, message: None, }, - crate::api::migrate::MigrationEvent::NothingToDo => MigrationEvent { + crate::migrate::step::StepOutcome::NothingToDo => MigrationEvent { event: "NothingToDo".to_string(), fee: None, message: None, }, - crate::api::migrate::MigrationEvent::Error { message } => MigrationEvent { - event: "Error".to_string(), - fee: None, - message: Some(message), - }, }) } diff --git a/rust/src/migrate/exec.rs b/rust/src/migrate/exec.rs new file mode 100644 index 000000000..48b0d266b --- /dev/null +++ b/rust/src/migrate/exec.rs @@ -0,0 +1,160 @@ +//! Task execution: the side effects, and nothing else. +//! +//! Every decision has already been made by the time control reaches here — a +//! task arrives naming exactly what to do, and these functions carry it out. +//! Keeping the effects behind this boundary is what makes the decision path +//! testable without a chain. +//! +//! Only the two broadcasts live here. `WaitDelay` and `WaitBoundary` consume +//! time rather than touching the wallet, so the driver schedules them; a +//! durable-execution engine would own them as timers instead. +//! +//! Migration never synchronizes. The wallet's own autosync advances the +//! checkpoint and migration observes where it got to — which is also why it +//! cannot force the wallet onto an anchor boundary and must wait for one. +//! A sync started here would in any case be unreliable: `synchronize_impl` +//! takes `SYNCING` with `try_lock` and returns silently when autosync already +//! holds it. + +use anyhow::Result; + +use crate::{ + account::get_account_full_address, + api::coin::Coin, + db::get_account_hw, + pay::{ + plan::{extract_transaction, plan_transaction, sign_transaction}, + pool::PoolMask, + send, Recipient, + }, +}; + +/// Broadcast the O→O split: consume `inputs`, mint `outputs` as standard +/// denominations back to the wallet's own address. +/// +/// Returns the fee paid. The inputs are locked as part of the broadcast, so a +/// re-planned split cannot select them again. +pub async fn split(c: &Coin, inputs: &[u32], outputs: &[(u64, u8)]) -> Result<u64> { + let network = c.network(); + let mut connection = c.get_connection().await?; + let mut client = c.client().await?; + let height = client.latest_height().await?; + let own_address = own_address(c, &mut connection).await?; + + let mut recipients: Vec<Recipient> = Vec::new(); + for &(denom, count) in outputs { + for _ in 0..count { + recipients.push(Recipient { + address: own_address.clone(), + amount: denom, + pools: Some(PoolMask::from_pool(2).0), // Orchard only + ..Recipient::default() + }); + } + } + + tracing::info!( + "Migration split: {} non-SD notes → {} SD outputs", + inputs.len(), + recipients.len(), + ); + + let pczt = plan_transaction( + &network, + &mut connection, + &mut client, + c.account, + PoolMask::from_pool(2).0, // Orchard source + &recipients, + false, + None, + false, + None, + None, + true, // migration + Some(inputs), + None, // anchor_height + ) + .await?; + + broadcast(c, &mut connection, &mut client, height, pczt).await +} + +/// Broadcast the O→I hop: spend one Orchard SD note at `anchor`, mint +/// `amount` into Ironwood. +/// +/// Returns the fee paid. +pub async fn migrate(c: &Coin, note: u32, amount: u64, anchor: u32) -> Result<u64> { + let network = c.network(); + let mut connection = c.get_connection().await?; + let mut client = c.client().await?; + let height = client.latest_height().await?; + let own_address = own_address(c, &mut connection).await?; + + // One Ironwood output; the dummy Orchard input and dummy output that pad + // the bundle are added by the builder. + let recipients = vec![Recipient { + address: own_address, + amount, + pools: Some(PoolMask::from_pool(3).0), // Ironwood + ..Recipient::default() + }]; + + tracing::info!( + "Migration: note id={} → Ironwood amount={}, anchor={}", + note, + amount, + anchor, + ); + + let pczt = plan_transaction( + &network, + &mut connection, + &mut client, + c.account, + PoolMask::from_pool(2).0, // Orchard source + &recipients, + false, + None, + false, + None, + None, + true, // migration — O→I + Some(&[note]), + Some(anchor), + ) + .await?; + + broadcast(c, &mut connection, &mut client, height, pczt).await +} + +/// Sign, extract, send, and lock the inputs. Returns the fee. +/// +/// Locking is what makes a re-planned task safe: the spent notes drop out of +/// the next observation, so the stale task fails its precondition rather than +/// producing a second transaction over the same inputs. A crash between the +/// send and the lock leaves that window open — closing it needs the two to +/// commit together, which is what a durable-execution transaction step buys. +async fn broadcast( + c: &Coin, + connection: &mut sqlx::SqliteConnection, + client: &mut crate::Client, + height: u32, + pczt: crate::api::pay::PcztPackage, +) -> Result<u64> { + let network = c.network(); + let fee = crate::pay::TxPlan::from_package(&network, &pczt) + .map(|p| p.fee) + .unwrap_or(0); + let pczt = sign_transaction(&mut *connection, c.account, &network, &pczt).await?; + let tx_bytes = extract_transaction(&pczt).await?; + let _txid = send(client, height, &tx_bytes).await?; + crate::pay::lock_spent_notes(&mut *connection, c.account, &tx_bytes).await?; + Ok(fee) +} + +async fn own_address(c: &Coin, connection: &mut sqlx::SqliteConnection) -> Result<String> { + let network = c.network(); + let hw = get_account_hw(&mut *connection, c.account).await?; + get_account_full_address(&network, &mut *connection, c.account, 0, hw).await +} diff --git a/rust/src/migrate/mod.rs b/rust/src/migrate/mod.rs index 968891036..ffa49d188 100644 --- a/rust/src/migrate/mod.rs +++ b/rust/src/migrate/mod.rs @@ -1,19 +1,17 @@ -use anyhow::Result; -use sqlx::{Row, SqliteConnection}; -use tracing::info; +//! Note migration: moving a wallet's ZEC out of Orchard and into Ironwood. +//! +//! The migration runs as a sequence of tasks. [`state`] observes the wallet, +//! [`plan`] decides what to do next (purely, from that observation alone), +//! [`task`] is the vocabulary of things that can be done, and [`exec`] does +//! them. This module holds only the denomination arithmetic they share. -use crate::{ - account::get_account_full_address, - api::coin::Network, - db::get_account_hw, - pay::{ - fee::{FeeManager, COST_PER_ACTION}, - plan::{extract_transaction, plan_transaction, sign_transaction}, - pool::PoolMask, - send, Recipient, - }, - Client, -}; +pub mod exec; +pub mod plan; +pub mod state; +pub mod step; +pub mod task; + +use crate::pay::fee::COST_PER_ACTION; /// Minimum spendable chunk: 100 × COST_PER_ACTION (500,000 zats). /// Below this threshold, non-SD notes are left alone — splitting them @@ -22,7 +20,7 @@ pub const MIN_SD: u64 = 100 * COST_PER_ACTION; /// Maximum number of non-SD notes to split in a single transaction. /// Caps transaction size to avoid oversized bundles that nodes reject. -const MAX_SPLIT_INPUTS: usize = 50; +pub(crate) const MAX_SPLIT_INPUTS: usize = 50; /// Maximum migration anchor interval specified by the migration protocol. pub const ANCHOR_BUCKET_SIZE: u32 = 144; @@ -34,7 +32,7 @@ const TARGET_BLOCK_SPACING_MS: u64 = 75_000; /// Fee padding embedded in each standard denomination. /// Covers Orchard input + change (2 actions in sum mode) and Ironwood /// output (2 actions, padded) = 4 × COST_PER_ACTION = 20,000 zats. -const SD_FEE_PAD: u64 = 4 * COST_PER_ACTION; +pub(crate) const SD_FEE_PAD: u64 = 4 * COST_PER_ACTION; /// Decompose a total amount into standard denomination notes with embedded fees. /// @@ -85,87 +83,7 @@ pub fn is_sd(value: u64) -> bool { value > SD_FEE_PAD && is_iw_sd(value - SD_FEE_PAD) } -/// Whether the next migration action can split the currently known non-SD -/// notes. This mirrors the input cap and ordering used by `step`. -pub(crate) fn has_split_transaction(mut values: Vec<u64>) -> bool { - values.sort_unstable_by(|a, b| b.cmp(a)); - values.truncate(MAX_SPLIT_INPUTS); - values.into_iter().sum::<u64>() >= MIN_SD -} - -/// Result of a migration step. -pub enum MigrationEvent { - /// A split transaction was broadcast. - SplitComplete { fee: u64 }, - /// A migration transaction was broadcast. - MigrateComplete { fee: u64 }, - /// Migration is complete — no more Orchard notes to migrate. - Complete, - /// No action needed (e.g., all notes are already SD but no migration - /// target yet, or waiting for confirmation). - NothingToDo, -} - -/// Current migration status for the UI. -pub struct MigrationStatus { - pub phase: String, - pub progress: f64, - pub next_action: String, - pub work_summary: String, - pub sd_notes_count: u32, - pub non_sd_notes_count: u32, -} - -/// Notes grouped by pool and ZEC/ZSA. -struct OrchardZecNote { - id: u32, - height: u32, - value: u64, - cmx: Option<Vec<u8>>, - has_checkpoint: bool, -} - -/// Fetch unspent Orchard ZEC notes with their cmx values. -/// -/// Like `fetch_unspent_notes_grouped_by_pool` but restricted to Orchard ZEC -/// (pool 2, no asset) and includes `cmx` so callers don't need a second -/// pass to fetch commitments. -async fn fetch_unspent_orchard_notes_with_cmx( - connection: &mut SqliteConnection, - account: u32, - checkpoint_height: u32, -) -> Result<Vec<OrchardZecNote>> { - sqlx::query( - "SELECT a.id_note, a.height, a.value, a.cmx, - EXISTS ( - SELECT 1 - FROM witnesses w - WHERE w.account = a.account - AND w.note = a.id_note - AND w.height = ?1 - ) - FROM notes a - LEFT JOIN spends b ON a.id_note = b.id_note - WHERE b.id_note IS NULL - AND a.account = ?2 - AND a.pool = 2 - AND a.id_asset IS NULL - AND a.locked = 0", - ) - .bind(checkpoint_height) - .bind(account) - .map(|row| OrchardZecNote { - id: row.get(0), - height: row.get(1), - value: row.get::<i64, _>(2) as u64, - cmx: row.get(3), - has_checkpoint: row.get(4), - }) - .fetch_all(connection) - .await - .map_err(Into::into) -} - +/// Scale the anchor interval to the selected migration speed. pub(crate) fn migration_anchor_bucket_size(mean_delay_ms: u64) -> u32 { let blocks = mean_delay_ms.saturating_add(TARGET_BLOCK_SPACING_MS - 1) / TARGET_BLOCK_SPACING_MS; @@ -184,264 +102,6 @@ pub(crate) fn next_anchor_bucket_height(height: u32, bucket_size: u32) -> u32 { } } -/// Run one migration step. Fully idempotent — re-scans notes on every call. -pub async fn step( - network: &Network, - connection: &mut SqliteConnection, - client: &mut Client, - account: u32, - anchor_bucket_size: u32, -) -> Result<MigrationEvent> { - let height = client.latest_height().await?; - let checkpoint_height = crate::sync::get_db_height(&mut *connection, account) - .await? - .height; - - // Get the wallet's own Orchard/Ironwood address - let hw = get_account_hw(&mut *connection, account).await?; - let own_address = get_account_full_address(network, &mut *connection, account, 0, hw).await?; - - // Fetch all unspent Orchard ZEC notes with cmx. - let orchard_zec = - fetch_unspent_orchard_notes_with_cmx(&mut *connection, account, checkpoint_height).await?; - - info!( - "Migration step: {} Orchard ZEC notes found", - orchard_zec.len(), - ); - if orchard_zec.is_empty() { - return Ok(MigrationEvent::Complete); - } - - // Separate SD vs non-SD - let sd_notes: Vec<&OrchardZecNote> = orchard_zec.iter().filter(|n| is_sd(n.value)).collect(); - let non_sd_notes: Vec<&OrchardZecNote> = - orchard_zec.iter().filter(|n| !is_sd(n.value)).collect(); - info!( - "SD notes: {:?}, non-SD notes: {:?}", - sd_notes.iter().map(|n| n.value).collect::<Vec<_>>(), - non_sd_notes.iter().map(|n| n.value).collect::<Vec<_>>(), - ); - - // ── Splitting phase ── - - // Cap inputs to keep transaction size manageable. Sort by value - // descending so the largest notes are split first; remaining non-SD - // notes will be handled in subsequent step() calls. - let capped_non_sd: Vec<&OrchardZecNote> = { - let mut sorted = non_sd_notes.clone(); - sorted.sort_by_key(|n| std::cmp::Reverse(n.value)); - sorted.truncate(MAX_SPLIT_INPUTS); - sorted - }; - - // Calculate total from capped non-SD notes. - let total: u64 = capped_non_sd.iter().map(|n| n.value).sum(); - - if total >= MIN_SD { - // Decompose into standard denomination counts (digits) and remainder. - let (mut digits, mut remainder) = decompose_to_sd(total); - info!("SD split: {:?}", digits,); - - // If the natural remainder is too small to cover the transaction fee, - // carve out MIN_SD from the decomposable pool as a fee buffer. - if remainder < MIN_SD / 2 { - let (d, r) = decompose_to_sd(total.saturating_sub(MIN_SD)); - digits = d; - remainder = r + MIN_SD; - info!("SD split (reserved {} for fees): {:?}", MIN_SD, digits,); - } - - let mut num_outputs: u64 = digits.iter().map(|&(_, c)| c as u64).sum(); - let num_inputs = capped_non_sd.len() as u64; - - // Build a FeeManager matching what plan_transaction will construct, - // including the change output, so our fee estimate is exact. - let mut fm = FeeManager { - migration: true, - ..FeeManager::default() - }; - for _ in 0..num_inputs { - fm.add_input(2); - } - for _ in 0..num_outputs { - fm.add_output(2); - } - fm.add_output(2); // change output - - // Fee loop: if fee exceeds remainder, trim the lowest-denomination - // output to make room, then retry. Exit when fee fits or no outputs - // remain (fall through to migration). - loop { - let fee = fm.fee(); - - if fee <= remainder || num_outputs == 0 { - break; - } - - // Remove one unit from the lowest denomination (last, since - // denominations are sorted largest-first). - if let Some((denom, count)) = digits.last_mut() { - *count -= 1; - remainder += *denom; - num_outputs -= 1; - fm.remove_output(2); - if *count == 0 { - digits.pop(); - } - } - } - - if num_outputs > 0 { - // Build recipients from (denom, count) pairs. - let mut recipients: Vec<Recipient> = Vec::new(); - for &(denom, count) in &digits { - for _ in 0..count { - recipients.push(Recipient { - address: own_address.clone(), - amount: denom, - pools: Some(PoolMask::from_pool(2).0), // Orchard only - ..Recipient::default() - }); - } - } - - info!( - "Migration split: {} non-SD notes (total {}) → {} SD outputs (remainder {})", - capped_non_sd.len(), - total, - recipients.len(), - remainder, - ); - - let preselected: Vec<u32> = capped_non_sd.iter().map(|n| n.id).collect(); - - let pczt = plan_transaction( - network, - &mut *connection, - client, - account, - PoolMask::from_pool(2).0, // Orchard source - &recipients, - false, - None, - false, - None, - None, - true, // migration - Some(&preselected), - None, // anchor_height - ) - .await?; - - let fee = crate::pay::TxPlan::from_package(network, &pczt) - .map(|p| p.fee) - .unwrap_or(0); - let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; - let tx_bytes = extract_transaction(&pczt).await?; - let _txid = send(client, height, &tx_bytes).await?; - crate::pay::lock_spent_notes(&mut *connection, account, &tx_bytes).await?; - - return Ok(MigrationEvent::SplitComplete { fee }); - } - // If no outputs after trimming, fall through to migration phase. - } // end if total >= MIN_SD - - if !sd_notes.is_empty() { - /* - # migrate one orchard SD note at a time - - inputs: - - select 1 SD note, it include 2 COST_ACTIONS - - dummy input - - outputs - - ironwood SD - 2 COST_ACTIONS = "real" SD - - dummy output - */ - - // ── Migrating phase ── - anyhow::ensure!( - checkpoint_height % anchor_bucket_size == 0, - "Migration checkpoint {checkpoint_height} is not on a \ - {anchor_bucket_size}-block anchor boundary", - ); - let anchor_height = checkpoint_height; - - // The selected note must exist at the current boundary checkpoint. - // Migration never rewinds a witness to a historical anchor. - let mut sorted_sd: Vec<&OrchardZecNote> = sd_notes - .iter() - .copied() - .filter(|n| n.height <= anchor_height && n.has_checkpoint) - .collect(); - if sorted_sd.is_empty() { - info!( - "Migration waiting: no SD note is available at checkpoint {}", - checkpoint_height, - ); - return Ok(MigrationEvent::NothingToDo); - } - - // Sort by cmx for deterministic random order - sorted_sd.sort_by(|a, b| { - let a_cmx = a.cmx.as_deref().unwrap_or(&[]); - let b_cmx = b.cmx.as_deref().unwrap_or(&[]); - a_cmx.cmp(b_cmx) - }); - - // Pick one SD note (largest cmx). Its value embeds 2*COST_PER_ACTION - // for Orchard fees; the Ironwood output is the "real" denomination. - let note = sorted_sd.last().unwrap(); - let ironwood_amount = note.value - SD_FEE_PAD; - - // One Ironwood output (dummy output for padding is handled by the - // builder, as is the dummy Orchard input). - let recipients = vec![Recipient { - address: own_address.clone(), - amount: ironwood_amount, - pools: Some(PoolMask::from_pool(3).0), // Ironwood - ..Recipient::default() - }]; - - info!( - "Migration: note id={} value={} → Ironwood amount={}, anchor={} (checkpoint={})", - note.id, note.value, ironwood_amount, anchor_height, checkpoint_height, - ); - - let preselected: Vec<u32> = vec![note.id]; - - let pczt = plan_transaction( - network, - &mut *connection, - client, - account, - PoolMask::from_pool(2).0, // Orchard source - &recipients, - false, - None, - false, - None, - None, - true, // migration — O→I - Some(&preselected), - Some(anchor_height), - ) - .await?; - - let fee = crate::pay::TxPlan::from_package(network, &pczt) - .map(|p| p.fee) - .unwrap_or(0); - let pczt = sign_transaction(&mut *connection, account, network, &pczt).await?; - let tx_bytes = extract_transaction(&pczt).await?; - let _txid = send(client, height, &tx_bytes).await?; - crate::pay::lock_spent_notes(&mut *connection, account, &tx_bytes).await?; - - return Ok(MigrationEvent::MigrateComplete { fee }); - } - - // No SD and no non-SD orchard notes - Ok(MigrationEvent::Complete) -} - #[cfg(test)] mod tests { use super::*; @@ -480,13 +140,6 @@ mod tests { assert_eq!(migration_anchor_bucket_size(u64::MAX), 144); } - #[test] - fn test_has_split_transaction_applies_input_cap() { - assert!(has_split_transaction(vec![MIN_SD])); - assert!(!has_split_transaction(vec![MIN_SD - 1])); - assert!(!has_split_transaction(vec![MIN_SD / 100; 100])); - } - #[test] fn test_decompose_below_min_denom() { // Below d_min (120_000). diff --git a/rust/src/migrate/plan.rs b/rust/src/migrate/plan.rs new file mode 100644 index 000000000..cbefc2bfd --- /dev/null +++ b/rust/src/migrate/plan.rs @@ -0,0 +1,557 @@ +//! Pure decision logic for the migration pipeline. +//! +//! Nothing here performs I/O. Every function is a total function of its +//! arguments, so what the migration decides to do can be unit-tested without +//! a wallet, a chain, or a clock. + +use crate::pay::fee::FeeManager; + +use super::state::{MigrationState, NoteRef}; +use super::task::{MigrationTask, Pacing}; +use super::{decompose_to_sd, next_anchor_bucket_height, MIN_SD, SD_FEE_PAD}; + +/// Plan the standard-denomination outputs of one O→O split transaction. +/// +/// `total` is the summed value of the preselected non-SD inputs, `num_inputs` +/// how many notes they are. Returns sparse `(denom, count)` pairs, largest +/// denomination first. +/// +/// An empty result means no split is worth broadcasting — either `total` is +/// below [`MIN_SD`], or the fee cannot be covered by the change left over +/// after denominating. Callers should treat `plan_split(..).is_empty()` as +/// the authoritative "is a split available?" predicate rather than +/// re-deriving one, so that what is displayed and what is executed cannot +/// disagree. +/// +/// The plan is exact rather than an estimate: the [`FeeManager`] mirrors what +/// `plan_transaction` builds for a migration self-send — one Orchard input per +/// note, one output per denomination, plus a change output — so `fee()` is the +/// fee the transaction will actually pay. +pub fn plan_split(total: u64, num_inputs: u64) -> Vec<(u64, u8)> { + // Below this, splitting costs more in fees than the value it recovers. + if total < MIN_SD { + return Vec::new(); + } + + let (mut digits, mut remainder) = decompose_to_sd(total); + let mut num_outputs: u64 = digits.iter().map(|&(_, c)| c as u64).sum(); + + let mut fm = FeeManager { + migration: true, + ..FeeManager::default() + }; + for _ in 0..num_inputs { + fm.add_input(2); + } + for _ in 0..num_outputs { + fm.add_output(2); + } + fm.add_output(2); // change output + + // While the fee exceeds the change it must come out of, drop one unit of + // the lowest denomination (last, since they are sorted largest-first). + // Each trim moves `denom` into the change *and* removes one action from + // the fee, so this converges in a pass or two. + while num_outputs > 0 && fm.fee() > remainder { + let Some((denom, count)) = digits.last_mut() else { + break; + }; + *count -= 1; + remainder += *denom; + num_outputs -= 1; + fm.remove_output(2); + if *count == 0 { + digits.pop(); + } + } + + digits +} + +/// Total value of a split plan's outputs. +pub fn planned_value(digits: &[(u64, u8)]) -> u64 { + digits.iter().map(|&(d, c)| d * c as u64).sum() +} + +/// Decide the migration's next step. +/// +/// Pure: a total function of observed wallet state and driver pacing. This is +/// the single authority on what the migration will do — the UI phase, the +/// loop's termination, and the action actually executed all derive from it, +/// so they cannot contradict each other. Previously a separate predicate +/// guessed at the same question and could disagree, which is how a wallet +/// could be told "splitting" forever while no split was ever built. +pub fn next_task(s: &MigrationState, p: &Pacing) -> MigrationTask { + let split = plan_split(s.split_input_total(), s.capped_non_sd().len() as u64); + + // Terminal first: a finished migration reports completion immediately + // rather than sleeping through one more delay. + if split.is_empty() && s.orchard_sd.is_empty() { + return MigrationTask::Done; + } + + // Pace the cycle, and never act twice in the same block. + let acted_this_block = p.last_action_height.is_some_and(|h| s.tip_height <= h); + if !p.delay_served || acted_this_block { + return MigrationTask::WaitDelay { + ms: p.sampled_delay_ms, + }; + } + + if !split.is_empty() { + return MigrationTask::Split { + inputs: s.capped_non_sd().iter().map(|n| n.id).collect(), + outputs: split, + }; + } + + // O→I. Every migrating wallet prepares against the same shared anchor, so + // the transaction may only be built once the wallet is synced onto a + // bucket boundary and the note is witnessed there. + match boundary_state(s.tip_height, s.checkpoint_height, s.anchor_bucket_size) { + BoundaryState::At { anchor } => match pick_sd(&s.sd_spendable_at(anchor)) { + Some(note) => MigrationTask::Migrate { + note: note.id, + // The note's value embeds SD_FEE_PAD to pay for this hop; the + // Ironwood output is the pure denomination. + amount: note.value - SD_FEE_PAD, + anchor, + }, + // On a boundary, but no SD note is witnessed there. Aim past it. + None => MigrationTask::WaitBoundary { + target: next_anchor_bucket_height(anchor.saturating_add(1), s.anchor_bucket_size), + }, + }, + // Not on a boundary. Migration does not sync itself: it waits for the + // wallet's autosync to land the checkpoint on one. + BoundaryState::Waiting { target } => MigrationTask::WaitBoundary { target }, + } +} + +/// Pick which SD note to migrate: the largest commitment, which is a +/// deterministic but chain-ordered choice rather than a predictable one. +fn pick_sd<'a>(spendable: &[&'a NoteRef]) -> Option<&'a NoteRef> { + spendable + .iter() + .max_by(|a, b| { + let a_cmx = a.cmx.as_deref().unwrap_or(&[]); + let b_cmx = b.cmx.as_deref().unwrap_or(&[]); + a_cmx.cmp(b_cmx) + }) + .copied() +} + +/// Where the wallet stands relative to the anchor boundary an O→I needs. +/// +/// Two outcomes, deliberately: either the wallet is sitting on a boundary and +/// the transaction can be prepared, or it is not and the caller is told which +/// height it is waiting for. Nothing blocks here and no state is held across +/// the wait — the caller comes back and asks again, so a missed boundary, a +/// sync landing late, or a restart all resolve by re-asking rather than by +/// unwinding a loop. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BoundaryState { + /// The wallet is synced onto `anchor`; an O→I may be prepared here. + At { anchor: u32 }, + /// Not there. Wait for `target` to become the chain tip. + Waiting { target: u32 }, +} + +/// The next boundary the wallet could land on. +/// +/// Takes the later of the tip and the wallet so the target is never a +/// boundary already behind us. +pub fn initial_boundary(tip: u32, wallet_height: u32, bucket_size: u32) -> u32 { + next_anchor_bucket_height(tip.max(wallet_height), bucket_size) +} + +/// Classify the wallet against the anchor discipline. +pub fn boundary_state(tip: u32, checkpoint: u32, bucket_size: u32) -> BoundaryState { + if checkpoint.is_multiple_of(bucket_size) { + BoundaryState::At { anchor: checkpoint } + } else { + BoundaryState::Waiting { + target: initial_boundary(tip, checkpoint, bucket_size), + } + } +} + +/// The phase to show the user, derived from the same `plan_split` the +/// executor uses, so the display cannot claim work that will not happen. +pub fn phase(s: &MigrationState) -> &'static str { + if !plan_split(s.split_input_total(), s.capped_non_sd().len() as u64).is_empty() { + "splitting" + } else if !s.orchard_sd.is_empty() { + "migrating" + } else { + "complete" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Value of one output count in a plan, 0 if the denomination is absent. + fn count_of(digits: &[(u64, u8)], denom: u64) -> u8 { + digits + .iter() + .find(|&&(d, _)| d == denom) + .map(|&(_, c)| c) + .unwrap_or(0) + } + + fn note(id: u32, value: u64, height: u32) -> NoteRef { + NoteRef { + id, + height, + value, + cmx: Some(vec![id as u8; 32]), + has_checkpoint: true, + } + } + + /// A wallet with `non_sd` unsplit notes and `sd` denominated ones, synced + /// to a checkpoint sitting exactly on an anchor boundary. + fn state(non_sd: &[u64], sd: &[u64]) -> MigrationState { + let mut id = 0; + let mut mk = |values: &[u64]| { + values + .iter() + .map(|&v| { + id += 1; + note(id, v, 100) + }) + .collect::<Vec<_>>() + }; + MigrationState { + tip_height: 288, + checkpoint_height: 288, + anchor_bucket_size: 144, + orchard_non_sd: mk(non_sd), + orchard_sd: mk(sd), + ironwood_sd_count: 0, + own_address: "addr".into(), + } + } + + /// Pacing for a cycle whose delay and sync are already behind it. + fn ready() -> Pacing { + Pacing { + sampled_delay_ms: 1000, + last_action_height: None, + delay_served: true, + } + } + + #[test] + fn test_initial_boundary_never_aims_behind_the_wallet() { + assert_eq!(initial_boundary(200, 100, 144), 288); + // Wallet ahead of the observed tip: aim past the wallet, not the tip. + assert_eq!(initial_boundary(100, 200, 144), 288); + // Already exactly on one. + assert_eq!(initial_boundary(288, 288, 144), 288); + } + + #[test] + fn test_boundary_state_two_outcomes() { + assert_eq!( + boundary_state(288, 288, 144), + BoundaryState::At { anchor: 288 }, + ); + assert_eq!( + boundary_state(200, 150, 144), + BoundaryState::Waiting { target: 288 }, + ); + } + + /// A boundary that went by unobserved must never be prepared against: + /// its tree state is no longer the one other wallets are using. + #[test] + fn test_boundary_never_targets_a_passed_height() { + for bucket in [1u32, 4, 12, 144] { + for tip in [1u32, 143, 145, 289, 100_001] { + for checkpoint in [0u32, 1, 143, 288] { + if let BoundaryState::Waiting { target } = + boundary_state(tip, checkpoint, bucket) + { + assert!(target.is_multiple_of(bucket), "bucket {bucket}"); + assert!(target >= tip, "target {target} behind tip {tip}"); + assert!(target > checkpoint, "target {target} behind wallet"); + } + } + } + } + } + + #[test] + fn test_next_task_done_on_empty_wallet() { + assert_eq!(next_task(&state(&[], &[]), &ready()), MigrationTask::Done); + } + + #[test] + fn test_next_task_done_skips_the_delay() { + // A finished migration reports completion immediately; it does not + // sleep one more time first. + let idle = Pacing { + delay_served: false, + ..ready() + }; + assert_eq!(next_task(&state(&[], &[]), &idle), MigrationTask::Done); + } + + #[test] + fn test_next_task_dust_below_threshold_is_done() { + // Sub-MIN_SD dust is deliberately left in Orchard rather than being + // split at a loss. + assert_eq!( + next_task(&state(&[100_000], &[]), &ready()), + MigrationTask::Done + ); + } + + #[test] + fn test_next_task_delays_first() { + let idle = Pacing { + delay_served: false, + ..ready() + }; + assert_eq!( + next_task(&state(&[550_000], &[]), &idle), + MigrationTask::WaitDelay { ms: 1000 }, + ); + } + + #[test] + fn test_next_task_does_not_act_twice_in_one_block() { + let s = state(&[550_000], &[]); + let paced = Pacing { + last_action_height: Some(s.tip_height), + ..ready() + }; + assert_eq!(next_task(&s, &paced), MigrationTask::WaitDelay { ms: 1000 },); + } + + /// Regression: the reported stall. A non-SD total in the dead zone must + /// yield a Split, not an unactionable state the runner spins on. + #[test] + fn test_next_task_splits_in_the_dead_zone() { + for total in [500_000u64, 550_000, 619_999] { + match next_task(&state(&[total], &[]), &ready()) { + MigrationTask::Split { inputs, outputs } => { + assert_eq!(inputs, vec![1]); + assert!(!outputs.is_empty(), "total {total}"); + } + other => panic!("total {total} planned {other:?}, expected a split"), + } + } + } + + /// Migration never syncs: a split is planned against whatever checkpoint + /// the wallet's autosync has reached. + #[test] + fn test_next_task_splits_without_syncing() { + let mut s = state(&[550_000], &[]); + s.checkpoint_height = 200; + assert!(matches!( + next_task(&s, &ready()), + MigrationTask::Split { .. }, + )); + } + + #[test] + fn test_next_task_migrates_sd_notes() { + let s = state(&[], &[120_000, 1_020_000]); + match next_task(&s, &ready()) { + MigrationTask::Migrate { + note, + amount, + anchor, + } => { + // Largest cmx wins; both notes carry SD_FEE_PAD for this hop. + assert_eq!(note, 2); + assert_eq!(amount, 1_020_000 - SD_FEE_PAD); + assert_eq!(anchor, 288); + } + other => panic!("expected a migrate, got {other:?}"), + } + } + + #[test] + fn test_next_task_splitting_takes_priority_over_migrating() { + // Splits are O→O and need no anchor, so they run first. + assert!(matches!( + next_task(&state(&[550_000], &[120_000]), &ready()), + MigrationTask::Split { .. }, + )); + } + + #[test] + fn test_next_task_waits_for_boundary_off_anchor() { + let mut s = state(&[], &[120_000]); + s.checkpoint_height = 300; // 300 % 144 != 0 + assert_eq!( + next_task(&s, &ready()), + MigrationTask::WaitBoundary { target: 432 }, + ); + } + + /// With a one-block bucket every height is a boundary, so the old + /// `ensure!` guarding this was vacuous and an O→I could be prepared off + /// a checkpoint the runner never waited for. The precondition now carries + /// that discipline instead. + #[test] + fn test_next_task_unit_bucket_is_always_on_boundary() { + let mut s = state(&[], &[120_000]); + s.anchor_bucket_size = 1; + s.checkpoint_height = 301; + s.orchard_sd[0].height = 300; + assert!(matches!( + next_task(&s, &ready()), + MigrationTask::Migrate { .. } + )); + } + + #[test] + fn test_next_task_waits_when_no_sd_note_is_witnessed() { + let mut s = state(&[], &[120_000]); + s.orchard_sd[0].has_checkpoint = false; + assert_eq!( + next_task(&s, &ready()), + MigrationTask::WaitBoundary { target: 432 }, + ); + } + + #[test] + fn test_phase_agrees_with_next_task() { + // The display and the executor read the same plan. + let cases = [ + (state(&[550_000], &[]), "splitting"), + (state(&[], &[120_000]), "migrating"), + (state(&[], &[]), "complete"), + (state(&[100_000], &[]), "complete"), + ]; + for (s, expected) in cases { + assert_eq!(phase(&s), expected); + let terminal = matches!(next_task(&s, &ready()), MigrationTask::Done); + assert_eq!(terminal, expected == "complete", "phase {expected}"); + } + } + + #[test] + fn test_precondition_rejects_a_spent_input() { + let s = state(&[550_000], &[]); + let task = next_task(&s, &ready()); + assert!(task.is_satisfied_by(&s)); + // The split is broadcast and locks its inputs, so they leave the + // snapshot; replanning must not reuse them. + let after = state(&[], &[]); + assert!(!task.is_satisfied_by(&after)); + } + + #[test] + fn test_precondition_rejects_a_moved_anchor() { + let s = state(&[], &[120_000]); + let task = next_task(&s, &ready()); + assert!(task.is_satisfied_by(&s)); + let mut moved = s.clone(); + moved.checkpoint_height = 432; // synced past the planned anchor + assert!(!task.is_satisfied_by(&moved)); + } + + #[test] + fn test_plan_split_below_min_sd() { + // Not worth splitting, however it would decompose. + assert!(plan_split(MIN_SD - 1, 1).is_empty()); + assert!(plan_split(400_000, 1).is_empty()); + assert!(plan_split(0, 0).is_empty()); + } + + /// Regression: a non-SD total anywhere in [MIN_SD, MIN_SD + 120_000) used + /// to plan zero outputs, because a flat MIN_SD fee reserve was subtracted + /// before decomposing. With no outputs no split was broadcast, no note was + /// spent, and the migration loop span forever on an unchanged wallet. + #[test] + fn test_plan_split_dead_zone_still_splits() { + for total in [500_000u64, 510_000, 550_000, 599_999, 619_999] { + let digits = plan_split(total, 1); + assert!( + !digits.is_empty(), + "total {total} planned no outputs — dead zone regression", + ); + assert!(planned_value(&digits) <= total); + } + } + + #[test] + fn test_plan_split_reported_case() { + // The user's log: `SD split: [(120000, 4)]`, one input note. + // fee = (1 input + 4 outputs + 1 change) × 5000 = 30_000, and the + // change is 550_000 - 480_000 = 70_000, so nothing is trimmed. + let digits = plan_split(550_000, 1); + assert_eq!(digits, vec![(120_000, 4)]); + assert_eq!(planned_value(&digits), 480_000); + } + + #[test] + fn test_plan_split_trims_when_fee_exceeds_change() { + // 50 dust inputs summing to 550_000: the fee starts at + // (50 + 4 + 1) × 5000 = 275_000 against 70_000 of change, so outputs + // are trimmed until it fits rather than the split being abandoned. + let digits = plan_split(550_000, 50); + assert!(!digits.is_empty(), "should still plan a smaller split"); + assert!(count_of(&digits, 120_000) < 4, "should have trimmed"); + assert!(planned_value(&digits) <= 550_000); + } + + #[test] + fn test_plan_split_change_covers_fee() { + // Whatever it plans, the change must cover the fee it will pay. + for num_inputs in [1u64, 2, 7, 50] { + for total in [500_000u64, 620_000, 1_000_000, 12_345_678, 100_000_000] { + let digits = plan_split(total, num_inputs); + let num_outputs: u64 = digits.iter().map(|&(_, c)| c as u64).sum(); + let remainder = total - planned_value(&digits); + + let mut fm = FeeManager { + migration: true, + ..FeeManager::default() + }; + for _ in 0..num_inputs { + fm.add_input(2); + } + for _ in 0..num_outputs { + fm.add_output(2); + } + fm.add_output(2); + + if !digits.is_empty() { + assert!( + fm.fee() <= remainder, + "total {total} / {num_inputs} inputs: fee {} > change {remainder}", + fm.fee(), + ); + } + } + } + } + + #[test] + fn test_plan_split_outputs_are_sd() { + let digits = plan_split(12_345_678, 3); + assert!(!digits.is_empty()); + for &(denom, count) in &digits { + assert!(super::super::is_sd(denom), "{denom} is not a denomination"); + assert!(count > 0, "zero-count denominations should be dropped"); + } + } + + #[test] + fn test_plan_split_largest_first() { + let digits = plan_split(100_000_000, 1); + let denoms: Vec<u64> = digits.iter().map(|&(d, _)| d).collect(); + let mut sorted = denoms.clone(); + sorted.sort_unstable_by(|a, b| b.cmp(a)); + assert_eq!(denoms, sorted, "trim assumes largest-first ordering"); + } +} diff --git a/rust/src/migrate/state.rs b/rust/src/migrate/state.rs new file mode 100644 index 000000000..e320c242d --- /dev/null +++ b/rust/src/migrate/state.rs @@ -0,0 +1,146 @@ +//! A snapshot of everything the migration needs in order to decide what to do. +//! +//! `observe` is the migration's single reader of wallet state. Prior to this, +//! the executing path and the status path each ran their own note query with +//! their own filters, and could therefore disagree about what work remained — +//! which is how a wallet ended up looping forever on a split it was never +//! going to build. One query, one snapshot, one set of facts. + +use anyhow::Result; +use sqlx::{Row, SqliteConnection}; + +use crate::{account::get_account_full_address, api::coin::Network, db::get_account_hw, Client}; + +use super::{is_iw_sd, is_sd, MAX_SPLIT_INPUTS}; + +/// An unspent, unlocked note the migration may act on. +#[derive(Clone, Debug)] +pub struct NoteRef { + pub id: u32, + pub height: u32, + pub value: u64, + pub cmx: Option<Vec<u8>>, + /// Whether a witness exists for this note at the observed checkpoint. + /// A note without one cannot be spent at that anchor. + pub has_checkpoint: bool, +} + +/// Wallet state at one instant, as the migration sees it. +#[derive(Clone, Debug)] +pub struct MigrationState { + pub tip_height: u32, + pub checkpoint_height: u32, + pub anchor_bucket_size: u32, + /// Orchard ZEC notes already at a standard denomination (`10^k + SD_FEE_PAD`), + /// ready for the O→I hop. + pub orchard_sd: Vec<NoteRef>, + /// Orchard ZEC notes that must be split before they can be migrated. + pub orchard_non_sd: Vec<NoteRef>, + /// Ironwood notes already at a pure denomination — migration's output. + pub ironwood_sd_count: u32, + pub own_address: String, +} + +impl MigrationState { + /// The non-SD notes a single split may consume: the largest first, capped + /// at [`MAX_SPLIT_INPUTS`] to keep the bundle a size nodes will accept. + /// Whatever is left over is picked up by later splits. + pub fn capped_non_sd(&self) -> Vec<&NoteRef> { + let mut sorted: Vec<&NoteRef> = self.orchard_non_sd.iter().collect(); + sorted.sort_by_key(|n| std::cmp::Reverse(n.value)); + sorted.truncate(MAX_SPLIT_INPUTS); + sorted + } + + /// Total value available to one split transaction. + pub fn split_input_total(&self) -> u64 { + self.capped_non_sd().iter().map(|n| n.value).sum() + } + + /// SD notes spendable at `anchor`: present at that checkpoint, with a + /// witness. Migration never rewinds a witness to a historical anchor. + pub fn sd_spendable_at(&self, anchor: u32) -> Vec<&NoteRef> { + self.orchard_sd + .iter() + .filter(|n| n.height <= anchor && n.has_checkpoint) + .collect() + } +} + +/// Read wallet state. The only I/O in the decision path: one note query, the +/// wallet checkpoint, the chain tip, and the account's own address. +pub async fn observe( + network: &Network, + connection: &mut SqliteConnection, + client: &mut Client, + account: u32, + anchor_bucket_size: u32, +) -> Result<MigrationState> { + let tip_height = client.latest_height().await?; + let checkpoint_height = crate::sync::get_db_height(&mut *connection, account) + .await? + .height; + + let hw = get_account_hw(&mut *connection, account).await?; + let own_address = get_account_full_address(network, &mut *connection, account, 0, hw).await?; + + // Orchard (pool 2) and Ironwood (pool 3) ZEC notes in one pass. Locked + // notes are excluded: a broadcast transaction locks its inputs, so they + // disappear here and any task that named them fails its precondition + // instead of being planned a second time. + let notes = sqlx::query( + "SELECT a.id_note, a.height, a.pool, a.value, a.cmx, + EXISTS ( + SELECT 1 + FROM witnesses w + WHERE w.account = a.account + AND w.note = a.id_note + AND w.height = ?1 + ) + FROM notes a + LEFT JOIN spends b ON a.id_note = b.id_note + WHERE b.id_note IS NULL + AND a.account = ?2 + AND a.pool IN (2, 3) + AND a.id_asset IS NULL + AND a.locked = 0", + ) + .bind(checkpoint_height) + .bind(account) + .map(|row| { + let pool: u8 = row.get(2); + let note = NoteRef { + id: row.get(0), + height: row.get(1), + value: row.get::<i64, _>(3) as u64, + cmx: row.get(4), + has_checkpoint: row.get(5), + }; + (pool, note) + }) + .fetch_all(&mut *connection) + .await?; + + let mut orchard_sd = Vec::new(); + let mut orchard_non_sd = Vec::new(); + let mut ironwood_sd_count = 0u32; + + for (pool, note) in notes { + match pool { + 2 if is_sd(note.value) => orchard_sd.push(note), + 2 => orchard_non_sd.push(note), + 3 if is_iw_sd(note.value) => ironwood_sd_count += 1, + _ => {} + } + } + + Ok(MigrationState { + tip_height, + checkpoint_height, + anchor_bucket_size, + orchard_sd, + orchard_non_sd, + ironwood_sd_count, + own_address, + }) +} diff --git a/rust/src/migrate/step.rs b/rust/src/migrate/step.rs new file mode 100644 index 000000000..ec209773b --- /dev/null +++ b/rust/src/migrate/step.rs @@ -0,0 +1,80 @@ +//! One migration step, without waiting. +//! +//! The shared entry point behind both front ends: `api::migrate` exposes it to +//! Flutter and the GraphQL server calls it directly. Neither the pacing delay +//! nor the boundary wait belongs here — a caller polls this and does its own +//! waiting between calls, which is what makes it safe to drive from a timer. + +use anyhow::Result; + +use crate::api::coin::Coin; + +use super::{ + exec, + plan::next_task, + task::{MigrationTask, Pacing}, +}; + +/// What one step did. +pub enum StepOutcome { + Split { + fee: u64, + }, + Migrated { + fee: u64, + }, + /// Nothing left to migrate. + Complete, + /// The next action is a wait, which a single step does not perform. + NothingToDo, +} + +/// Run one step for `account`. +/// +/// The account is explicit rather than read from `c.account`: a caller holding +/// a process-wide coin — the GraphQL server does — must step the wallet it was +/// asked about, not whichever one the coin happens to name. +/// +/// Migration does not synchronize; this plans against the checkpoint the +/// wallet already has, so the caller syncs first if it wants a current one. +pub async fn step_once(c: &Coin, account: u32) -> Result<StepOutcome> { + let c = &Coin { + account, + ..c.clone() + }; + let mut connection = c.get_connection().await?; + let mut client = c.client().await?; + let state = super::state::observe( + &c.network(), + &mut connection, + &mut client, + account, + super::ANCHOR_BUCKET_SIZE, + ) + .await?; + drop(connection); + + // One step does one substantive thing: no pacing delay to serve. + let pacing = Pacing { + delay_served: true, + ..Pacing::default() + }; + + Ok(match next_task(&state, &pacing) { + MigrationTask::Done => StepOutcome::Complete, + MigrationTask::Split { inputs, outputs } => StepOutcome::Split { + fee: exec::split(c, &inputs, &outputs).await?, + }, + MigrationTask::Migrate { + note, + amount, + anchor, + } => StepOutcome::Migrated { + fee: exec::migrate(c, note, amount, anchor).await?, + }, + // Waiting is the caller's business, not a single step's. + MigrationTask::WaitDelay { .. } | MigrationTask::WaitBoundary { .. } => { + StepOutcome::NothingToDo + } + }) +} diff --git a/rust/src/migrate/task.rs b/rust/src/migrate/task.rs new file mode 100644 index 000000000..b5348b24b --- /dev/null +++ b/rust/src/migrate/task.rs @@ -0,0 +1,107 @@ +//! The unit of migration work. +//! +//! A task is plain data: it names an action without performing it, so the +//! same value can be planned, displayed, re-validated against fresh state, +//! and only then executed. Time- and network-bound work are distinct variants +//! rather than steps buried inside a larger function, which is what lets a +//! driver — or, later, a durable-execution engine — schedule, retry, and +//! resume them independently. + +use super::state::MigrationState; + +/// What kind of work a task represents. A driver uses this to decide how to +/// run it: a timer wants a durable sleep, a network read wants retry with +/// backoff, an effect wants exactly-once semantics. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TaskKind { + /// Elapses wall-clock time. No wallet state changes. + Time, + /// Broadcasts a transaction. The only kind that spends notes. + Effect, + /// Nothing left to do. + Terminal, +} + +/// One step of the migration. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum MigrationTask { + /// Pace the migration. The first step of every cycle, including the + /// first: acting on a predictable schedule would leak the wallet's + /// activity to an observer. + WaitDelay { ms: u64 }, + /// Hold until the wallet's checkpoint lands on a shared anchor boundary. + /// Migration does not sync — the wallet's own autosync does — so this + /// waits for that to happen rather than making it happen. `target` is the + /// boundary being waited for, for display. + WaitBoundary { target: u32 }, + /// O→O self-send: consume `inputs` and mint standard denominations. + Split { + inputs: Vec<u32>, + outputs: Vec<(u64, u8)>, + }, + /// O→I: spend one Orchard SD note, mint `amount` into Ironwood. + Migrate { note: u32, amount: u64, anchor: u32 }, + /// No further progress is possible. + Done, +} + +impl MigrationTask { + pub fn kind(&self) -> TaskKind { + match self { + MigrationTask::WaitDelay { .. } | MigrationTask::WaitBoundary { .. } => TaskKind::Time, + MigrationTask::Split { .. } | MigrationTask::Migrate { .. } => TaskKind::Effect, + MigrationTask::Done => TaskKind::Terminal, + } + } + + /// Whether this task is still valid against freshly observed state. + /// + /// A task is planned from one snapshot and executed against another: the + /// chain advances, a sync lands, an earlier broadcast locks its inputs. + /// Re-checking here turns a stale plan into a re-plan rather than an + /// error or, worse, a second transaction over notes already spent. + pub fn is_satisfied_by(&self, s: &MigrationState) -> bool { + match self { + MigrationTask::WaitDelay { .. } | MigrationTask::WaitBoundary { .. } => true, + MigrationTask::Split { inputs, .. } => inputs + .iter() + .all(|id| s.orchard_non_sd.iter().any(|n| n.id == *id)), + MigrationTask::Migrate { note, anchor, .. } => { + s.checkpoint_height == *anchor + && anchor.is_multiple_of(s.anchor_bucket_size) + && s.sd_spendable_at(*anchor).iter().any(|n| n.id == *note) + } + MigrationTask::Done => true, + } + } +} + +/// Driver-local pacing state, threaded through the decision function so that +/// it stays pure. +/// +/// `sampled_delay_ms` is drawn by the driver rather than computed during +/// planning: a durable-execution engine replays control flow, so a random +/// draw has to be a journaled input, never something re-rolled on replay. +#[derive(Clone, Copy, Debug, Default)] +pub struct Pacing { + pub sampled_delay_ms: u64, + /// Tip height at the last broadcast, so the migration does not act twice + /// in one block. + pub last_action_height: Option<u32>, + /// Whether this cycle's delay has already elapsed. + pub delay_served: bool, +} + +impl Pacing { + /// Begin a fresh cycle, delaying again. Used when a planned task turns + /// out to be stale, so that retrying cannot become a hot loop. + pub fn restart(&mut self) { + self.delay_served = false; + } + + /// Begin a new cycle after an effect has been broadcast at `height`. + pub fn after_effect(&mut self, height: u32) { + self.last_action_height = Some(height); + self.restart(); + } +} From d6ec0b538b226dc650323c00dde8e4e7e010b8ec Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sun, 30 Aug 2026 08:19:59 +0800 Subject: [PATCH 135/189] chore(pay): demote the extracted transaction hex to debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every transaction logged its full hex at info level. It is multi-kilobyte and drowns out everything around it — enough to make a CI log or a bug report impractical to read. Still available at debug when inspecting a specific transaction. Claude-Session: https://claude.ai/code/session_01TppXvnfqGTBNJWEtv6e2ix --- rust/src/pay/plan.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index dd967084d..ccdf40324 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -25,7 +25,7 @@ use sapling_crypto::PaymentAddress; use secp256k1::{PublicKey, SecretKey}; use sha2::{Digest as _, Sha256}; use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; -use tracing::{event, info, span, Level}; +use tracing::{debug, event, info, span, Level}; use zcash_address::{unified::Receiver, ConversionError, TryFromAddress, ZcashAddress}; use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec as _}; use zcash_note_encryption::Domain; @@ -1398,7 +1398,9 @@ pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { tx.write(&mut tx_bytes).unwrap(); info!("Tx Extracted"); span.in_scope(|| { - info!("TX HEX: {}", hex::encode(&tx_bytes)); + // Multi-kilobyte; only wanted when inspecting a specific + // transaction, and it drowns out everything else in a log. + debug!("TX HEX: {}", hex::encode(&tx_bytes)); info!("Tx Ready - {} bytes", tx_bytes.len()); }); return Ok(tx_bytes); From 3745ec8030dbdca7e7ab2a24d33afbbf7acde05a Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sun, 30 Aug 2026 08:23:22 +0800 Subject: [PATCH 136/189] test(migrate): cover Orchard->Ironwood migration end-to-end on regtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drives a full migration headlessly through the GraphQL stepMigration mutation: fund Orchard, split into standard denominations, migrate each to Ironwood, terminate. Two subjects on one chain, the second holding 550_000 zats — the balance from the reported stall, which used to plan zero outputs and spin forever. Two properties of the system shape the setup: Orchard can only be funded before Ironwood activates. Afterwards there is no pool-restricted address — addressByAccount returns the same string for orchard and ironwood — so a payment lands in Ironwood and legacy Orchard notes can no longer be created. The chain must therefore be mined into the window above coinbase maturity (100) and below activation (250), and since a chain cannot be rewound, both subjects are funded up front in one test rather than one per test. The activation height must agree between misc/zebra.toml and the regtest parameters in rust/src/api/coin.rs, or the wallet builds with a branch id the chain rejects. Migration does not synchronize, so the driver calls synchronizeAccount itself between steps and parks the wallet on an anchor boundary before each O->I. Beyond "it completed", the test checks that Orchard notes existed beforehand; that Ironwood notes exist afterwards and every one is a pure 10^k denomination; that the Orchard residue is below the threshold worth splitting; that each O->I costs exactly SD_FEE_PAD, since the note prefunds its own hop; that total fees stay under a quarter of the balance; and that ironwood + leftover + fees equals what was funded, so nothing is lost or invented. A skipped test is a green build, so a missing prerequisite fails under CI and only skips locally. mine.sh takes BLOCKS and FUND; both defaults reproduce its current behaviour, leaving the wallet tests untouched. FUND=0 exits once the chain is up, since the shielding half asserts an Ironwood balance and so cannot run before activation. It also now waits for lightwalletd to ingest rather than assuming a fixed sleep was long enough. The new job cannot reuse the zebra action: wallet.yml references it at @main, so edits would not take effect in the PR that makes them. It inlines the install with the same cache key instead. Claude-Session: https://claude.ai/code/session_01TppXvnfqGTBNJWEtv6e2ix --- .github/workflows/migration.yml | 85 +++++++ example/sh/mine.sh | 32 ++- tests/tests/test_migration.py | 380 ++++++++++++++++++++++++++++++++ tests/tests/utils.py | 13 +- 4 files changed, 507 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/migration.yml create mode 100644 tests/tests/test_migration.py diff --git a/.github/workflows/migration.yml b/.github/workflows/migration.yml new file mode 100644 index 000000000..891107ac7 --- /dev/null +++ b/.github/workflows/migration.yml @@ -0,0 +1,85 @@ +name: Migration Tests + +on: + workflow_dispatch: + pull_request: + branches: + - main + +jobs: + migration: + if: ${{ !startsWith(github.head_ref, 'release-please--branches--') }} + runs-on: ubuntu-latest + steps: + - name: Install RUST + uses: dtolnay/rust-toolchain@stable + - name: Checkout code + uses: actions/checkout@v6 + + # Same path and key as .github/actions/zebra, so this job shares the + # cache that the wallet tests populate rather than building its own. + - name: Cache zebra + id: cache-zebra + uses: actions/cache@v5 + with: + path: | + ./tools/bin + key: ${{ runner.os }}-zebra-lwd-6.2.1 + + - name: Install zebra & lightwalletd + if: steps.cache-zebra.outputs.cache-hit != 'true' + run: | + sudo apt update && sudo apt install -y libclang-dev clang + rm -rf ./tools + cargo install --git https://github.com/ZcashFoundation/zebra --tag v6.2.1 --features=internal-miner --root ./tools zebrad + git clone https://github.com/zecrocks/lightwalletd.git + cd lightwalletd + git checkout 9b69519c57785e04e92a16365483f869dd878700 + go build -o ../tools/bin/lightwalletd . + + - name: Save cache + if: steps.cache-zebra.outputs.cache-hit != 'true' + uses: actions/cache/save@v5 + with: + path: ./tools/bin + key: ${{ runner.os }}-zebra-lwd-6.2.1 + + - name: Build zkool_graphql + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libudev-dev + cd rust + cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params + + # target/release first, so the chain is brought up with the binary built + # from this PR rather than the released one cached in tools/bin. + - name: Add tools to PATH + run: | + echo "$GITHUB_WORKSPACE/target/release" >> $GITHUB_PATH + echo "$GITHUB_WORKSPACE/tools/bin" >> $GITHUB_PATH + + # Stops below the Ironwood (NU6.3) activation height of 250 and funds + # nothing: the test needs to create legacy Orchard notes, which is only + # possible before activation, and it funds its own accounts. + - name: Start regtest below Ironwood activation + run: | + rm -rf "$HOME/.cache/zebra" data regtest.db + ./example/sh/mine.sh + env: + BLOCKS: 150 + FUND: 0 + MINER_ADDRESS: "tmQ1BiNRfsvT6eMkJ5n7nMZsbz1PGwCs1Zs" + + - name: Run migration test + run: | + cd tests + pip install uv + uv sync --all-groups + uv run pytest tests/test_migration.py -v -s + + - name: Dump logs on failure + if: failure() + run: | + tail -100 zebrad.log || true + tail -100 lightwalletd.log || true + tail -200 /tmp/graphql_migration.log || true diff --git a/example/sh/mine.sh b/example/sh/mine.sh index 438013fb9..ee440c83d 100755 --- a/example/sh/mine.sh +++ b/example/sh/mine.sh @@ -2,6 +2,19 @@ set -euo pipefail set -x +# Number of blocks to mine. The note-migration tests need a chain that stops +# below the Ironwood (NU6.3) activation height in misc/zebra.toml, because +# after activation there is no pool-restricted address — addressByAccount +# returns the same string for orchard and ironwood — so a payment lands in +# Ironwood and legacy Orchard notes can no longer be created. They pass 150: +# above coinbase maturity (100), below activation (250). +BLOCKS=${BLOCKS:-300} + +# Whether to shield the miner's coinbase to DESTINATION_ADDRESS afterwards. +# Set to 0 for callers that fund their own accounts; the shielding step below +# requires Ironwood to be active and so cannot run on a pre-activation chain. +FUND=${FUND:-1} + sed -i -e "s#miner_address = \"\"#miner_address = \"${MINER_ADDRESS}\"#" misc/zebra.toml nohup zebrad -c misc/zebra.toml start > zebrad.log 2>&1 & disown sleep 60 @@ -10,7 +23,7 @@ nohup lightwalletd --no-tls-very-insecure --data-dir=./data/regtest --grpc-bind- nohup zkool_graphql -d regtest.db -l http://localhost:8137 -n & sleep 60 -curl --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "generate", "params": [300] }' -H 'Content-type: application/json' http://127.0.0.1:18232/ +curl --data-binary "{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"generate\", \"params\": [${BLOCKS}] }" -H 'Content-type: application/json' http://127.0.0.1:18232/ GRAPHQL_URL="http://localhost:8000/graphql" MATURITY_THRESHOLD=100 @@ -37,10 +50,27 @@ wait_zaino() { done } +# Wait for lightwalletd to ingest what was just mined. currentHeight is +# served through it, so this also confirms the whole stack is answering. +for _ in $(seq 1 120); do + H=$(height || true) + case "$H" in '' | null) H=0 ;; esac + if [ "$H" -ge "$BLOCKS" ]; then + break + fi + sleep 2 +done + # Get current height HEIGHT=$(height) echo "Height: $HEIGHT" +if [ "$FUND" != "1" ]; then + echo "FUND=0: leaving the chain unfunded at height $HEIGHT" + pkill zkool_graphql + exit 0 +fi + # Create miner account MINER=$(gql 'mutation CreateAccount($account: NewAccount!) { createAccount(newAccount: $account) diff --git a/tests/tests/test_migration.py b/tests/tests/test_migration.py new file mode 100644 index 000000000..8bd9222e1 --- /dev/null +++ b/tests/tests/test_migration.py @@ -0,0 +1,380 @@ +"""End-to-end note migration on regtest: Orchard → split → SD → Ironwood. + +Migration is driven headlessly through the GraphQL `stepMigration` mutation, +which runs one step of the pipeline per call. + +Two properties of the system shape this test: + +* **Orchard can only be funded before Ironwood activates.** After NU6.3 there + is no pool-restricted address — `addressByAccount` returns the same string + for `orchard` and `ironwood` — so a payment lands in Ironwood and legacy + Orchard notes can no longer be created. The chain must therefore activate + NU6.3 above the funding height, and a chain cannot be rewound, so both + subjects are funded up front in a single test rather than one per test. +* **Migration does not synchronize.** The wallet's autosync does that in the + app, so this driver calls `synchronizeAccount` itself between steps and + parks the wallet on an anchor boundary before an O→I step can run. + +Requires a fresh regtest chain mined into the window between coinbase +maturity (100) and NU6.3 activation (250), so there is spendable coinbase and +Ironwood is not yet live: + + zebrad -c misc/zebra.toml start + curl --data-binary '{"jsonrpc":"1.0","method":"generate","params":[150]}' \ + -H 'Content-type: application/json' http://127.0.0.1:18232/ + lightwalletd --no-tls-very-insecure --data-dir=./data/regtest \ + --grpc-bind-addr=127.0.0.1:8137 --zcash-conf-path=./misc/zebra.conf + pytest tests/test_migration.py +""" + +import os + +import pytest +from gql import GraphQLRequest, gql + +from utils import ( + cleanup_test_files, + dump_server_log, + create_account, + get_address, + get_balance, + get_current_height, + kill_existing_zkool_processes, + mine_blocks, + start_zkool_instance, + stop_zkool_instance, + sync_account, + wait_for_blocks, +) + +# Must match crate::migrate::ANCHOR_BUCKET_SIZE, which step_migration uses. +ANCHOR_BUCKET_SIZE = 144 +# Must match crate::migrate::MIN_SD (100 * COST_PER_ACTION), in zats. +MIN_SD = 500_000 +# The smallest standard denomination, 10^5 + SD_FEE_PAD. +SD_MIN_DENOM = 120_000 +# Must match crate::migrate::SD_FEE_PAD (4 * COST_PER_ACTION). Every Orchard SD +# note carries this to pay for its own O→I hop, so each migrate step should +# cost exactly this much. +SD_FEE_PAD = 20_000 +# Migration must not eat an unreasonable share of the balance. Loose, because +# the per-transaction cost is fixed and so weighs heavily on a small wallet. +MAX_FEE_FRACTION = 0.25 +# --coin 2: regtest. Passed explicitly; the server would otherwise infer the +# network from the database filename. +REGTEST_COIN = 2 +ZATS_PER_ZEC = 100_000_000 +# Coinbase maturity: the miner's notes are only spendable this far back. +MATURITY = 100 + +# NU6.3 (Ironwood) activation. This must agree with BOTH misc/zebra.toml and +# the hardcoded regtest parameters in rust/src/api/coin.rs (nu6_3: 250) — the +# wallet picks its consensus branch id from its own copy, so a chain that +# disagrees rejects every transaction it builds. +NU6_3_HEIGHT = int(os.getenv("NU6_3_HEIGHT", "250")) +# Owns the coinbase: matches miner_address in misc/zebra.toml. +MINER_SEED = os.getenv( + "MINER_SEED", + "burger voice warrior danger satoshi you solid atom elite alcohol category " + "layer able debate culture talk tissue language hip surge fiction paddle " + "stove voyage", +) + +STEP_MIGRATION_MUTATION = gql( + """ + mutation ($account: Int!) { + stepMigration(idAccount: $account) { + event + fee + message + } + } + """ +) + +NOTES_QUERY = gql( + """ + query ($account: Int!) { + notesByAccount(idAccount: $account) { + pool + value + } + } + """ +) + +PAY_FROM_COINBASE_MUTATION = gql( + """ + mutation ($account: Int!, $address: String!, $amount: BigDecimal!, $confirmations: Int!) { + pay( + idAccount: $account + payment: { + recipients: [{address: $address, amount: $amount}] + srcPools: 1 + confirmations: $confirmations + } + ) + } + """ +) + + +def _missing(reason: str): + """Fail in CI, skip locally: a missing prerequisite must never be green.""" + if os.getenv("CI"): + pytest.fail(f"prerequisite not met: {reason}") + pytest.skip(reason) + + +def is_iw_sd(value: int) -> bool: + """A pure standard denomination, 10^k for k >= 5 — mirrors crate::migrate::is_iw_sd. + + Ironwood notes are minted at the bare denomination; the SD_FEE_PAD an + Orchard SD note carried is consumed by the hop that mints it. + """ + if value < 100_000 or value % 100_000: + return False + x = value // 100_000 + while x % 10 == 0: + x //= 10 + return x == 1 + + +async def assert_migrated( + client, account_id: int, funded: int, steps: list[tuple[str, int]], label: str +): + """Check the shape of a finished migration, not just that it finished.""" + fees = sum(fee for _, fee in steps) + ironwood_notes = await pool_note_values(client, account_id, pool=3) + leftover_notes = await orchard_zec_values(client, account_id) + ironwood = sum(ironwood_notes) + leftover = sum(leftover_notes) + print(f"{label}: ironwood={ironwood_notes} leftover={leftover_notes} fees={fees}") + + # Ironwood notes exist afterwards, each at a standard denomination. + assert ironwood_notes, f"{label}: no Ironwood notes after migration" + for value in ironwood_notes: + assert is_iw_sd(value), f"{label}: Ironwood note {value} is not a denomination" + + # Whatever is left in Orchard is below the threshold worth splitting. + assert leftover < MIN_SD, f"{label}: {leftover} zats still migratable in Orchard" + + # Migration was not expensive. Each O→I hop is prefunded by the SD_FEE_PAD + # baked into its note, so it must cost exactly that; the split is the only + # step whose fee varies with the wallet's shape. + for event, fee in steps: + if event == "MigrateComplete": + assert fee == SD_FEE_PAD, f"{label}: O→I cost {fee}, expected {SD_FEE_PAD}" + assert fees < funded * MAX_FEE_FRACTION, ( + f"{label}: migration spent {fees} of {funded} " + f"({fees / funded:.1%}, limit {MAX_FEE_FRACTION:.0%})" + ) + + # Nothing lost, nothing invented. + assert ironwood + leftover + fees == funded, ( + f"{label}: {ironwood} + {leftover} + {fees} != {funded} funded " + f"(off by {ironwood + leftover + fees - funded})" + ) + + +async def orchard_zec_values(client, account_id: int) -> list[int]: + return await pool_note_values(client, account_id, pool=2) + + +async def pool_note_values(client, account_id: int, pool: int) -> list[int]: + """Unspent ZEC note values in `pool` (2 = Orchard, 3 = Ironwood), in zats. + + `notesByAccount` reports values in ZEC, not zats. It exposes no asset + field to filter ZSA notes by, but ZSA is NU7 and cannot be active on an + Ironwood (NU6.3) chain, so pool 2 here is always ZEC. + """ + result = await client.execute_async( + GraphQLRequest(NOTES_QUERY, variable_values={"account": account_id}) + ) + return [ + round(float(n["value"]) * ZATS_PER_ZEC) + for n in result["notesByAccount"] + if int(n["pool"]) == pool + ] + + +async def fund_orchard(client, rpc_url: str, miner_id: int, address: str, amount: str): + """Pay `amount` from mature coinbase and confirm it.""" + height = await get_current_height(client) + result = await client.execute_async( + GraphQLRequest( + PAY_FROM_COINBASE_MUTATION, + variable_values={ + "account": miner_id, + "address": address, + "amount": amount, + "confirmations": MATURITY, + }, + ) + ) + # `pay` reports broadcast failures in its String result rather than as a + # GraphQL error, so a txid is the only success signal. + txid = result["pay"] + assert "failed" not in txid.lower(), f"pay failed: {txid}" + await mine_blocks(rpc_url, 3) + await wait_for_blocks(client, height, 3) + # Re-sync the payer, or the next payment reselects the UTXO just spent. + await sync_account(client, miner_id) + + +async def mine_to_anchor_boundary(client, rpc_url: str) -> int: + """Mine so the tip lands exactly on an anchor boundary, and return it. + + An O→I is only built when the wallet checkpoint sits on a shared boundary, + so a caller syncs immediately after this. + """ + height = await get_current_height(client) + remainder = height % ANCHOR_BUCKET_SIZE + needed = ANCHOR_BUCKET_SIZE - remainder if remainder else 0 + if needed: + await mine_blocks(rpc_url, needed) + await wait_for_blocks(client, height, needed) + boundary = await get_current_height(client) + assert boundary % ANCHOR_BUCKET_SIZE == 0, f"tip {boundary} is not a boundary" + return boundary + + +async def drive_migration( + client, rpc_url: str, account_id: int, max_steps: int = 40 +) -> list[tuple[str, int]]: + """Run the migration to completion, returning (event, fee) per step. + + Between steps this does what the app's autosync would: park the wallet on + an anchor boundary, sync, and confirm each broadcast. + """ + steps: list[tuple[str, int]] = [] + + for _ in range(max_steps): + boundary = await mine_to_anchor_boundary(client, rpc_url) + await sync_account(client, account_id) + + result = await client.execute_async( + GraphQLRequest(STEP_MIGRATION_MUTATION, variable_values={"account": account_id}) + ) + step = result["stepMigration"] + event = step["event"] + steps.append((event, step["fee"] or 0)) + print(f" step -> {event} (fee={step['fee']}) at boundary {boundary}") + + if event == "Complete": + return steps + if event == "Error": + pytest.fail(f"migration reported an error: {step['message']}") + if event in ("SplitComplete", "MigrateComplete"): + height = await get_current_height(client) + await mine_blocks(rpc_url, 3) + await wait_for_blocks(client, height, 3) + await sync_account(client, account_id) + + pytest.fail(f"migration did not finish in {max_steps} steps: {[e for e, _ in steps]}") + + +@pytest.mark.asyncio +async def test_migration_orchard_to_ironwood(gql_client_factory, rpc_url, zkool_binary, lwd_url): + """Orchard notes split into standard denominations and migrate to Ironwood. + + Covers two subjects on one chain: + + 1. A wallet with an ordinary Orchard balance migrates and terminates. + 2. A wallet whose Orchard total lands in [MIN_SD, MIN_SD + SD_MIN_DENOM) + also splits. A flat MIN_SD fee reserve used to be subtracted before + denominating, which removed every planned output for totals in that + window: no split was broadcast, no note was spent, and the runner span + forever on an unchanging wallet while reporting the splitting phase. + """ + # A skip is a green build. Anything that means the fixture is wrong must + # fail in CI rather than quietly passing. + if not os.path.exists(zkool_binary): + _missing(f"zkool_graphql binary not found at {zkool_binary}") + + PORT = 8003 + DB_PATH = "/tmp/regtest_migration.db" + LOG_PATH = "/tmp/graphql_migration.log" + GRAPHQL_URL = f"http://localhost:{PORT}/graphql" + process = None + + try: + await kill_existing_zkool_processes() + cleanup_test_files(DB_PATH, LOG_PATH) + process = await start_zkool_instance( + zkool_binary, DB_PATH, PORT, lwd_url, LOG_PATH, coin=REGTEST_COIN + ) + assert process.poll() is None, "zkool_graphql failed to start" + + async with gql_client_factory(GRAPHQL_URL) as client: + height = await get_current_height(client) + if height >= NU6_3_HEIGHT: + _missing( + f"chain is at {height}, past NU6.3 activation ({NU6_3_HEIGHT}): " + "Orchard can no longer be funded. Bring the chain up with " + "BLOCKS below the activation height." + ) + assert height > MATURITY, f"need mature coinbase, chain is only at {height}" + + print("\n=== Fund in Orchard, before Ironwood activates ===") + miner_id = await create_account(client, "Miner", key=MINER_SEED) + await sync_account(client, miner_id) + miner_balance = await get_balance(client, miner_id, pool="transparent") + print(f"Miner coinbase: {miner_balance}") + assert float(miner_balance) > 0, "miner has no coinbase to spend" + + ordinary_id = await create_account(client, "Ordinary", key="") + dead_zone_id = await create_account(client, "DeadZone", key="") + + # 0.0055 ZEC = 550_000 zats decomposes to 4 x 120_000 with 70_000 + # left over: the exact shape from the reported stall. + for account_id, amount in ((ordinary_id, "0.05"), (dead_zone_id, "0.0055")): + address = await get_address(client, account_id, pool="orchard") + await fund_orchard(client, rpc_url, miner_id, address, amount) + await sync_account(client, account_id) + + ordinary_notes = await orchard_zec_values(client, ordinary_id) + dead_zone_notes = await orchard_zec_values(client, dead_zone_id) + print(f"Ordinary Orchard notes: {ordinary_notes}") + print(f"Dead-zone Orchard notes: {dead_zone_notes}") + + # Orchard notes exist before migration — otherwise there is + # nothing to migrate and every later check is vacuous. + assert ordinary_notes, "funding did not land in Orchard" + assert dead_zone_notes, "dead-zone funding did not land in Orchard" + dead_zone_total = sum(dead_zone_notes) + assert MIN_SD <= dead_zone_total < MIN_SD + SD_MIN_DENOM, ( + f"total {dead_zone_total} is outside the dead zone; adjust the amount" + ) + + print(f"\n=== Mine past NU6.3 activation ({NU6_3_HEIGHT}) ===") + height = await get_current_height(client) + needed = NU6_3_HEIGHT - height + 1 + await mine_blocks(rpc_url, needed) + await wait_for_blocks(client, height, needed) + print(f"Height now {await get_current_height(client)}") + + print("\n=== Subject 1: ordinary balance ===") + steps = await drive_migration(client, rpc_url, ordinary_id) + events = [event for event, _ in steps] + print(f"Events: {events}") + assert "SplitComplete" in events, "no split was ever built" + assert "MigrateComplete" in events, "nothing reached Ironwood" + assert events[-1] == "Complete" + await assert_migrated(client, ordinary_id, sum(ordinary_notes), steps, "ordinary") + + print("\n=== Subject 2: dead zone [500_000, 620_000) ===") + steps = await drive_migration(client, rpc_url, dead_zone_id) + events = [event for event, _ in steps] + print(f"Events: {events}") + assert "SplitComplete" in events, "dead-zone total planned no split" + assert "MigrateComplete" in events, "dead-zone split never reached Ironwood" + assert events[-1] == "Complete", "migration did not terminate" + await assert_migrated(client, dead_zone_id, dead_zone_total, steps, "dead-zone") + except Exception: + dump_server_log(LOG_PATH, "MIGRATION SERVER LOG") + raise + finally: + if process: + await stop_zkool_instance(process) + cleanup_test_files(DB_PATH, LOG_PATH) diff --git a/tests/tests/utils.py b/tests/tests/utils.py index 6659258f3..6e887d928 100644 --- a/tests/tests/utils.py +++ b/tests/tests/utils.py @@ -38,12 +38,15 @@ async def wait_for_blocks(client, start_height: int, num_blocks: int): await asyncio.sleep(1) -async def mine_blocks(rpc_url: str, num_blocks: int): +async def mine_blocks(rpc_url: str, num_blocks: int, timeout: float = 300.0): """Mine blocks using the RPC endpoint. Args: rpc_url: RPC endpoint URL num_blocks: Number of blocks to mine + timeout: Request timeout in seconds. The default httpx timeout of 5s + is only enough for a handful of blocks; generating a hundred to + cross an activation height takes considerably longer. Returns: RPC response @@ -54,7 +57,7 @@ async def mine_blocks(rpc_url: str, num_blocks: int): "method": "generate", "params": [num_blocks], } - async with httpx.AsyncClient() as client: + async with httpx.AsyncClient(timeout=timeout) as client: response = await client.post(rpc_url, json=payload) response.raise_for_status() return response.json() @@ -93,6 +96,7 @@ async def start_zkool_instance( lwd_url: str, log_path: str | None = None, zebra: bool = False, + coin: int | None = None, ) -> subprocess.Popen: """Start a zkool_graphql instance. @@ -103,6 +107,9 @@ async def start_zkool_instance( lwd_url: Light wallet daemon URL (or zebra RPC URL when zebra=True) log_path: Optional path for log file zebra: If True, use zebra JSON-RPC backend instead of lightwalletd gRPC + coin: 0=mainnet, 1=testnet, 2=regtest, 3=ZSA regtest. When omitted the + server infers the network from the database filename, so pass it + explicitly rather than relying on db_path containing "regtest". Returns: Subprocess object @@ -121,6 +128,8 @@ async def start_zkool_instance( cmd = [zkool_binary, "-d", db_path, "-p", str(port), "-l", lwd_url] if zebra: cmd.append("--zebra") + if coin is not None: + cmd += ["-C", str(coin)] process = subprocess.Popen( cmd, From 623ded005f7eb6b8aa448ff1247ad5b4c3a41103 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Mon, 31 Aug 2026 10:08:27 +0800 Subject: [PATCH 137/189] feat(frost): drive DKG and signing from autosync instead of self-syncing (#1236) Refactor the DKG rounds into a plan/step/exec/state pipeline (mirroring the note migration) and make both do_dkg and do_sign depend on the wallet's autosync rather than syncing themselves. - do_dkg/do_sign no longer call sync_frost_accounts/synchronize_impl; the Flutter pages force a sync per block and then step, and the headless server keeps syncing in graphql::frost::new_block. - A publish that cannot be funded yet (the previous round's change is not mined) is surfaced as a WaitingForFunds warning and retried on the next block instead of hard-failing. The broadcast-time note lock, released only once the spend is mined, keeps this safe from double-spends. - The DKG/FROST pages replace the 30s timer with a block-height subscription, serialize passes to avoid overlapping publishes, and drop the frostInProgress autosync guard. - plan_transaction returns a typed NoFeasibleSelection error so the FROST path can treat it as transient while normal pay still reports it as insufficient funds. Adds a 2-of-3 headless DKG test. --- lib/pages/dkg.dart | 165 ++++++------ lib/pages/frost.dart | 176 +++++++------ lib/src/rust/api/frost.dart | 32 ++- lib/src/rust/api/frost.freezed.dart | 79 ++++++ lib/src/rust/api/migrate.dart | 3 +- lib/src/rust/api/pay.dart | 6 + lib/src/rust/api/sync.dart | 8 + lib/src/rust/frb_generated.dart | 34 ++- lib/store.dart | 6 - rust/src/api/frost.rs | 134 ++++++---- rust/src/db.rs | 8 + rust/src/frb_generated.rs | 40 ++- rust/src/frost/dkg/exec.rs | 357 ++++++++++++++++++++++++++ rust/src/frost/{dkg.rs => dkg/mod.rs} | 319 ++--------------------- rust/src/frost/dkg/plan.rs | 210 +++++++++++++++ rust/src/frost/dkg/state.rs | 286 +++++++++++++++++++++ rust/src/frost/dkg/step.rs | 148 +++++++++++ rust/src/frost/dkg/task.rs | 83 ++++++ rust/src/frost/mod.rs | 4 +- rust/src/frost/protocol.rs | 150 +++++------ rust/src/frost/sign.rs | 48 +++- rust/src/graphql/frost.rs | 33 +-- rust/src/pay/error.rs | 6 + rust/src/pay/plan.rs | 16 +- tests/tests/test_dkg_2_of_3.py | 321 +++++++++++++++++++++++ 25 files changed, 2005 insertions(+), 667 deletions(-) create mode 100644 rust/src/frost/dkg/exec.rs rename rust/src/frost/{dkg.rs => dkg/mod.rs} (66%) create mode 100644 rust/src/frost/dkg/plan.rs create mode 100644 rust/src/frost/dkg/state.rs create mode 100644 rust/src/frost/dkg/step.rs create mode 100644 rust/src/frost/dkg/task.rs create mode 100644 tests/tests/test_dkg_2_of_3.py diff --git a/lib/pages/dkg.dart b/lib/pages/dkg.dart index 5156aa96c..44afbca51 100644 --- a/lib/pages/dkg.dart +++ b/lib/pages/dkg.dart @@ -318,30 +318,48 @@ class DKGPage3 extends ConsumerStatefulWidget { class DKGPage3State extends ConsumerState<DKGPage3> { late final c = coinContext.coin; - late final SynchronizerNotifier _synchronizer; + // Held in a field because `ref` is unsafe to use once the widget is disposed. + late final SynchronizerNotifier _synchronizer = + ref.read(synchronizerProvider.notifier); String message = ""; int index = 0; - Timer? runTimer; + StreamSubscription<int>? _heightSub; + int? _lastStepHeight; + // Guards against overlapping passes: a slow sync+step must finish before the + // next block starts another, or two `doDkg` runs would each publish the same + // round and double-spend the funding note. + bool _stepping = false; bool finished = false; @override void initState() { super.initState(); - // doDkg syncs the DKG accounts itself; keep autosync off the same database - // while the rounds run. The notifier is held in a field because `ref` is - // unsafe to use from dispose(). - _synchronizer = ref.read(synchronizerProvider.notifier); - _synchronizer.frostInProgress = true; - runTimer = Timer.periodic(const Duration(seconds: 30), (_) async { - await runDkg(); + // `doDkg` no longer syncs itself; it steps against what is already synced. + // Drive the wallet's synchronizer once per block and then step, rather than + // on a fixed timer: the block-height stream delivers the current tip on + // subscribe (kicking off round 0) and then only on changes. A round waiting + // for its own change to confirm defers to the next block, so + // `_lastStepHeight` guards against stepping the same height twice — keeping + // the "waiting for funds" warning to at most once per block. + _heightSub = blockHeightService.heights.listen((height) async { + if (_stepping || _lastStepHeight == height) return; + _stepping = true; + _lastStepHeight = height; + try { + // Force a sync of the funding and internal frost accounts (which stores + // the incoming package memos), then step against the fresh state. + await _synchronizer.syncIfNeeded(height, now: true); + if (!mounted) return; + await runDkg(); + } finally { + _stepping = false; + } }); - unawaited(runDkg()); } @override void dispose() { - runTimer?.cancel(); - _synchronizer.frostInProgress = false; + unawaited(_heightSub?.cancel()); super.dispose(); } @@ -349,72 +367,67 @@ class DKGPage3State extends ConsumerState<DKGPage3> { try { await ref.read(currentHeightProvider.notifier).fetch(); - // No startSynchronize here: doDkg syncs the accounts it needs itself, so - // the rounds cannot run on notes a separate sync has not caught up on. - final status = doDkg(c: c); - status.listen( - (s) { - if (s is DKGStatus_PublishRound0Pkg) { - setState(() { - message = "Broadcasting participant keys"; - index = 0; - }); - } - if (s is DKGStatus_WaitRound0Pkg) { - setState(() { - message = "Waiting for other participants to send their keys"; - index = 0; - }); - } - if (s is DKGStatus_PublishRound1Pkg) { - setState(() { - message = "Broadcasting round 1 packages"; - index = 1; - }); - } - if (s is DKGStatus_WaitRound1Pkg) { - setState(() { - message = "Waiting for other participants to send their round 1 packages"; - index = 1; - }); - } - if (s is DKGStatus_PublishRound2Pkg) { - setState(() { - message = "Broadcasting round 2 packages"; - index = 2; - }); - } - if (s is DKGStatus_WaitRound2Pkg) { - setState(() { - message = "Waiting for other participants to send their round 2 packages"; - index = 2; - }); - } - if (s is DKGStatus_Finalize) { - setState(() { - message = "Deriving the shared key"; - index = 3; - }); - } - if (s is DKGStatus_SharedAddress) { - final sharedUA = s.field0; - ref.invalidate(getAccountsProvider); - setState(() { - message = "The shared address is: $sharedUA"; - index = 3; - finished = true; - }); - } - }, - onError: (Object e) async { - final exc = e as AnyhowException; - if (!context.mounted) return; - // Transient: the 30s timer retries, so warn instead of a modal error. - showWarningSnackbar(exc.message); - }, - ); + // No startSynchronize here: the block-height handler syncs first, and + // doDkg steps against what is already synced. Await the stream to + // completion so the handler serializes passes — overlapping doDkg runs + // would each publish the same round and double-spend the funding note. + await for (final s in doDkg(c: c)) { + if (!mounted) return; + if (s is DKGStatus_PublishRound0Pkg) { + setState(() { + message = "Broadcasting participant keys"; + index = 0; + }); + } else if (s is DKGStatus_WaitRound0Pkg) { + setState(() { + message = "Waiting for other participants to send their keys"; + index = 0; + }); + } else if (s is DKGStatus_PublishRound1Pkg) { + setState(() { + message = "Broadcasting round 1 packages"; + index = 1; + }); + } else if (s is DKGStatus_WaitRound1Pkg) { + setState(() { + message = "Waiting for other participants to send their round 1 packages"; + index = 1; + }); + } else if (s is DKGStatus_PublishRound2Pkg) { + setState(() { + message = "Broadcasting round 2 packages"; + index = 2; + }); + } else if (s is DKGStatus_WaitRound2Pkg) { + setState(() { + message = "Waiting for other participants to send their round 2 packages"; + index = 2; + }); + } else if (s is DKGStatus_WaitingForFunds) { + // The previous round's change is not mined yet, so this round's + // publish has nothing to spend. The next block retries; surface it + // as a warning rather than failing so the user knows why it paused. + showWarningSnackbar( + "Waiting for the previous round's change to be confirmed…", + ); + } else if (s is DKGStatus_Finalize) { + setState(() { + message = "Deriving the shared key"; + index = 3; + }); + } else if (s is DKGStatus_SharedAddress) { + final sharedUA = s.field0; + ref.invalidate(getAccountsProvider); + setState(() { + message = "The shared address is: $sharedUA"; + index = 3; + finished = true; + }); + } + } } on AnyhowException catch (e) { if (!context.mounted) return; + // Transient: the next block retries, so warn instead of a modal error. showWarningSnackbar(e.message); } } diff --git a/lib/pages/frost.dart b/lib/pages/frost.dart index 30d29e781..bcd1a887f 100644 --- a/lib/pages/frost.dart +++ b/lib/pages/frost.dart @@ -187,30 +187,47 @@ class FrostPage2 extends ConsumerStatefulWidget { class FrostPage2State extends ConsumerState<FrostPage2> { late final c = coinContext.coin; - late final SynchronizerNotifier _synchronizer; + // Held in a field because `ref` is unsafe to use once the widget is disposed. + late final SynchronizerNotifier _synchronizer = + ref.read(synchronizerProvider.notifier); String message = ""; - Timer? timer; + StreamSubscription<int>? _heightSub; + int? _lastStepHeight; + // Guards against overlapping passes: a slow sync+step must finish before the + // next block starts another, or two `doSign` runs would each spend the same + // funding note and double-spend. + bool _stepping = false; int currentIndex = 0; bool finished = false; @override void initState() { super.initState(); - // doSign syncs the accounts it needs; keep autosync off the same database - // while the rounds run. The notifier is held in a field because `ref` is - // unsafe to use from dispose(). - _synchronizer = ref.read(synchronizerProvider.notifier); - _synchronizer.frostInProgress = true; - runFrost(); - timer = Timer.periodic(Duration(seconds: 30), (_) async { - runFrost(); + // `doSign` no longer syncs itself; it steps against what is already synced. + // Drive the wallet's synchronizer once per block and then step: the + // block-height stream delivers the current tip on subscribe (kicking off + // the first round) and then only on changes. A message waiting for its + // change to confirm defers to the next block, so `_lastStepHeight` guards + // against stepping the same height twice. + _heightSub = blockHeightService.heights.listen((height) async { + if (_stepping || _lastStepHeight == height) return; + _stepping = true; + _lastStepHeight = height; + try { + // Force a sync of the funding and internal frost accounts (which stores + // the incoming message memos), then step against the fresh state. + await _synchronizer.syncIfNeeded(height, now: true); + if (!mounted) return; + await runFrost(); + } finally { + _stepping = false; + } }); } @override void dispose() { - timer?.cancel(); - _synchronizer.frostInProgress = false; + unawaited(_heightSub?.cancel()); super.dispose(); } @@ -226,77 +243,80 @@ class FrostPage2State extends ConsumerState<FrostPage2> { ); } - void runFrost() async { + Future<void> runFrost() async { try { await ref.read(currentHeightProvider.notifier).fetch(); - // No startSynchronize here: doSign syncs the accounts it needs itself. - final status = doSign(c: c); - status.listen( - (s) { - if (s is SigningStatus_WaitingForCommitments) { - setState(() { - message = "Waiting for other participants to send their commitments"; - currentIndex = 1; // coordinator - }); - } else if (s is SigningStatus_SendingCommitment) { - setState(() { - message = "Sending our commitments to the coordinator"; - currentIndex = 1; // other - }); - } else if (s is SigningStatus_SendingSigningPackage) { - setState(() { - message = "Broadcasting the signing package to all participants"; - currentIndex = 2; // coordinator - }); - } else if (s is SigningStatus_WaitingForSigningPackage) { - setState(() { - message = "Waiting for the signing package from the coordinator"; - currentIndex = 2; // other - }); - } else if (s is SigningStatus_SendingSignatureShare) { - setState(() { - message = "Sending our signature share to the coordinator"; - currentIndex = 3; // other - }); - } else if (s is SigningStatus_SigningCompleted) { - setState(() { - message = "Signing completed"; - currentIndex = 3; // other - finished = true; - }); - } else if (s is SigningStatus_WaitingForSignatureShares) { - setState(() { - message = "Waiting for the signature share from the other participants"; - currentIndex = 2; // coordinator - }); - } else if (s is SigningStatus_PreparingTransaction) { - setState(() { - message = "Assembling the transaction"; - currentIndex = 3; // coordinator - }); - } else if (s is SigningStatus_SendingTransaction) { - setState(() { - message = "Sending the transaction to the network"; - currentIndex = 3; // coordinator - }); - } else if (s is SigningStatus_TransactionSent) { - setState(() { - message = "TX ID: ${s.field0}"; - currentIndex = 3; // coordinator - finished = true; - }); - } - }, - onError: (e) async { - final exc = e as AnyhowException; - if (!context.mounted) return; - // Transient: the 30s timer retries, so warn instead of a modal error. - showWarningSnackbar(exc.message); - }, - ); + // No startSynchronize here: the block-height handler syncs first, and + // doSign steps against what is already synced. Await the stream to + // completion so the handler serializes passes — overlapping doSign runs + // would each spend the same funding note and double-spend. + await for (final s in doSign(c: c)) { + if (!mounted) return; + if (s is SigningStatus_WaitingForCommitments) { + setState(() { + message = "Waiting for other participants to send their commitments"; + currentIndex = 1; // coordinator + }); + } else if (s is SigningStatus_SendingCommitment) { + setState(() { + message = "Sending our commitments to the coordinator"; + currentIndex = 1; // other + }); + } else if (s is SigningStatus_SendingSigningPackage) { + setState(() { + message = "Broadcasting the signing package to all participants"; + currentIndex = 2; // coordinator + }); + } else if (s is SigningStatus_WaitingForSigningPackage) { + setState(() { + message = "Waiting for the signing package from the coordinator"; + currentIndex = 2; // other + }); + } else if (s is SigningStatus_SendingSignatureShare) { + setState(() { + message = "Sending our signature share to the coordinator"; + currentIndex = 3; // other + }); + } else if (s is SigningStatus_SigningCompleted) { + setState(() { + message = "Signing completed"; + currentIndex = 3; // other + finished = true; + }); + } else if (s is SigningStatus_WaitingForSignatureShares) { + setState(() { + message = "Waiting for the signature share from the other participants"; + currentIndex = 2; // coordinator + }); + } else if (s is SigningStatus_PreparingTransaction) { + setState(() { + message = "Assembling the transaction"; + currentIndex = 3; // coordinator + }); + } else if (s is SigningStatus_SendingTransaction) { + setState(() { + message = "Sending the transaction to the network"; + currentIndex = 3; // coordinator + }); + } else if (s is SigningStatus_TransactionSent) { + setState(() { + message = "TX ID: ${s.field0}"; + currentIndex = 3; // coordinator + finished = true; + }); + } else if (s is SigningStatus_WaitingForFunds) { + // The previous message's change is not mined yet, so this one has + // nothing to spend. The next block retries; surface it as a warning + // rather than failing. + showWarningSnackbar( + "Waiting for the previous message's change to be confirmed…", + ); + } + } } on AnyhowException catch (e) { if (!context.mounted) return; + // Transient: the next block retries, so warn instead of a modal error. showWarningSnackbar(e.message); } } diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index cc43cb4f6..1325efab6 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -11,7 +11,7 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; import 'pay.dart'; part 'frost.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `get_funding_account` +// These functions are ignored because they are not marked as `pub`: `dkg_status_for`, `get_funding_account`, `sync_frost_accounts` // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DKGParams` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt` @@ -34,6 +34,20 @@ Future<void> initDkg({required Coin c}) => Future<bool> hasDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgAddresses(c: c); +/// Advance the DKG by one pass. Does **not** synchronize. +/// +/// Like the note migration, the DKG depends on the wallet's autosync to advance +/// the funding and internal frost accounts; the step runs against whatever is +/// already synced. Syncing was moved out because it must not race the rounds and +/// autosync already drives the chain forward — the caller retries this on each +/// new block (`lib/pages/dkg.dart`), and the headless server steps from +/// `graphql::frost::new_block`, which syncs first. +/// +/// Each pass executes every effect the planner names until it hits a wait — +/// one precondition-checked effect at a time. Statuses arrive after the pass, +/// one per executed task plus the wait it stopped on. A publish that cannot be +/// funded yet (previous round's change not mined) ends the pass with a +/// [`DKGStatus::WaitingForFunds`] warning rather than an error. Stream<DKGStatus> doDkg({required Coin c}) => RustLib.instance.api.crateApiFrostDoDkg(c: c); @@ -65,6 +79,13 @@ Future<void> initSign( Future<bool> isSigningInProgress({required Coin c}) => RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); +/// Advance the signing rounds by one step. Does **not** synchronize. +/// +/// Like [`do_dkg`], signing depends on the wallet's autosync to advance the +/// funding and internal frost accounts; the step runs against what is already +/// synced and the caller retries on each new block. A signing message that +/// cannot be funded yet ends the step with a [`SigningStatus::WaitingForFunds`] +/// warning rather than an error. Stream<SigningStatus> doSign({required Coin c}) => RustLib.instance.api.crateApiFrostDoSign(c: c); @@ -85,6 +106,11 @@ sealed class DKGStatus with _$DKGStatus { const factory DKGStatus.waitRound1Pkg() = DKGStatus_WaitRound1Pkg; const factory DKGStatus.publishRound2Pkg() = DKGStatus_PublishRound2Pkg; const factory DKGStatus.waitRound2Pkg() = DKGStatus_WaitRound2Pkg; + + /// A round's package could not be funded yet: the note spent for the + /// previous round is locked and its change is not mined. Transient — the + /// next block retries. Shown as an info/warning, not an error. + const factory DKGStatus.waitingForFunds() = DKGStatus_WaitingForFunds; const factory DKGStatus.finalize() = DKGStatus_Finalize; const factory DKGStatus.sharedAddress( String field0, @@ -121,6 +147,10 @@ sealed class SigningStatus with _$SigningStatus { SigningStatus_SigningCompleted; const factory SigningStatus.waitingForSignatureShares() = SigningStatus_WaitingForSignatureShares; + + /// A signing message could not be funded yet (previous broadcast's change + /// not mined). Transient — the next block retries. Info/warning, not error. + const factory SigningStatus.waitingForFunds() = SigningStatus_WaitingForFunds; const factory SigningStatus.preparingTransaction() = SigningStatus_PreparingTransaction; const factory SigningStatus.sendingTransaction() = diff --git a/lib/src/rust/api/frost.freezed.dart b/lib/src/rust/api/frost.freezed.dart index 50b8b77b4..f9716eaec 100644 --- a/lib/src/rust/api/frost.freezed.dart +++ b/lib/src/rust/api/frost.freezed.dart @@ -58,6 +58,7 @@ extension DKGStatusPatterns on DKGStatus { TResult Function(DKGStatus_WaitRound1Pkg value)? waitRound1Pkg, TResult Function(DKGStatus_PublishRound2Pkg value)? publishRound2Pkg, TResult Function(DKGStatus_WaitRound2Pkg value)? waitRound2Pkg, + TResult Function(DKGStatus_WaitingForFunds value)? waitingForFunds, TResult Function(DKGStatus_Finalize value)? finalize, TResult Function(DKGStatus_SharedAddress value)? sharedAddress, required TResult orElse(), @@ -80,6 +81,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(_that); case DKGStatus_WaitRound2Pkg() when waitRound2Pkg != null: return waitRound2Pkg(_that); + case DKGStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(_that); case DKGStatus_Finalize() when finalize != null: return finalize(_that); case DKGStatus_SharedAddress() when sharedAddress != null: @@ -115,6 +118,7 @@ extension DKGStatusPatterns on DKGStatus { required TResult Function(DKGStatus_PublishRound2Pkg value) publishRound2Pkg, required TResult Function(DKGStatus_WaitRound2Pkg value) waitRound2Pkg, + required TResult Function(DKGStatus_WaitingForFunds value) waitingForFunds, required TResult Function(DKGStatus_Finalize value) finalize, required TResult Function(DKGStatus_SharedAddress value) sharedAddress, }) { @@ -136,6 +140,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(_that); case DKGStatus_WaitRound2Pkg(): return waitRound2Pkg(_that); + case DKGStatus_WaitingForFunds(): + return waitingForFunds(_that); case DKGStatus_Finalize(): return finalize(_that); case DKGStatus_SharedAddress(): @@ -165,6 +171,7 @@ extension DKGStatusPatterns on DKGStatus { TResult? Function(DKGStatus_WaitRound1Pkg value)? waitRound1Pkg, TResult? Function(DKGStatus_PublishRound2Pkg value)? publishRound2Pkg, TResult? Function(DKGStatus_WaitRound2Pkg value)? waitRound2Pkg, + TResult? Function(DKGStatus_WaitingForFunds value)? waitingForFunds, TResult? Function(DKGStatus_Finalize value)? finalize, TResult? Function(DKGStatus_SharedAddress value)? sharedAddress, }) { @@ -186,6 +193,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(_that); case DKGStatus_WaitRound2Pkg() when waitRound2Pkg != null: return waitRound2Pkg(_that); + case DKGStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(_that); case DKGStatus_Finalize() when finalize != null: return finalize(_that); case DKGStatus_SharedAddress() when sharedAddress != null: @@ -217,6 +226,7 @@ extension DKGStatusPatterns on DKGStatus { TResult Function()? waitRound1Pkg, TResult Function()? publishRound2Pkg, TResult Function()? waitRound2Pkg, + TResult Function()? waitingForFunds, TResult Function()? finalize, TResult Function(String field0)? sharedAddress, required TResult orElse(), @@ -239,6 +249,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(); case DKGStatus_WaitRound2Pkg() when waitRound2Pkg != null: return waitRound2Pkg(); + case DKGStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(); case DKGStatus_Finalize() when finalize != null: return finalize(); case DKGStatus_SharedAddress() when sharedAddress != null: @@ -271,6 +283,7 @@ extension DKGStatusPatterns on DKGStatus { required TResult Function() waitRound1Pkg, required TResult Function() publishRound2Pkg, required TResult Function() waitRound2Pkg, + required TResult Function() waitingForFunds, required TResult Function() finalize, required TResult Function(String field0) sharedAddress, }) { @@ -292,6 +305,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(); case DKGStatus_WaitRound2Pkg(): return waitRound2Pkg(); + case DKGStatus_WaitingForFunds(): + return waitingForFunds(); case DKGStatus_Finalize(): return finalize(); case DKGStatus_SharedAddress(): @@ -321,6 +336,7 @@ extension DKGStatusPatterns on DKGStatus { TResult? Function()? waitRound1Pkg, TResult? Function()? publishRound2Pkg, TResult? Function()? waitRound2Pkg, + TResult? Function()? waitingForFunds, TResult? Function()? finalize, TResult? Function(String field0)? sharedAddress, }) { @@ -342,6 +358,8 @@ extension DKGStatusPatterns on DKGStatus { return publishRound2Pkg(); case DKGStatus_WaitRound2Pkg() when waitRound2Pkg != null: return waitRound2Pkg(); + case DKGStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(); case DKGStatus_Finalize() when finalize != null: return finalize(); case DKGStatus_SharedAddress() when sharedAddress != null: @@ -570,6 +588,27 @@ class DKGStatus_WaitRound2Pkg extends DKGStatus { /// @nodoc +class DKGStatus_WaitingForFunds extends DKGStatus { + const DKGStatus_WaitingForFunds() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is DKGStatus_WaitingForFunds); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'DKGStatus.waitingForFunds()'; + } +} + +/// @nodoc + class DKGStatus_Finalize extends DKGStatus { const DKGStatus_Finalize() : super._(); @@ -1028,6 +1067,7 @@ extension SigningStatusPatterns on SigningStatus { TResult Function(SigningStatus_SigningCompleted value)? signingCompleted, TResult Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, + TResult Function(SigningStatus_WaitingForFunds value)? waitingForFunds, TResult Function(SigningStatus_PreparingTransaction value)? preparingTransaction, TResult Function(SigningStatus_SendingTransaction value)? @@ -1056,6 +1096,8 @@ extension SigningStatusPatterns on SigningStatus { case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(_that); + case SigningStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(_that); case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(_that); @@ -1097,6 +1139,8 @@ extension SigningStatusPatterns on SigningStatus { signingCompleted, required TResult Function(SigningStatus_WaitingForSignatureShares value) waitingForSignatureShares, + required TResult Function(SigningStatus_WaitingForFunds value) + waitingForFunds, required TResult Function(SigningStatus_PreparingTransaction value) preparingTransaction, required TResult Function(SigningStatus_SendingTransaction value) @@ -1120,6 +1164,8 @@ extension SigningStatusPatterns on SigningStatus { return signingCompleted(_that); case SigningStatus_WaitingForSignatureShares(): return waitingForSignatureShares(_that); + case SigningStatus_WaitingForFunds(): + return waitingForFunds(_that); case SigningStatus_PreparingTransaction(): return preparingTransaction(_that); case SigningStatus_SendingTransaction(): @@ -1155,6 +1201,7 @@ extension SigningStatusPatterns on SigningStatus { TResult? Function(SigningStatus_SigningCompleted value)? signingCompleted, TResult? Function(SigningStatus_WaitingForSignatureShares value)? waitingForSignatureShares, + TResult? Function(SigningStatus_WaitingForFunds value)? waitingForFunds, TResult? Function(SigningStatus_PreparingTransaction value)? preparingTransaction, TResult? Function(SigningStatus_SendingTransaction value)? @@ -1182,6 +1229,8 @@ extension SigningStatusPatterns on SigningStatus { case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(_that); + case SigningStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(_that); case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(_that); @@ -1215,6 +1264,7 @@ extension SigningStatusPatterns on SigningStatus { TResult Function()? sendingSignatureShare, TResult Function()? signingCompleted, TResult Function()? waitingForSignatureShares, + TResult Function()? waitingForFunds, TResult Function()? preparingTransaction, TResult Function()? sendingTransaction, TResult Function(String field0)? transactionSent, @@ -1241,6 +1291,8 @@ extension SigningStatusPatterns on SigningStatus { case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(); + case SigningStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(); case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(); @@ -1275,6 +1327,7 @@ extension SigningStatusPatterns on SigningStatus { required TResult Function() sendingSignatureShare, required TResult Function() signingCompleted, required TResult Function() waitingForSignatureShares, + required TResult Function() waitingForFunds, required TResult Function() preparingTransaction, required TResult Function() sendingTransaction, required TResult Function(String field0) transactionSent, @@ -1295,6 +1348,8 @@ extension SigningStatusPatterns on SigningStatus { return signingCompleted(); case SigningStatus_WaitingForSignatureShares(): return waitingForSignatureShares(); + case SigningStatus_WaitingForFunds(): + return waitingForFunds(); case SigningStatus_PreparingTransaction(): return preparingTransaction(); case SigningStatus_SendingTransaction(): @@ -1325,6 +1380,7 @@ extension SigningStatusPatterns on SigningStatus { TResult? Function()? sendingSignatureShare, TResult? Function()? signingCompleted, TResult? Function()? waitingForSignatureShares, + TResult? Function()? waitingForFunds, TResult? Function()? preparingTransaction, TResult? Function()? sendingTransaction, TResult? Function(String field0)? transactionSent, @@ -1350,6 +1406,8 @@ extension SigningStatusPatterns on SigningStatus { case SigningStatus_WaitingForSignatureShares() when waitingForSignatureShares != null: return waitingForSignatureShares(); + case SigningStatus_WaitingForFunds() when waitingForFunds != null: + return waitingForFunds(); case SigningStatus_PreparingTransaction() when preparingTransaction != null: return preparingTransaction(); @@ -1512,6 +1570,27 @@ class SigningStatus_WaitingForSignatureShares extends SigningStatus { /// @nodoc +class SigningStatus_WaitingForFunds extends SigningStatus { + const SigningStatus_WaitingForFunds() : super._(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is SigningStatus_WaitingForFunds); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + String toString() { + return 'SigningStatus.waitingForFunds()'; + } +} + +/// @nodoc + class SigningStatus_PreparingTransaction extends SigningStatus { const SigningStatus_PreparingTransaction() : super._(); diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index dd7ee381a..b38200c11 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -9,7 +9,8 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'migrate.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `current_migration_status`, `do_step`, `run_migration`, `synchronize_to`, `wait_for_anchor_boundary`, `wallet_height` +// These functions are ignored because they are not marked as `pub`: `execute`, `observe_state`, `run_migration`, `sample_delay`, `status_from`, `wait_for_next_height` +// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `Executed` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` /// Single-shot step (kept for FRB generated-code compatibility). diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index 5af48ef4c..ca8eccb63 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -39,6 +39,12 @@ Future<PcztPackage> signTransaction( Future<Uint8List> extractTransaction({required PcztPackage package}) => RustLib.instance.api.crateApiPayExtractTransaction(package: package); +/// Serialize a PCZT for transport between participants. +/// +/// Uses bincode's `standard()` config so the bytes are interchangeable with +/// zkool_graphql, whose `prepareSend` / `frostSign` use the same config. The +/// two used to disagree (`legacy()` here), which made it impossible for an app +/// user and a zkool_graphql user to co-sign a FROST transaction. Future<Uint8List> packTransaction({required PcztPackage pczt}) => RustLib.instance.api.crateApiPayPackTransaction(pczt: pczt); diff --git a/lib/src/rust/api/sync.dart b/lib/src/rust/api/sync.dart index 2e19f76a8..d07d48c5e 100644 --- a/lib/src/rust/api/sync.dart +++ b/lib/src/rust/api/sync.dart @@ -40,6 +40,14 @@ Future<void> rewindSync( Future<SyncHeight> getDbHeight({required Coin c}) => RustLib.instance.api.crateApiSyncGetDbHeight(c: c); +/// Decrypt memos and store transaction details for `account`. +/// +/// Deliberately does NOT take SYNCING. It did briefly, to stop it colliding +/// with `do_dkg` — but holding the lock here let it starve the next sync, and +/// `synchronize_impl` reports a skipped sync as success, so the DKG went on to +/// build a transaction from stale notes and double-spent. Detail fetching is +/// best effort and its `database is locked` failures are self-healing; a +/// starved sync is not. Future<void> fetchTxDetails({required int account, required Coin c}) => RustLib.instance.api.crateApiSyncFetchTxDetails(account: account, c: c); diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index f6cd94276..482886d89 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -8711,8 +8711,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 7: return DKGStatus_WaitRound2Pkg(); case 8: - return DKGStatus_Finalize(); + return DKGStatus_WaitingForFunds(); case 9: + return DKGStatus_Finalize(); + case 10: return DKGStatus_SharedAddress( dco_decode_String(raw[1]), ); @@ -9691,10 +9693,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 6: return SigningStatus_WaitingForSignatureShares(); case 7: - return SigningStatus_PreparingTransaction(); + return SigningStatus_WaitingForFunds(); case 8: - return SigningStatus_SendingTransaction(); + return SigningStatus_PreparingTransaction(); case 9: + return SigningStatus_SendingTransaction(); + case 10: return SigningStatus_TransactionSent( dco_decode_String(raw[1]), ); @@ -11085,8 +11089,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 7: return DKGStatus_WaitRound2Pkg(); case 8: - return DKGStatus_Finalize(); + return DKGStatus_WaitingForFunds(); case 9: + return DKGStatus_Finalize(); + case 10: var var_field0 = sse_decode_String(deserializer); return DKGStatus_SharedAddress(var_field0); default: @@ -12409,10 +12415,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 6: return SigningStatus_WaitingForSignatureShares(); case 7: - return SigningStatus_PreparingTransaction(); + return SigningStatus_WaitingForFunds(); case 8: - return SigningStatus_SendingTransaction(); + return SigningStatus_PreparingTransaction(); case 9: + return SigningStatus_SendingTransaction(); + case 10: var var_field0 = sse_decode_String(deserializer); return SigningStatus_TransactionSent(var_field0); default: @@ -13933,10 +13941,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_32(6, serializer); case DKGStatus_WaitRound2Pkg(): sse_encode_i_32(7, serializer); - case DKGStatus_Finalize(): + case DKGStatus_WaitingForFunds(): sse_encode_i_32(8, serializer); - case DKGStatus_SharedAddress(field0: final field0): + case DKGStatus_Finalize(): sse_encode_i_32(9, serializer); + case DKGStatus_SharedAddress(field0: final field0): + sse_encode_i_32(10, serializer); sse_encode_String(field0, serializer); } } @@ -14984,12 +14994,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_32(5, serializer); case SigningStatus_WaitingForSignatureShares(): sse_encode_i_32(6, serializer); - case SigningStatus_PreparingTransaction(): + case SigningStatus_WaitingForFunds(): sse_encode_i_32(7, serializer); - case SigningStatus_SendingTransaction(): + case SigningStatus_PreparingTransaction(): sse_encode_i_32(8, serializer); - case SigningStatus_TransactionSent(field0: final field0): + case SigningStatus_SendingTransaction(): sse_encode_i_32(9, serializer); + case SigningStatus_TransactionSent(field0: final field0): + sse_encode_i_32(10, serializer); sse_encode_String(field0, serializer); } } diff --git a/lib/store.dart b/lib/store.dart index 583ed1a83..b905bdd6c 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -757,11 +757,6 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { StreamSubscription<int>? _autoSyncSubscription; bool _handlingAutoSyncHeight = false; bool _forceNextAutoSync = false; - /// While a FROST round is running, autosync must not fire: doDkg/doSign sync - /// the accounts they need themselves, and a background sync racing them - /// spawns an unawaited fetchTxDetails that writes while the rounds are - /// building a transaction — which produced double-spends from stale notes. - bool frostInProgress = false; int? _pendingAutoSyncHeight; StreamSubscription<SyncProgress>? syncProgressSubscription; int retryCount = 0; @@ -938,7 +933,6 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } void _queueAutoSync(int height, {required bool force}) { - if (frostInProgress) return; _pendingAutoSyncHeight = max(_pendingAutoSyncHeight ?? height, height); _forceNextAutoSync |= force; if (_handlingAutoSyncHeight) return; diff --git a/rust/src/api/frost.rs b/rust/src/api/frost.rs index 249842781..0c011d582 100644 --- a/rust/src/api/frost.rs +++ b/rust/src/api/frost.rs @@ -8,8 +8,11 @@ use sqlx::{query, sqlite::SqliteRow, Row, SqliteConnection}; use crate::{ api::coin::Coin, - frost::dkg::{get_dkg_params, get_mailbox_account}, + frost::dkg::{ + get_dkg_params, get_mailbox_account, task::DkgTask, + }, sync::{synchronize_impl, DEFAULT_ACTIONS_PER_SYNC}, + Sink, }; use std::str::FromStr; @@ -78,28 +81,87 @@ pub async fn has_dkg_addresses(c: &Coin) -> Result<bool> { #[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] -/// Advance the DKG by one step, syncing first. +/// Advance the DKG by one pass. Does **not** synchronize. /// -/// The sync is done here rather than by the caller so the rounds can never run -/// on stale notes. The UI used to sync separately before calling this, and that -/// sync spawned an unawaited `fetch_tx_details` which raced the rounds — see -/// `api::sync::fetch_tx_details`. This mirrors the headless path, where -/// `graphql::frost::new_block` syncs and then calls `do_dkg_impl`. +/// Like the note migration, the DKG depends on the wallet's autosync to advance +/// the funding and internal frost accounts; the step runs against whatever is +/// already synced. Syncing was moved out because it must not race the rounds and +/// autosync already drives the chain forward — the caller retries this on each +/// new block (`lib/pages/dkg.dart`), and the headless server steps from +/// `graphql::frost::new_block`, which syncs first. +/// +/// Each pass executes every effect the planner names until it hits a wait — +/// one precondition-checked effect at a time. Statuses arrive after the pass, +/// one per executed task plus the wait it stopped on. A publish that cannot be +/// funded yet (previous round's change not mined) ends the pass with a +/// [`DKGStatus::WaitingForFunds`] warning rather than an error. pub async fn do_dkg(status: StreamSink<DKGStatus>, c: &Coin) -> Result<()> { let mut connection = c.get_connection().await?; + // A completed or cancelled DKG must stay silent: the retry keeps firing + // after SharedAddress until the page is closed. + if !crate::frost::dkg::in_dkg(&mut connection).await? { + return Ok(()); + } let mut client = c.client().await?; let height = client.latest_height().await?; let account = get_funding_account(&mut connection).await?; - // The funding account pays for the memos; the internal frost-* accounts are - // the mailbox and broadcast addresses the packages arrive on. + let outcome = + crate::frost::dkg::step::dkg_step(&c.network(), &mut connection, &mut client, height, account) + .await?; + for task in &outcome.executed { + if let Some(s) = dkg_status_for(task) { + status.send(s).await; + } + } + if outcome.waiting_for_funds { + status.send(DKGStatus::WaitingForFunds).await; + } + if let Some(shared_address) = outcome.shared_address { + status.send(DKGStatus::SharedAddress(shared_address)).await; + } + Ok(()) +} + +/// Map a task to the UI status it corresponds to. Publishes and waits map to +/// their round's variants; the three finalize stages all share `Finalize`. +fn dkg_status_for(task: &DkgTask) -> Option<DKGStatus> { + match task { + DkgTask::PublishRound { round: 0 } => Some(DKGStatus::PublishRound0Pkg), + DkgTask::PublishRound { round: 1 } => Some(DKGStatus::PublishRound1Pkg), + DkgTask::PublishRound { round: 2 } => Some(DKGStatus::PublishRound2Pkg), + DkgTask::WaitRound { round: 0 } => Some(DKGStatus::WaitRound0Pkg), + DkgTask::WaitRound { round: 1 } => Some(DKGStatus::WaitRound1Pkg), + DkgTask::WaitRound { round: 2 } => Some(DKGStatus::WaitRound2Pkg), + DkgTask::FinalizeKey | DkgTask::CreateFrostAccount | DkgTask::CompleteFinalize => { + Some(DKGStatus::Finalize) + } + _ => None, + } +} + +/// Sync the funding account plus the internal frost-* accounts — the mailbox +/// and broadcast addresses the protocol messages arrive on. The funding +/// account pays for the memos. Returns the post-sync height. +/// +/// `pub(crate)`, not `pub`: it takes a `&mut SqliteConnection` that cannot cross +/// the flutter_rust_bridge boundary, and only the headless GraphQL server +/// (`graphql::frost`) drives it — the app relies on its autosync instead. Hence +/// it is unused (dead) in a flutter-only build. +#[cfg_attr(not(feature = "graphql"), allow(dead_code))] +pub(crate) async fn sync_frost_accounts( + c: &Coin, + connection: &mut SqliteConnection, + account: u32, + height: u32, +) -> Result<u32> { let mut accounts = query("SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1") .map(|r: SqliteRow| r.get::<u32, _>(0)) .fetch_all(&mut *connection) .await?; accounts.push(account); - let height = synchronize_impl( + synchronize_impl( (), accounts, height, @@ -109,21 +171,7 @@ pub async fn do_dkg(status: StreamSink<DKGStatus>, c: &Coin) -> Result<()> { false, c, ) - .await?; - - let r = crate::frost::dkg::do_dkg( - &c.network(), - &mut connection, - account, - &mut client, - height, - status.clone(), - ) - .await; - if let Err(e) = r { - let _ = status.add_error(e); - } - Ok(()) + .await } pub async fn get_dkg_addresses(c: &Coin) -> Result<Vec<String>> { @@ -178,6 +226,10 @@ pub enum DKGStatus { WaitRound1Pkg, PublishRound2Pkg, WaitRound2Pkg, + /// A round's package could not be funded yet: the note spent for the + /// previous round is locked and its change is not mined. Transient — the + /// next block retries. Shown as an info/warning, not an error. + WaitingForFunds, Finalize, SharedAddress(String), } @@ -214,35 +266,18 @@ pub async fn is_signing_in_progress(c: &Coin) -> Result<bool> { #[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] -/// Advance the signing rounds by one step, syncing first. +/// Advance the signing rounds by one step. Does **not** synchronize. /// -/// Syncs here for the same reason as [`do_dkg`]: the rounds must not run on -/// stale notes, and a caller-side sync spawns an unawaited `fetch_tx_details` -/// that races them. +/// Like [`do_dkg`], signing depends on the wallet's autosync to advance the +/// funding and internal frost accounts; the step runs against what is already +/// synced and the caller retries on each new block. A signing message that +/// cannot be funded yet ends the step with a [`SigningStatus::WaitingForFunds`] +/// warning rather than an error. pub async fn do_sign(status: StreamSink<SigningStatus>, c: &Coin) -> Result<()> { let mut connection = c.get_connection().await?; let mut client = c.client().await?; let height = client.latest_height().await?; - let account = get_funding_account(&mut connection).await?; - let mut accounts = - query("SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1") - .map(|r: SqliteRow| r.get::<u32, _>(0)) - .fetch_all(&mut *connection) - .await?; - accounts.push(account); - let height = synchronize_impl( - (), - accounts, - height, - DEFAULT_ACTIONS_PER_SYNC, - 1, - 100, - false, - c, - ) - .await?; - let r = crate::frost::sign::do_sign( &c.network(), &mut *connection, @@ -274,6 +309,9 @@ pub enum SigningStatus { SendingSignatureShare, SigningCompleted, WaitingForSignatureShares, + /// A signing message could not be funded yet (previous broadcast's change + /// not mined). Transient — the next block retries. Info/warning, not error. + WaitingForFunds, PreparingTransaction, SendingTransaction, TransactionSent(String), diff --git a/rust/src/db.rs b/rust/src/db.rs index 91d510bc5..9591234b9 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -568,6 +568,14 @@ pub async fn create_schema(connection: &mut SqliteConnection) -> Result<()> { .execute(&mut *connection) .await?; + // DKG publish intent: the outgoing package(s) of the round being + // published, staged before the broadcast and cleared after it. NULL means + // nothing pending (or already sent under an older build). Added without a + // DB_VERSION bump: nullable, only read by new code, older builds ignore it. + let _ = sqlx::query("ALTER TABLE dkg_state ADD COLUMN pending_publish BLOB") + .execute(&mut *connection) + .await; + let version = get_prop(connection, "version").await?; match version { Some(version) if version.parse::<u16>()? > DB_VERSION => { diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index a2cfddda1..278d651a7 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -9891,9 +9891,12 @@ impl SseDecode for crate::api::frost::DKGStatus { return crate::api::frost::DKGStatus::WaitRound2Pkg; } 8 => { - return crate::api::frost::DKGStatus::Finalize; + return crate::api::frost::DKGStatus::WaitingForFunds; } 9 => { + return crate::api::frost::DKGStatus::Finalize; + } + 10 => { let mut var_field0 = <String>::sse_decode(deserializer); return crate::api::frost::DKGStatus::SharedAddress(var_field0); } @@ -11334,12 +11337,15 @@ impl SseDecode for crate::api::frost::SigningStatus { return crate::api::frost::SigningStatus::WaitingForSignatureShares; } 7 => { - return crate::api::frost::SigningStatus::PreparingTransaction; + return crate::api::frost::SigningStatus::WaitingForFunds; } 8 => { - return crate::api::frost::SigningStatus::SendingTransaction; + return crate::api::frost::SigningStatus::PreparingTransaction; } 9 => { + return crate::api::frost::SigningStatus::SendingTransaction; + } + 10 => { let mut var_field0 = <String>::sse_decode(deserializer); return crate::api::frost::SigningStatus::TransactionSent(var_field0); } @@ -13258,9 +13264,10 @@ impl flutter_rust_bridge::IntoDart for crate::api::frost::DKGStatus { crate::api::frost::DKGStatus::WaitRound1Pkg => [5.into_dart()].into_dart(), crate::api::frost::DKGStatus::PublishRound2Pkg => [6.into_dart()].into_dart(), crate::api::frost::DKGStatus::WaitRound2Pkg => [7.into_dart()].into_dart(), - crate::api::frost::DKGStatus::Finalize => [8.into_dart()].into_dart(), + crate::api::frost::DKGStatus::WaitingForFunds => [8.into_dart()].into_dart(), + crate::api::frost::DKGStatus::Finalize => [9.into_dart()].into_dart(), crate::api::frost::DKGStatus::SharedAddress(field0) => { - [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() + [10.into_dart(), field0.into_into_dart().into_dart()].into_dart() } _ => { unimplemented!(""); @@ -13970,10 +13977,11 @@ impl flutter_rust_bridge::IntoDart for crate::api::frost::SigningStatus { crate::api::frost::SigningStatus::WaitingForSignatureShares => { [6.into_dart()].into_dart() } - crate::api::frost::SigningStatus::PreparingTransaction => [7.into_dart()].into_dart(), - crate::api::frost::SigningStatus::SendingTransaction => [8.into_dart()].into_dart(), + crate::api::frost::SigningStatus::WaitingForFunds => [7.into_dart()].into_dart(), + crate::api::frost::SigningStatus::PreparingTransaction => [8.into_dart()].into_dart(), + crate::api::frost::SigningStatus::SendingTransaction => [9.into_dart()].into_dart(), crate::api::frost::SigningStatus::TransactionSent(field0) => { - [9.into_dart(), field0.into_into_dart().into_dart()].into_dart() + [10.into_dart(), field0.into_into_dart().into_dart()].into_dart() } _ => { unimplemented!(""); @@ -15576,11 +15584,14 @@ impl SseEncode for crate::api::frost::DKGStatus { crate::api::frost::DKGStatus::WaitRound2Pkg => { <i32>::sse_encode(7, serializer); } - crate::api::frost::DKGStatus::Finalize => { + crate::api::frost::DKGStatus::WaitingForFunds => { <i32>::sse_encode(8, serializer); } - crate::api::frost::DKGStatus::SharedAddress(field0) => { + crate::api::frost::DKGStatus::Finalize => { <i32>::sse_encode(9, serializer); + } + crate::api::frost::DKGStatus::SharedAddress(field0) => { + <i32>::sse_encode(10, serializer); <String>::sse_encode(field0, serializer); } _ => { @@ -16680,14 +16691,17 @@ impl SseEncode for crate::api::frost::SigningStatus { crate::api::frost::SigningStatus::WaitingForSignatureShares => { <i32>::sse_encode(6, serializer); } - crate::api::frost::SigningStatus::PreparingTransaction => { + crate::api::frost::SigningStatus::WaitingForFunds => { <i32>::sse_encode(7, serializer); } - crate::api::frost::SigningStatus::SendingTransaction => { + crate::api::frost::SigningStatus::PreparingTransaction => { <i32>::sse_encode(8, serializer); } - crate::api::frost::SigningStatus::TransactionSent(field0) => { + crate::api::frost::SigningStatus::SendingTransaction => { <i32>::sse_encode(9, serializer); + } + crate::api::frost::SigningStatus::TransactionSent(field0) => { + <i32>::sse_encode(10, serializer); <String>::sse_encode(field0, serializer); } _ => { diff --git a/rust/src/frost/dkg/exec.rs b/rust/src/frost/dkg/exec.rs new file mode 100644 index 000000000..3894cb9ea --- /dev/null +++ b/rust/src/frost/dkg/exec.rs @@ -0,0 +1,357 @@ +//! Task execution: the side effects, and nothing else. +//! +//! Every decision has already been made by the time control reaches here — a +//! task arrives naming exactly what to do, and these functions carry it out. +//! The crypto (`dkg::part1/2/3`, the address derivations) is called, never +//! reimplemented, here. +//! +//! The one invariant worth calling out is intent before publish: producing a +//! round commits the secret **and** the outgoing bytes in one transaction +//! with no network I/O, and only then does the broadcast go out. A crash +//! after the send but before the marker is cleared retries the identical +//! bytes — every peer's `dkg_peers` primary key dedups them — so the +//! produce-then-publish window that could once wedge a session now costs at +//! most one wasted fee. + +use anyhow::{bail, Context, Result}; +use orchard::keys::{FullViewingKey, Scope}; +use reddsa::frost::redpallas::{ + frost::keys::PublicKeyPackage, + keys::{dkg, EvenY}, +}; +use sqlx::{Connection, SqliteConnection}; +use tracing::info; +use zcash_keys::address::UnifiedAddress; + +use crate::{ + account::{get_account_seed, get_orchard_vk}, + api::{coin::Network, frost::DKGParams}, + db::{delete_account, init_account_orchard, store_account_metadata, store_account_orchard_vk}, + frost::{Dispatch, FrostBytes, FrostMessage, P, RouteCtx}, + Client, +}; + +use super::{ + delete_frost_state, get_addresses, get_coordinator_broadcast_account, get_mailbox_account, + publish, DkgInit, DkgRound0, DkgRound1, DkgRound2, Round, +}; +use super::state::{DkgState, PendingPublish}; + +/// EnsureAccounts: create the private mailbox and the shared broadcast +/// account if missing. Both helpers are create-if-missing and idempotent. +pub async fn ensure_accounts( + network: &Network, + connection: &mut SqliteConnection, + account: u32, + params: &DKGParams, +) -> Result<()> { + // The broadcast account's seed is a hash over every participant address; + // creating it with addresses missing would derive a seed other + // participants never find. The planner gates this behind WaitAddresses, + // but the guard costs one query and makes the effect safe on its own. + let addresses = get_addresses(connection, account, params.n).await?; + anyhow::ensure!( + addresses.iter().all(|a| !a.is_empty()), + "participant addresses incomplete; cannot create the broadcast account" + ); + get_mailbox_account(network, connection, account, params.id, params.birth_height).await?; + get_coordinator_broadcast_account(network, connection, account, params.birth_height).await?; + Ok(()) +} + +/// PublishRound: stage our outgoing package if the round's secret is not +/// stored yet (secret + staged bytes commit together, before any network +/// I/O), then send whatever is staged and clear the marker. +pub async fn publish_round( + network: &Network, + connection: &mut SqliteConnection, + client: &mut Client, + account: u32, + height: u32, + round: u8, + state: &DkgState, +) -> Result<()> { + if !state.rounds[round as usize].secret_present { + stage(connection, round, account, state).await?; + } + publish_staged(network, connection, client, account, height, state.params.id).await +} + +/// Produce the round's package and commit it — secret plus outgoing bytes — +/// in one transaction. No network I/O here. +async fn stage( + connection: &mut SqliteConnection, + round: u8, + account: u32, + state: &DkgState, +) -> Result<()> { + let broadcast_address = state + .broadcast_address + .clone() + .context("broadcast account missing")?; + let route_ctx = RouteCtx { + broadcast_address: broadcast_address.clone(), + coordinator_address: broadcast_address, // unused in DKG + peer_addresses: state.addresses.clone(), + }; + + match round { + 0 => { + let input = DkgInit { + self_id: state.params.id, + n: state.params.n, + t: state.params.t, + }; + let (secret, outgoing) = + DkgRound0::produce(&input).context("round 0 produce failed")?; + let recipients = outgoing.into_recipients(&route_ctx)?; + let mut tx = connection.begin().await?; + <DkgRound0 as Round>::store_secret(&mut *tx, account, &secret).await?; + store_pending(&mut *tx, account, round, recipients).await?; + tx.commit().await?; + } + 1 => { + let input = state + .state0 + .as_ref() + .context("round 1 input not reconstructed")?; + let (secret, outgoing) = + DkgRound1::produce(input).context("round 1 produce failed")?; + let recipients = outgoing.into_recipients(&route_ctx)?; + let mut tx = connection.begin().await?; + <DkgRound1 as Round>::store_secret(&mut *tx, account, &secret).await?; + store_pending(&mut *tx, account, round, recipients).await?; + tx.commit().await?; + } + 2 => { + let input = state + .state1 + .as_ref() + .context("round 2 input not reconstructed")?; + let (secret, outgoing) = + DkgRound2::produce(input).context("round 2 produce failed")?; + let recipients = outgoing.into_recipients(&route_ctx)?; + let mut tx = connection.begin().await?; + <DkgRound2 as Round>::store_secret(&mut *tx, account, &secret).await?; + store_pending(&mut *tx, account, round, recipients).await?; + tx.commit().await?; + } + _ => bail!("invalid round {round}"), + } + Ok(()) +} + +async fn store_pending( + tx: &mut sqlx::SqliteConnection, + account: u32, + round: u8, + recipients: Vec<(String, Vec<u8>)>, +) -> Result<()> { + let pending = PendingPublish { round, recipients }; + sqlx::query("UPDATE dkg_state SET pending_publish = ?1 WHERE account = ?2") + .bind(pending.encode()?) + .bind(account) + .execute(&mut *tx) + .await?; + Ok(()) +} + +/// Send the staged bytes, if any, and clear the marker only afterwards. A +/// crash in between retries the identical bytes; peers dedup them. +async fn publish_staged( + network: &Network, + connection: &mut SqliteConnection, + client: &mut Client, + account: u32, + height: u32, + self_id: u8, +) -> Result<()> { + let pending = load_pending(connection, account).await?; + let Some(pending) = pending else { + return Ok(()); + }; + let prefix = match pending.round { + 0 => <DkgRound0 as Round>::PREFIX, + 1 => <DkgRound1 as Round>::PREFIX, + 2 => <DkgRound2 as Round>::PREFIX, + _ => bail!("invalid round {}", pending.round), + }; + let refs: Vec<(&str, Vec<u8>)> = pending + .recipients + .iter() + .map(|(addr, data)| { + let msg = FrostMessage { + from_id: self_id, + data: data.clone(), + }; + Ok((addr.as_str(), msg.encode_with_prefix(&prefix)?)) + }) + .collect::<Result<_>>()?; + publish(network, connection, account, client, height, &refs) + .await + .context("publish DKG package")?; + sqlx::query("UPDATE dkg_state SET pending_publish = NULL WHERE account = ?") + .bind(account) + .execute(&mut *connection) + .await?; + Ok(()) +} + +async fn load_pending( + connection: &mut SqliteConnection, + account: u32, +) -> Result<Option<PendingPublish>> { + sqlx::query_as::<_, (Vec<u8>,)>( + "SELECT pending_publish FROM dkg_state WHERE account = ? AND pending_publish IS NOT NULL", + ) + .bind(account) + .fetch_optional(&mut *connection) + .await? + .map(|(b,)| PendingPublish::decode(&b)) + .transpose() +} + +/// FinalizeKey: derive our key package and the group public key package from +/// the completed rounds. Idempotent via the stored key package. +pub async fn finalize_key( + connection: &mut SqliteConnection, + account: u32, + state: &DkgState, +) -> Result<()> { + if state.key_pkg_present { + return Ok(()); + } + let state2 = state + .state2 + .as_ref() + .context("round 2 not complete; cannot finalize")?; + info!( + "DKG: calling dkg::part3 (self_id={}, n={}, t={})", + state.params.id, state.params.n, state.params.t + ); + let (kp, pp) = dkg::part3(&state2.spkg2, &state2.state1.ppkg1s, &state2.ppkg2s)?; + info!("DKG: dkg::part3 completed successfully"); + sqlx::query("UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2") + .bind(kp.to_bytes()?) + .bind(account) + .execute(&mut *connection) + .await?; + sqlx::query( + "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 3, ?2, ?3) + ON CONFLICT DO NOTHING", + ) + .bind(account) + .bind(state.params.id) + .bind(pp.to_bytes()?) + .execute(&mut *connection) + .await?; + Ok(()) +} + +/// CreateFrostAccount: build the shared Orchard address by replacing the +/// spend-auth key in the broadcast account's FVK with the FROST group public +/// key, then create the frost account holding it. The creation and the +/// marker recording it commit together, so a crash cannot orphan the account +/// and re-running cannot duplicate it. Returns the shared address. +pub async fn create_frost_account( + network: &Network, + connection: &mut SqliteConnection, + account: u32, + broadcast_account: u32, + height: u32, +) -> Result<String> { + let (pp_data,) = sqlx::query_as::<_, (Vec<u8>,)>( + "SELECT data FROM dkg_peers WHERE account = ? AND round = 3 LIMIT 1", + ) + .bind(account) + .fetch_one(&mut *connection) + .await?; + let pub_key_pkg = PublicKeyPackage::<P>::from_bytes(&pp_data)?; + let pub_key_pkg = pub_key_pkg.into_even_y(None); + let vk = pub_key_pkg.verifying_key(); + let pkb = vk.serialize().expect("pk serialize"); + + let fvk = get_orchard_vk(&mut *connection, broadcast_account) + .await? + .context("broadcast account vk not found")?; + let mut fvkb = fvk.to_bytes(); + fvkb[0..32].copy_from_slice(&pkb); + let shared_fvk = FullViewingKey::from_bytes(&fvkb).expect("Failed to create shared FVK"); + + let (name,) = sqlx::query_as::<_, (String,)>( + "SELECT name FROM dkg_params WHERE account = ?", + ) + .bind(account) + .fetch_one(&mut *connection) + .await?; + + let mut tx = connection.begin().await?; + let frost_account = + store_account_metadata(&mut *tx, &name, &None, &None, height, false, false).await?; + init_account_orchard(network, &mut *tx, frost_account, height).await?; + store_account_orchard_vk(&mut *tx, frost_account, &shared_fvk).await?; + sqlx::query("INSERT OR REPLACE INTO props(key, value) VALUES ('dkg_frost_account', ?1)") + .bind(frost_account.to_string()) + .execute(&mut *tx) + .await?; + tx.commit().await?; + info!("Frost account {frost_account} created with the shared key"); + + shared_address(network, connection, frost_account).await +} + +/// The shared address, derived from the frost account's stored group FVK. +pub async fn shared_address( + network: &Network, + connection: &mut SqliteConnection, + frost_account: u32, +) -> Result<String> { + let fvk = get_orchard_vk(&mut *connection, frost_account) + .await? + .context("frost account vk not found")?; + let address = fvk.address_at(0u64, Scope::External); + let ua = UnifiedAddress::from_receivers(Some(address), None, None).unwrap(); + Ok(ua.encode(network)) +} + +/// CompleteFinalize: rekey the protocol rows onto the frost account, record +/// the mailbox seed, tear down the helper accounts, and only then clear the +/// props that stop the drivers — a crash mid-teardown must leave the drivers +/// still willing to step, so the remaining operations re-run idempotently. +pub async fn complete_finalize( + connection: &mut SqliteConnection, + funding_account: u32, + frost_account: u32, + mailbox: Option<u32>, + broadcast: Option<u32>, +) -> Result<()> { + // 1. Rekey the protocol rows (no-ops when already done). + for table in ["dkg_params", "dkg_state", "dkg_peers", "dkg_addresses"] { + sqlx::query(&format!("UPDATE {table} SET account = ?1 WHERE account = ?2")) + .bind(frost_account) + .bind(funding_account) + .execute(&mut *connection) + .await?; + } + // 2. The mailbox seed under the frost account, while the mailbox exists. + if let Some(mailbox) = mailbox { + let seed = get_account_seed(&mut *connection, mailbox) + .await? + .context("mailbox seed not found")? + .mnemonic; + sqlx::query("UPDATE dkg_params SET seed = ?1 WHERE account = ?2") + .bind(seed) + .bind(frost_account) + .execute(&mut *connection) + .await?; + } + // 3. Tear down the helper accounts. + if let Some(mailbox) = mailbox { + delete_account(&mut *connection, mailbox).await?; + } + if let Some(broadcast) = broadcast { + delete_account(&mut *connection, broadcast).await?; + } + // 4. Cleanup LAST: the props this deletes are what stop the drivers. + delete_frost_state(&mut *connection).await +} diff --git a/rust/src/frost/dkg.rs b/rust/src/frost/dkg/mod.rs similarity index 66% rename from rust/src/frost/dkg.rs rename to rust/src/frost/dkg/mod.rs index e0973e15d..dade73c94 100644 --- a/rust/src/frost/dkg.rs +++ b/rust/src/frost/dkg/mod.rs @@ -2,32 +2,29 @@ use std::collections::BTreeMap; use anyhow::{Context, Result}; use ed25519_dalek::{SigningKey, VerifyingKey, SECRET_KEY_LENGTH}; -use orchard::keys::{FullViewingKey, Scope}; use rand_core::OsRng; use reddsa::frost::redpallas::{ - frost::keys::{KeyPackage, PublicKeyPackage}, keys::dkg::{self, round1, round2}, - keys::EvenY, Identifier, }; use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use tracing::info; -use zcash_keys::address::UnifiedAddress; use crate::{ - account::{get_account_seed, get_orchard_vk}, - api::{ - coin::Network, - frost::{get_funding_account, DKGParams, DKGStatus}, - sync::SYNCING, - }, - db::{delete_account, init_account_orchard, store_account_metadata, store_account_orchard_vk}, - frost::{Broadcast, FrostBytes, PerPeer, Round, RouteCtx}, - Client, Sink, + api::{coin::Network, frost::{get_funding_account, DKGParams}}, + db::delete_account, + frost::{Broadcast, FrostBytes, PerPeer, Round}, + Client, }; +pub mod exec; +pub mod plan; +pub mod state; +pub mod step; +pub mod task; + pub use super::protocol::{ - get_addresses, get_coordinator_broadcast_account, get_mailbox_account, publish, run_round, + get_addresses, get_coordinator_broadcast_account, get_mailbox_account, publish, }; // ── FrostBytes for ed25519 types ───────────────────────────────────────────── @@ -74,6 +71,7 @@ impl FrostBytes for VerifyingKey { // ── State types ────────────────────────────────────────────────────────────── /// Seed data for the first DKG round. +#[derive(Clone, Copy, Debug)] pub struct DkgInit { pub self_id: u8, pub n: u8, @@ -81,6 +79,7 @@ pub struct DkgInit { } /// State after round 0 completes: our signing keypair + all peers' public keys. +#[derive(Clone)] pub struct DkgState0 { pub init: DkgInit, pub signing_key: SigningKey, @@ -89,6 +88,7 @@ pub struct DkgState0 { } /// State after round 1 completes: our secret + all peers' round-1 packages. +#[derive(Clone)] pub struct DkgState1 { pub state0: DkgState0, pub spkg1: round1::SecretPackage, @@ -96,6 +96,7 @@ pub struct DkgState1 { } /// State after round 2 completes: carries forward everything needed for part3. +#[derive(Clone)] pub struct DkgState2 { pub state1: DkgState1, pub spkg2: round2::SecretPackage, @@ -115,11 +116,6 @@ impl Round for DkgRound0 { const PREFIX: [u8; 4] = *b"DK00"; - /// Need all other participants' public keys. - fn threshold(_n: u8, t: u8) -> usize { - t as usize - } - fn produce(input: &DkgInit) -> Result<(SigningKey, Broadcast<VerifyingKey>)> { info!( "DKG Round0: generating signing keypair (self_id={}, n={}, t={})", @@ -258,11 +254,6 @@ impl Round for DkgRound1 { const PREFIX: [u8; 4] = *b"DK11"; - /// Need all other participants' packages. - fn threshold(_n: u8, t: u8) -> usize { - t as usize - } - fn produce(input: &DkgState0) -> Result<(round1::SecretPackage, Broadcast<round1::Package>)> { info!( "DKG: calling dkg::part1 (self_id={}, n={}, t={})", @@ -371,11 +362,6 @@ impl Round for DkgRound2 { const PREFIX: [u8; 4] = *b"DK21"; - /// Need all other participants' packages. - fn threshold(_n: u8, t: u8) -> usize { - t as usize - } - fn produce(input: &DkgState1) -> Result<(round2::SecretPackage, PerPeer<round2::Package>)> { // part2 takes spkg1 by value — clone since input is borrowed info!( @@ -624,278 +610,3 @@ pub async fn delete_frost_state(connection: &mut SqliteConnection) -> Result<()> Ok(()) } -// ── Main orchestrator ──────────────────────────────────────────────────────── - -#[cfg(feature = "flutter")] -use crate::frb_generated::StreamSink; - -#[cfg(feature = "flutter")] -pub async fn do_dkg( - network: &Network, - connection: &mut SqliteConnection, - account: u32, - client: &mut Client, - height: u32, - status: StreamSink<DKGStatus>, -) -> Result<()> { - do_dkg_impl(network, connection, account, client, height, status).await -} - -pub async fn do_dkg_impl( - network: &Network, - connection: &mut SqliteConnection, - account: u32, - client: &mut Client, - height: u32, - status: impl Sink<DKGStatus>, -) -> Result<()> { - info!("dkg: {account}"); - - let guard = SYNCING.try_lock(); - if guard.is_err() { - return Ok(()); - } - - let DKGParams { - id: self_id, - n, - t, - birth_height, - } = get_dkg_params(connection, account).await?; - - let (mailbox_account, _) = - get_mailbox_account(network, connection, account, self_id, birth_height).await?; - let (broadcast_account, broadcast_address) = - get_coordinator_broadcast_account(network, connection, account, birth_height).await?; - - let addresses = get_addresses(connection, account, n).await?; - let route_ctx = RouteCtx { - broadcast_address: broadcast_address.clone(), - coordinator_address: broadcast_address.clone(), // unused in DKG - peer_addresses: addresses, - }; - - // ── Round 0: broadcast signing public keys ──────────────────────────────── - // `run_round` publishes our own package only on the invocation where our - // secret does not exist yet, so checking for it first tells us whether this - // pass is a broadcast or just a poll for peer packages. - let init = DkgInit { self_id, n, t }; - if <DkgRound0 as Round>::load_secret(connection, account) - .await? - .is_none() - { - status.send(DKGStatus::PublishRound0Pkg).await; - } - let Some(state0) = run_round::<DkgRound0>( - connection, - account, - n, - t, - self_id, - account, // funding_account - broadcast_account, // incoming memos arrive at broadcast - init, - &route_ctx, - network, - client, - height, - ) - .await? - else { - status.send(DKGStatus::WaitRound0Pkg).await; - return Ok(()); - }; - info!( - "Round 0 complete - collected {} peer signing keys", - state0.peer_verifying_keys.len() - ); - - // ── Round 1: everyone broadcasts one package to the shared address ──────── - if <DkgRound1 as Round>::load_secret(connection, account) - .await? - .is_none() - { - status.send(DKGStatus::PublishRound1Pkg).await; - } - let Some(state1) = run_round::<DkgRound1>( - connection, - account, - n, - t, - self_id, - account, // funding_account - broadcast_account, // incoming memos arrive at broadcast - state0, - &route_ctx, - network, - client, - height, - ) - .await? - else { - status.send(DKGStatus::WaitRound1Pkg).await; - return Ok(()); - }; - info!("Round 1 complete"); - - // ── Round 2: each sends a unique package to every peer's mailbox ────────── - if <DkgRound2 as Round>::load_secret(connection, account) - .await? - .is_none() - { - status.send(DKGStatus::PublishRound2Pkg).await; - } - let Some(state2) = run_round::<DkgRound2>( - connection, - account, - n, - t, - self_id, - account, // funding_account - mailbox_account, // incoming memos arrive at our private mailbox - state1, - &route_ctx, - network, - client, - height, - ) - .await? - else { - status.send(DKGStatus::WaitRound2Pkg).await; - return Ok(()); - }; - info!("Round 2 complete"); - - // ── Round 3: local only — derive the shared key ─────────────────────────── - status.send(DKGStatus::Finalize).await; - let key_pkg = sqlx::query_as::<_, (Vec<u8>,)>( - "SELECT key_pkg FROM dkg_state WHERE account = ? AND key_pkg IS NOT NULL", - ) - .bind(account) - .fetch_optional(&mut *connection) - .await?; - - let (key_pkg, pub_key_pkg) = if let Some((data,)) = key_pkg { - // Already computed on a previous block — reload from DB - let kp = KeyPackage::<_>::from_bytes(&data)?; - let (pp_data,) = sqlx::query_as::<_, (Vec<u8>,)>( - "SELECT data FROM dkg_peers WHERE account = ? AND round = 3 LIMIT 1", - ) - .bind(account) - .fetch_one(&mut *connection) - .await?; - (kp, PublicKeyPackage::from_bytes(&pp_data)?) - } else { - info!( - "DKG: calling dkg::part3 (self_id={}, n={}, t={})", - self_id, n, t - ); - let (kp, pp) = dkg::part3(&state2.spkg2, &state2.state1.ppkg1s, &state2.ppkg2s)?; - info!("DKG: dkg::part3 completed successfully"); - sqlx::query("UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2") - .bind(kp.to_bytes()?) - .bind(account) - .execute(&mut *connection) - .await?; - sqlx::query( - "INSERT INTO dkg_peers(account, round, from_id, data) VALUES(?1, 3, ?2, ?3) - ON CONFLICT DO NOTHING", - ) - .bind(account) - .bind(self_id) - .bind(pp.to_bytes()?) - .execute(&mut *connection) - .await?; - (kp, pp) - }; - - // Build the shared Orchard address by replacing the spend-auth key in the - // broadcast account's FVK with the FROST group public key. - let fvk = get_orchard_vk(connection, broadcast_account) - .await? - .expect("broadcast account vk not found"); - let mut fvkb = fvk.to_bytes(); - let pub_key_pkg = pub_key_pkg.into_even_y(None); - let vk = pub_key_pkg.verifying_key(); - let pkb = vk.serialize().expect("pk serialize"); - fvkb[0..32].copy_from_slice(&pkb); - let shared_fvk = FullViewingKey::from_bytes(&fvkb).expect("Failed to create shared FVK"); - let address = shared_fvk.address_at(0u64, Scope::External); - let ua = UnifiedAddress::from_receivers(Some(address), None, None).unwrap(); - let sua = ua.encode(network); - info!("Shared address: {sua}"); - - let (name,) = sqlx::query_as::<_, (String,)>("SELECT name FROM dkg_params WHERE account = ?") - .bind(account) - .fetch_one(&mut *connection) - .await?; - let frost_account = - store_account_metadata(connection, &name, &None, &None, height, false, false).await?; - init_account_orchard(network, connection, frost_account, height).await?; - store_account_orchard_vk(connection, frost_account, &shared_fvk).await?; - - dkg_finalize( - connection, - account, - frost_account, - mailbox_account, - broadcast_account, - ) - .await?; - - // Store key material under the frost account - sqlx::query("UPDATE dkg_state SET key_pkg = ?1 WHERE account = ?2") - .bind(key_pkg.to_bytes()?) - .bind(frost_account) - .execute(&mut *connection) - .await?; - - status.send(DKGStatus::SharedAddress(sua)).await; - - cancel_dkg(connection, account).await?; - Ok(()) -} - -async fn dkg_finalize( - connection: &mut SqliteConnection, - account: u32, - frost_account: u32, - mailbox_account: u32, - broadcast_account: u32, -) -> Result<()> { - sqlx::query("UPDATE dkg_params SET account = ?1 WHERE account = ?2") - .bind(frost_account) - .bind(account) - .execute(&mut *connection) - .await?; - sqlx::query("UPDATE dkg_state SET account = ?1 WHERE account = ?2") - .bind(frost_account) - .bind(account) - .execute(&mut *connection) - .await?; - sqlx::query("UPDATE dkg_peers SET account = ?1 WHERE account = ?2") - .bind(frost_account) - .bind(account) - .execute(&mut *connection) - .await?; - sqlx::query("UPDATE dkg_addresses SET account = ?1 WHERE account = ?2") - .bind(frost_account) - .bind(account) - .execute(&mut *connection) - .await?; - sqlx::query("DELETE FROM props WHERE key LIKE 'dkg_%'") - .execute(&mut *connection) - .await?; - let seed = get_account_seed(&mut *connection, mailbox_account) - .await? - .expect("mailbox seed not found") - .mnemonic; - sqlx::query("UPDATE dkg_params SET seed = ?1 WHERE account = ?2") - .bind(seed) - .bind(frost_account) - .execute(&mut *connection) - .await?; - delete_account(&mut *connection, mailbox_account).await?; - delete_account(&mut *connection, broadcast_account).await?; - Ok(()) -} diff --git a/rust/src/frost/dkg/plan.rs b/rust/src/frost/dkg/plan.rs new file mode 100644 index 000000000..79df63d97 --- /dev/null +++ b/rust/src/frost/dkg/plan.rs @@ -0,0 +1,210 @@ +//! Pure decision logic for the DKG pipeline. +//! +//! Nothing here performs I/O. Every function is a total function of its +//! arguments, so what the DKG decides to do can be unit-tested without a +//! wallet, a chain, or other participants. + +use super::state::DkgState; +use super::task::DkgTask; + +/// Decide the DKG's next step. +/// +/// Pure: a total function of observed protocol state. Rounds advance only +/// when every participant's package has arrived — the all-n discipline that +/// keeps every wallet's materialized key set identical, so any t-subset is +/// valid when signing begins. +pub fn next_task(s: &DkgState) -> DkgTask { + if !s.addresses_complete() { + return DkgTask::WaitAddresses; + } + if s.mailbox.is_none() || s.broadcast.is_none() { + return DkgTask::EnsureAccounts; + } + // A staged-but-unsent publish outranks everything: resending exactly + // those bytes is the crash-recovery path, and every peer dedups them. + if let Some(round) = s.pending_round() { + return DkgTask::PublishRound { round }; + } + for round in 0..3u8 { + let rs = &s.rounds[round as usize]; + if !rs.secret_present { + return DkgTask::PublishRound { round }; + } + if rs.others < s.params.n.saturating_sub(1) { + return DkgTask::WaitRound { round }; + } + } + if !s.key_pkg_present { + return DkgTask::FinalizeKey; + } + if s.frost_account.is_none() { + return DkgTask::CreateFrostAccount; + } + DkgTask::CompleteFinalize +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::api::frost::DKGParams; + use crate::frost::dkg::state::RoundState; + + fn params(n: u8) -> DKGParams { + DKGParams { + id: 1, + n, + t: 2, + birth_height: 0, + } + } + + fn round(secret: bool, others: u8) -> RoundState { + RoundState { + secret_present: secret, + others, + pending: None, + } + } + + /// A wallet with all addresses exchanged, both helper accounts present. + fn state(n: u8, rounds: [RoundState; 3]) -> DkgState { + DkgState { + funding_account: 1, + params: params(n), + addresses: vec!["a".to_string(); n as usize], + mailbox: Some(100), + broadcast: Some(101), + broadcast_address: Some("b".into()), + rounds, + key_pkg_present: false, + frost_account: None, + rekeyed: false, + state0: None, + state1: None, + state2: None, + } + } + + /// Rounds 0..=`last` have secrets and all n-1 peer packages. + fn through(n: u8, last: u8) -> [RoundState; 3] { + let mut rounds = [round(false, 0); 3]; + for (i, r) in rounds.iter_mut().enumerate() { + if i <= last as usize { + *r = round(true, n - 1); + } + } + rounds + } + + #[test] + fn waits_for_all_addresses() { + let mut s = state(3, through(3, 2)); + s.addresses[1] = String::new(); + assert_eq!(next_task(&s), DkgTask::WaitAddresses); + } + + #[test] + fn ensures_accounts_before_anything_else() { + let mut s = state(3, through(3, 2)); + s.broadcast = None; + s.broadcast_address = None; + assert_eq!(next_task(&s), DkgTask::EnsureAccounts); + } + + #[test] + fn pending_publish_outranks_producing_the_next_round() { + let mut s = state(3, through(3, 0)); + s.rounds[0].pending = Some(0); + assert_eq!(next_task(&s), DkgTask::PublishRound { round: 0 }); + } + + /// Regression: rounds used to advance once t packages had arrived, which + /// with t < n finalized each wallet on a nondeterministic subset of the + /// key material. All n participants run the DKG, so every round waits + /// for all n-1 peers. + #[test] + fn rounds_wait_for_all_participants() { + let s = state( + 3, + { + let mut r = [round(false, 0); 3]; + r[0] = round(true, 1); // only 1 of 2 peers so far + r + }, + ); + assert_eq!(next_task(&s), DkgTask::WaitRound { round: 0 }); + } + + #[test] + fn produces_rounds_in_order() { + assert_eq!( + next_task(&state(3, [round(false, 0); 3])), + DkgTask::PublishRound { round: 0 } + ); + assert_eq!( + next_task(&state(3, through(3, 0))), + DkgTask::PublishRound { round: 1 } + ); + assert_eq!( + next_task(&state(3, through(3, 1))), + DkgTask::PublishRound { round: 2 } + ); + } + + #[test] + fn finalizes_in_stages() { + let s = state(3, through(3, 2)); + assert_eq!(next_task(&s), DkgTask::FinalizeKey); + let mut s2 = s.clone(); + s2.key_pkg_present = true; + assert_eq!(next_task(&s2), DkgTask::CreateFrostAccount); + let mut s3 = s2.clone(); + s3.frost_account = Some(7); + assert_eq!(next_task(&s3), DkgTask::CompleteFinalize); + } + + /// A wallet the rekey already moved to the frost account must resume + /// with the cleanup, not start over. + #[test] + fn rekeyed_wallet_finishes_the_cleanup() { + let mut s = state(3, through(3, 2)); + s.rekeyed = true; + s.key_pkg_present = true; + s.frost_account = Some(7); + assert_eq!(next_task(&s), DkgTask::CompleteFinalize); + } + + #[test] + fn preconditions_reject_stale_plans() { + let s = state(3, through(3, 0)); + + // Round 1 not produced yet: staging is due. + assert!(DkgTask::PublishRound { round: 1 }.is_satisfied_by(&s)); + // Published (secret stored, nothing staged): re-publishing is stale. + let mut published = s.clone(); + published.rounds[1].secret_present = true; + assert!(!DkgTask::PublishRound { round: 1 }.is_satisfied_by(&published)); + // Staged but unconfirmed: resending the staged bytes is the point. + published.rounds[1].pending = Some(1); + assert!(DkgTask::PublishRound { round: 1 }.is_satisfied_by(&published)); + + assert!(DkgTask::FinalizeKey.is_satisfied_by(&s)); + let mut done_key = s.clone(); + done_key.key_pkg_present = true; + assert!(!DkgTask::FinalizeKey.is_satisfied_by(&done_key)); + + assert!(DkgTask::CreateFrostAccount.is_satisfied_by(&s)); + let mut acc = s.clone(); + acc.frost_account = Some(7); + assert!(!DkgTask::CreateFrostAccount.is_satisfied_by(&acc)); + + assert!(!DkgTask::EnsureAccounts.is_satisfied_by(&s)); + let mut noacc = s.clone(); + noacc.mailbox = None; + assert!(DkgTask::EnsureAccounts.is_satisfied_by(&noacc)); + + assert!(DkgTask::WaitRound { round: 0 }.is_satisfied_by(&s)); + assert!(DkgTask::WaitAddresses.is_satisfied_by(&s)); + assert!(DkgTask::CompleteFinalize.is_satisfied_by(&s)); + } +} diff --git a/rust/src/frost/dkg/state.rs b/rust/src/frost/dkg/state.rs new file mode 100644 index 000000000..0ae4cf100 --- /dev/null +++ b/rust/src/frost/dkg/state.rs @@ -0,0 +1,286 @@ +//! A snapshot of everything the DKG needs in order to decide what to do. +//! +//! `observe` is the DKG's single reader of protocol state. Unlike the note +//! migration's observation, it is not purely read-only: it first ingests the +//! peer packages that have arrived in memos since the last step. That ingest +//! is idempotent — `dkg_peers`' primary key `(account, round, from_id)` dedups +//! — and it is what makes peer progress visible: in a multi-party protocol, +//! the state that decides the next task lives partly in other wallets' +//! messages. + +use anyhow::{bail, Context, Result}; +use bincode::{config, Decode, Encode}; +use sqlx::{Row, SqliteConnection}; + +use crate::api::{coin::Network, frost::DKGParams}; +use crate::frost::protocol::{decode_dkg_memos, get_addresses, lookup_broadcast_account}; + +use super::{DkgRound0, DkgRound1, DkgRound2, DkgInit, DkgState0, DkgState1, DkgState2, Round}; + +/// Outgoing bytes staged before the broadcast, cleared after it. Routing is +/// frozen at stage time so a retry sends exactly what was planned. The crash +/// window between `send` and clearing the marker only ever costs one +/// duplicate memo transmission — the identical bytes, deduplicated by every +/// peer's primary key — never a secret/package mismatch. +#[derive(Encode, Decode)] +pub struct PendingPublish { + pub round: u8, + pub recipients: Vec<(String, Vec<u8>)>, +} + +impl PendingPublish { + pub fn encode(&self) -> Result<Vec<u8>> { + Ok(bincode::encode_to_vec(self, config::legacy())?) + } + + pub fn decode(data: &[u8]) -> Result<Self> { + Ok(bincode::decode_from_slice(data, config::legacy())?.0) + } +} + +/// Where one round stands: our secret, the peers we have heard from, and +/// whether an outgoing package is staged but not yet confirmed sent. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct RoundState { + pub secret_present: bool, + /// Distinct packages from participants other than us. + pub others: u8, + /// Round whose outgoing bytes are staged in `dkg_state.pending_publish`. + pub pending: Option<u8>, +} + +/// The wallet's DKG state at one instant, as the planner sees it. +#[derive(Clone)] +pub struct DkgState { + pub funding_account: u32, + pub params: DKGParams, + /// Participant addresses, slot `id - 1` empty when not yet exchanged. + pub addresses: Vec<String>, + pub mailbox: Option<u32>, + pub broadcast: Option<u32>, + pub broadcast_address: Option<String>, + pub rounds: [RoundState; 3], + pub key_pkg_present: bool, + /// The shared frost account, once created (props `dkg_frost_account`). + pub frost_account: Option<u32>, + /// True when `dkg_params` was found under the frost account: the finalize + /// rekey already happened and only cleanup remains. + pub rekeyed: bool, + // Reconstructed round inputs (pure `collect` chains), consumed by exec. + pub state0: Option<DkgState0>, + pub state1: Option<DkgState1>, + pub state2: Option<DkgState2>, +} + +impl DkgState { + pub fn addresses_complete(&self) -> bool { + self.addresses.len() == self.params.n as usize + && self.addresses.iter().all(|a| !a.is_empty()) + } + + /// The round with staged-but-unsent outgoing bytes, if any. + pub fn pending_round(&self) -> Option<u8> { + self.rounds + .iter() + .position(|r| r.pending.is_some()) + .map(|r| r as u8) + } +} + +/// Read protocol state. Peer packages are ingested from memos first; the +/// rest is a handful of queries over the dkg_* tables plus the two helper +/// accounts, and the pure `collect` chain that rebuilds the round inputs. +pub async fn observe( + network: &Network, + connection: &mut SqliteConnection, + funding_account: u32, +) -> Result<DkgState> { + // Resolve which account's rows we are on: the funding account until the + // finalize rekey, the frost account after it. props `dkg_frost_account` + // bridges the gap so a crash inside finalize resumes instead of failing. + let frost_account: Option<u32> = sqlx::query_as::<_, (String,)>( + "SELECT value FROM props WHERE key = 'dkg_frost_account'", + ) + .fetch_optional(&mut *connection) + .await? + .and_then(|(v,)| v.parse().ok()); + + let (params, params_account, rekeyed) = match get_params_opt(connection, funding_account).await? + { + Some(p) => (p, funding_account, false), + None => match frost_account { + Some(fa) => match get_params_opt(connection, fa).await? { + Some(p) => (p, fa, true), + None => bail!("dkg_params not found for account {funding_account}"), + }, + None => bail!("dkg_params not found for account {funding_account}"), + }, + }; + + let n = params.n; + let addresses = get_addresses(connection, params_account, n).await?; + let addresses_complete = addresses.len() == n as usize && addresses.iter().all(|a| !a.is_empty()); + + // Helper accounts, looked up read-only — creating them is an effect + // (EnsureAccounts), and observe has no side effects beyond memo ingest. + let mailbox = mailbox_account_id(connection, params_account).await?; + let broadcast_lookup = if addresses_complete { + lookup_broadcast_account(network, connection, params_account).await? + } else { + None + }; + let (broadcast, broadcast_address) = match broadcast_lookup { + Some((id, addr)) => (Some(id), Some(addr)), + None => (None, None), + }; + + // Ingest arrived peer packages. Rounds 0 and 1 are broadcast to the + // shared address, round 2 to our private mailbox; ingest whichever + // accounts exist (a missing account has nothing to read yet). + if let Some(broadcast_id) = broadcast { + decode_dkg_memos::<DkgRound0>(connection, params_account, broadcast_id).await?; + decode_dkg_memos::<DkgRound1>(connection, params_account, broadcast_id).await?; + } + if let Some(mailbox_id) = mailbox { + decode_dkg_memos::<DkgRound2>(connection, params_account, mailbox_id).await?; + } + + let pending: Option<PendingPublish> = + sqlx::query_as::<_, (Vec<u8>,)>( + "SELECT pending_publish FROM dkg_state WHERE account = ? AND pending_publish IS NOT NULL", + ) + .bind(params_account) + .fetch_optional(&mut *connection) + .await? + .map(|(b,)| PendingPublish::decode(&b)) + .transpose()?; + + let mut rounds = [RoundState { secret_present: false, others: 0, pending: None }; 3]; + for (round, rs) in rounds.iter_mut().enumerate() { + let round = round as u8; + rs.secret_present = match round { + 0 => <DkgRound0 as Round>::load_secret(connection, params_account).await?.is_some(), + 1 => <DkgRound1 as Round>::load_secret(connection, params_account).await?.is_some(), + _ => <DkgRound2 as Round>::load_secret(connection, params_account).await?.is_some(), + }; + rs.others = sqlx::query_as::<_, (u32,)>( + "SELECT COUNT(*) FROM dkg_peers WHERE account = ? AND round = ? AND from_id != ?", + ) + .bind(params_account) + .bind(round) + .bind(params.id) + .fetch_one(&mut *connection) + .await? + .0 as u8; + rs.pending = pending + .as_ref() + .filter(|p| p.round == round) + .map(|p| p.round); + } + + let key_pkg_present = sqlx::query_as::<_, (Vec<u8>,)>( + "SELECT key_pkg FROM dkg_state WHERE account = ? AND key_pkg IS NOT NULL", + ) + .bind(params_account) + .fetch_optional(&mut *connection) + .await? + .is_some(); + + // Rebuild the round inputs by chaining the pure `collect` functions over + // stored secrets and peer packages — the same data `do_dkg_impl` used to + // thread through `run_round` return values, re-derived from the DB each + // step instead. + let init = DkgInit { + self_id: params.id, + n, + t: params.t, + }; + let need_peers = |rs: &RoundState| rs.secret_present && rs.others >= n.saturating_sub(1); + let state0 = if need_peers(&rounds[0]) { + let secret = <DkgRound0 as Round>::load_secret(connection, params_account) + .await? + .unwrap(); + let peers = <DkgRound0 as Round>::load_publics(connection, params_account).await?; + Some(DkgRound0::collect(init, secret, peers)?) + } else { + None + }; + let state1 = if let (Some(s0), true) = (&state0, need_peers(&rounds[1])) { + let secret = <DkgRound1 as Round>::load_secret(connection, params_account) + .await? + .unwrap(); + let peers = <DkgRound1 as Round>::load_publics(connection, params_account).await?; + Some(DkgRound1::collect(s0.clone(), secret, peers)?) + } else { + None + }; + let state2 = if let (Some(s1), true) = (&state1, need_peers(&rounds[2])) { + let secret = <DkgRound2 as Round>::load_secret(connection, params_account) + .await? + .unwrap(); + let peers = <DkgRound2 as Round>::load_publics(connection, params_account).await?; + Some(DkgRound2::collect(s1.clone(), secret, peers)?) + } else { + None + }; + + Ok(DkgState { + funding_account, + params, + addresses, + mailbox, + broadcast, + broadcast_address, + rounds, + key_pkg_present, + frost_account, + rekeyed, + state0, + state1, + state2, + }) +} + +/// The dkg_params row, if present. Unlike [`super::get_dkg_params`], missing +/// rows are a normal outcome: they mean the finalize rekey already moved the +/// row to the frost account. +async fn get_params_opt( + connection: &mut SqliteConnection, + account: u32, +) -> Result<Option<DKGParams>> { + sqlx::query("SELECT id, n, t, birth_height FROM dkg_params WHERE account = ?") + .bind(account) + .map(|row: sqlx::sqlite::SqliteRow| DKGParams { + id: row.get(0), + n: row.get(1), + t: row.get(2), + birth_height: row.get(3), + }) + .fetch_optional(&mut *connection) + .await + .context("Fetch dkg_params") +} + +/// The private mailbox account, found by the seed stored in dkg_params when +/// it was created. None when the mailbox does not exist yet. +async fn mailbox_account_id( + connection: &mut SqliteConnection, + params_account: u32, +) -> Result<Option<u32>> { + let seed: Option<(String,)> = + sqlx::query_as("SELECT seed FROM dkg_params WHERE account = ?") + .bind(params_account) + .fetch_optional(&mut *connection) + .await?; + let Some((seed,)) = seed else { + return Ok(None); + }; + if seed.is_empty() { + return Ok(None); + } + let r: Option<(u32,)> = sqlx::query_as("SELECT id_account FROM accounts WHERE seed = ?1") + .bind(&seed) + .fetch_optional(&mut *connection) + .await?; + Ok(r.map(|(a,)| a)) +} diff --git a/rust/src/frost/dkg/step.rs b/rust/src/frost/dkg/step.rs new file mode 100644 index 000000000..62334bebe --- /dev/null +++ b/rust/src/frost/dkg/step.rs @@ -0,0 +1,148 @@ +//! One DKG pass, without waiting. +//! +//! The shared entry point behind both front ends: `api::frost` exposes it to +//! Flutter and the GraphQL server calls it directly. A pass executes every +//! effect the planner names until it hits a wait or the protocol completes — +//! the same multi-round advance per invocation the sequential orchestrator +//! performed, one precondition-checked effect at a time. The caller syncs +//! first if fresh memo data matters; like [`crate::migrate::step::step_once`], +//! the step itself never synchronizes. + +use anyhow::{bail, Context, Result}; +use sqlx::SqliteConnection; + +use crate::{api::coin::Network, Client}; + +use super::{ + exec, + plan::next_task, + state::observe, + task::{DkgTask, TaskKind}, +}; + +/// What one pass did. `executed` ends with the wait/terminal task the pass +/// stopped on — planned but not executed — so a front end can show where +/// things stand without re-observing. +pub struct DkgStepOutcome { + pub executed: Vec<DkgTask>, + /// The shared address, once the frost account exists. + pub shared_address: Option<String>, + /// A publish could not be funded yet: the note we spent for the previous + /// round is locked and its change is not mined, so there is nothing to + /// spend. Transient — the staged `pending_publish` is kept and the caller + /// retries on the next block. Surfaced as a warning, never an error. + pub waiting_for_funds: bool, +} + +/// Run one pass for `account`. +/// +/// The account is explicit rather than read from `c.account`: a caller holding +/// a process-wide coin — the GraphQL server does — must step the wallet it was +/// asked about, not whichever one the coin happens to name. +pub async fn dkg_step( + network: &Network, + connection: &mut SqliteConnection, + client: &mut Client, + height: u32, + account: u32, +) -> Result<DkgStepOutcome> { + let mut executed = Vec::new(); + let mut shared_address = None; + + // Effects per pass are bounded (three publishes plus three finalize + // stages); the cap turns a would-be hot loop into an error. + for _ in 0..16 { + let state = observe(network, connection, account).await?; + let task = next_task(&state); + + if !matches!(task.kind(), TaskKind::Effect) { + executed.push(task); + return Ok(DkgStepOutcome { + executed, + shared_address, + waiting_for_funds: false, + }); + } + + // Re-validate before touching anything. The snapshot the task was + // planned from is an observe old, and a concurrent step — the app and + // the GraphQL server can drive the same wallet — may have moved the + // protocol underneath it. A stale task is re-planned, never executed. + let fresh = observe(network, connection, account).await?; + if !task.is_satisfied_by(&fresh) { + tracing::info!("DKG task {task:?} no longer applies; replanning"); + continue; + } + + match task { + DkgTask::EnsureAccounts => { + exec::ensure_accounts(network, connection, account, &fresh.params).await?; + } + DkgTask::PublishRound { round } => { + match exec::publish_round( + network, connection, client, account, height, round, &fresh, + ) + .await + { + Ok(()) => {} + // No spendable note yet: the previous round's change is not + // mined. `stage()` already committed the secret and the + // pending bytes, so bail out of the pass as a wait — the + // caller retries on the next block and the resend goes + // through once the change confirms. + Err(e) if crate::pay::plan::is_no_feasible_selection(&e) => { + tracing::warn!( + "DKG round {round} publish deferred: no spendable note yet; \ + will retry on the next block" + ); + return Ok(DkgStepOutcome { + executed, + shared_address, + waiting_for_funds: true, + }); + } + Err(e) => return Err(e), + } + } + DkgTask::FinalizeKey => { + exec::finalize_key(connection, account, &fresh).await?; + } + DkgTask::CreateFrostAccount => { + let broadcast = fresh.broadcast.context("broadcast account missing")?; + shared_address = Some( + exec::create_frost_account(network, connection, account, broadcast, height) + .await?, + ); + } + DkgTask::CompleteFinalize => { + let frost_account = fresh.frost_account.context("frost account missing")?; + exec::complete_finalize( + connection, + account, + frost_account, + fresh.mailbox, + fresh.broadcast, + ) + .await?; + // The rekey moved the protocol rows and the cleanup deleted + // the props, so this is the pass's last act: report the shared + // address from the frost account's stored group key. + if shared_address.is_none() { + shared_address = + Some(exec::shared_address(network, connection, frost_account).await?); + } + executed.push(task); + return Ok(DkgStepOutcome { + executed, + shared_address, + waiting_for_funds: false, + }); + } + DkgTask::WaitAddresses | DkgTask::WaitRound { .. } | DkgTask::Done => { + unreachable!("non-effect task handled above") + } + } + executed.push(task); + } + bail!("DKG pass executed too many effects without reaching a wait; aborting") +} diff --git a/rust/src/frost/dkg/task.rs b/rust/src/frost/dkg/task.rs new file mode 100644 index 000000000..5f3ef044e --- /dev/null +++ b/rust/src/frost/dkg/task.rs @@ -0,0 +1,83 @@ +//! The unit of DKG work. +//! +//! A task is plain data: it names an action without performing it, so the +//! same value can be planned, displayed, re-validated against fresh state, +//! and only then executed. This is the discipline the note migration +//! ([`crate::migrate::task`]) established for a single wallet, extended to a +//! multi-party protocol where progress depends on other participants' +//! packages arriving. + +use super::state::DkgState; + +/// What kind of work a task represents. A driver uses this to decide how to +/// run it: a wait ends the pass, an effect carries a precondition that is +/// re-checked against fresh state before it runs. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TaskKind { + /// Nothing to do but wait — the pass stops here. + Time, + /// Touches the wallet database or the chain. + Effect, + /// Nothing left to do. + Terminal, +} + +/// One step of the DKG. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum DkgTask { + /// Not all n participant addresses are known yet. + WaitAddresses, + /// Create the private mailbox and shared broadcast accounts if missing. + EnsureAccounts, + /// Publish our outgoing package for `round` (0..3): produce it if our + /// secret is not stored yet, then send whatever bytes are staged. + PublishRound { round: u8 }, + /// Peer packages for `round` are still incoming. The all-n discipline: + /// every participant's package must arrive before the round advances, so + /// each wallet materializes the same complete key set. + WaitRound { round: u8 }, + /// dkg::part3 — derive our key package and the group public key package. + FinalizeKey, + /// Create the shared frost account holding the group spending key. + CreateFrostAccount, + /// Rekey the dkg_* rows onto the frost account and tear down the helper + /// accounts. The last effect of the protocol. + CompleteFinalize, + /// No further progress is possible. + Done, +} + +impl DkgTask { + pub fn kind(&self) -> TaskKind { + match self { + DkgTask::WaitAddresses | DkgTask::WaitRound { .. } => TaskKind::Time, + DkgTask::EnsureAccounts + | DkgTask::PublishRound { .. } + | DkgTask::FinalizeKey + | DkgTask::CreateFrostAccount + | DkgTask::CompleteFinalize => TaskKind::Effect, + DkgTask::Done => TaskKind::Terminal, + } + } + + /// Whether this task is still valid against freshly observed state. + /// + /// A task is planned from one snapshot and executed against another: a + /// sync lands, a peer's package arrives, another driver — the app and the + /// GraphQL server can drive the same wallet — advanced the protocol. + /// Re-checking here turns a stale plan into a re-plan rather than a + /// repeated publish. + pub fn is_satisfied_by(&self, s: &DkgState) -> bool { + match self { + DkgTask::WaitAddresses | DkgTask::WaitRound { .. } | DkgTask::Done => true, + DkgTask::EnsureAccounts => s.mailbox.is_none() || s.broadcast.is_none(), + DkgTask::PublishRound { round } => { + let rs = &s.rounds[*round as usize]; + !rs.secret_present || rs.pending == Some(*round) + } + DkgTask::FinalizeKey => !s.key_pkg_present, + DkgTask::CreateFrostAccount => s.frost_account.is_none(), + DkgTask::CompleteFinalize => true, + } + } +} diff --git a/rust/src/frost/mod.rs b/rust/src/frost/mod.rs index 9c658bd92..16e7cd810 100644 --- a/rust/src/frost/mod.rs +++ b/rust/src/frost/mod.rs @@ -3,6 +3,6 @@ pub mod protocol; pub mod sign; pub use protocol::{ - run_round, to_arb_memo, Broadcast, Dispatch, FrostBytes, FrostMessage, FrostSigMessage, - Indexed, NoSend, PK1Map, PK2Map, PerPeer, Round, RouteCtx, ToCoordinator, P, + to_arb_memo, Broadcast, Dispatch, FrostBytes, FrostMessage, FrostSigMessage, Indexed, NoSend, + PK1Map, PK2Map, PerPeer, Round, RouteCtx, ToCoordinator, P, }; diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index 5ab86629b..cec9b9894 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -15,7 +15,7 @@ use reddsa::frost::redpallas::{ keys::dkg::{round1, round2}, Identifier, PallasBlake2b512, Randomizer, }; -use sqlx::{sqlite::SqliteRow, Connection, Row, SqliteConnection}; +use sqlx::{sqlite::SqliteRow, Row, SqliteConnection}; use tracing::info; use zcash_keys::address::UnifiedAddress; use zcash_protocol::memo::Memo; @@ -311,9 +311,6 @@ pub trait Round { /// 4-byte memo prefix that identifies messages for this round. const PREFIX: [u8; 4]; - /// Minimum number of peer packages required to advance. - fn threshold(n: u8, t: u8) -> usize; - /// Pure: given the previous round's output, compute our secret and /// the outgoing package(s). fn produce(input: &Self::Input) -> Result<(Self::Secret, Self::Outgoing)>; @@ -355,11 +352,14 @@ pub trait Round { ) -> Result<Vec<(u8, Self::Public)>>; } -// ── Generic round engine ───────────────────────────────────────────────────── +// ── Memo ingest ────────────────────────────────────────────────────────────── /// Decode memos from `mailbox_account`, filter by `R::PREFIX`, deserialize /// each as a `FrostMessage`, and store the public package via `R::store_public`. -async fn decode_dkg_memos<R: Round>( +/// +/// Idempotent: `dkg_peers`' primary key `(account, round, from_id)` dedups, +/// so re-ingesting the same memos is a no-op. +pub async fn decode_dkg_memos<R: Round>( conn: &mut SqliteConnection, account: u32, mailbox_account: u32, @@ -390,77 +390,6 @@ async fn decode_dkg_memos<R: Round>( Ok(()) } -/// Drive one round of a FROST protocol. -/// -/// 1. Decodes incoming memos from `mailbox_account` and stores peer packages. -/// 2. If our own secret is not yet produced, calls `R::produce`, stores the -/// secret, and publishes outgoing packages to the network (in a DB tx). -/// 3. Checks whether enough peer packages have arrived (`R::threshold`). -/// 4. If ready, assembles and returns `R::Output` via `R::collect`. -/// Returns `None` when still waiting for peer messages. -#[allow(clippy::too_many_arguments)] -pub async fn run_round<R: Round>( - conn: &mut SqliteConnection, - account: u32, - n: u8, - t: u8, - self_id: u8, - funding_account: u32, - mailbox_account: u32, - input: R::Input, - route_ctx: &RouteCtx, - network: &Network, - client: &mut Client, - height: u32, -) -> Result<Option<R::Output>> { - // 1. Decode incoming peer packages from memos - decode_dkg_memos::<R>(conn, account, mailbox_account).await?; - - // 2. Produce our own secret + outgoing packages if not yet done - if R::load_secret(conn, account).await?.is_none() { - let (secret, outgoing) = - R::produce(&input).context(format!("Round produce failed for account {}", account))?; - let recipients_raw = outgoing.into_recipients(route_ctx)?; - - let mut tx = conn.begin().await?; - R::store_secret(&mut *tx, account, &secret).await?; - if !recipients_raw.is_empty() { - let recipients: Vec<(String, Vec<u8>)> = recipients_raw - .into_iter() - .map(|(addr, data)| { - let msg = FrostMessage { - from_id: self_id, - data, - }; - let bytes = msg.encode_with_prefix(&R::PREFIX)?; - Ok((addr, bytes)) - }) - .collect::<Result<_>>()?; - let refs: Vec<(&str, Vec<u8>)> = recipients - .iter() - .map(|(a, d)| (a.as_str(), d.clone())) - .collect(); - publish(network, &mut *tx, funding_account, client, height, &refs).await?; - } - tx.commit().await?; - } - - // 3. Check if enough peer packages have arrived - let peers = R::load_publics(conn, account).await?; - // Filter out our own package, then check threshold (accounting that we have our own package) - let peer_count = peers.iter().filter(|(id, _)| *id != self_id).count(); - if peer_count + 1 < R::threshold(n, t) { - // +1 for our own package - return Ok(None); - } - - // 4. Collect and advance to the next round - let secret = R::load_secret(conn, account).await?.unwrap(); - R::collect(input, secret, peers) - .context(format!("Round collect failed for account {}", account)) - .map(Some) -} - /// Wire message used during DKG rounds. #[derive(Encode, Decode)] pub struct FrostMessage { @@ -660,6 +589,61 @@ pub async fn get_mailbox_account( Ok((account, mailbox_address)) } +/// Seed of the shared broadcast account: a deterministic function of the +/// participant addresses, so every participant derives the same account. +fn broadcast_seed(addresses: &[String]) -> String { + let mut state = blake2b_simd::Params::new() + .hash_length(32) + .personal(b"Zcash__FROST_DKG") + .to_state(); + for a in addresses.iter() { + state.update(a.as_bytes()); + } + let hash = state.finalize(); + let m = Mnemonic::from_entropy(hash.as_ref()).expect("Failed to create mnemonic from hash"); + m.to_string() +} + +/// Look up the shared broadcast account without creating it. Returns the +/// account id and its encoded unified address, or `None` when the account +/// does not exist or any participant address is still missing. +pub async fn lookup_broadcast_account( + network: &Network, + connection: &mut SqliteConnection, + account: u32, +) -> Result<Option<(u32, String)>> { + let addresses = sqlx::query_as::<_, (String,)>( + "SELECT address FROM dkg_addresses WHERE account = ?1 ORDER BY from_id", + ) + .bind(account) + .fetch_all(&mut *connection) + .await?; + let addresses = addresses.into_iter().map(|row| row.0).collect::<Vec<_>>(); + if addresses.iter().any(|a| a.is_empty()) { + return Ok(None); + } + let seed = broadcast_seed(&addresses); + + let r = sqlx::query_as::<_, (u32, Vec<u8>)>( + "SELECT a.id_account, o.xvk FROM accounts a + JOIN orchard_accounts o ON a.id_account = o.account + WHERE seed = ?1", + ) + .bind(&seed) + .fetch_optional(&mut *connection) + .await?; + match r { + None => Ok(None), + Some((account, xvk)) => { + let fvk = FullViewingKey::from_bytes(&xvk.try_into().unwrap()) + .expect("Failed to create shared FVK"); + let address = fvk.address_at(0u64, Scope::External); + let ua = UnifiedAddress::from_receivers(Some(address), None, None).unwrap(); + Ok(Some((account, ua.encode(network)))) + } + } +} + /// Get (and create if needed) the shared broadcast address for /// communication between all participants in the group. /// It is derived from the hash of the participant private mailbox addresses. @@ -677,17 +661,7 @@ pub async fn get_coordinator_broadcast_account( .fetch_all(&mut *connection) .await?; let addresses = addresses.into_iter().map(|row| row.0).collect::<Vec<_>>(); - - let mut state = blake2b_simd::Params::new() - .hash_length(32) - .personal(b"Zcash__FROST_DKG") - .to_state(); - for a in addresses.iter() { - state.update(a.as_bytes()); - } - let hash = state.finalize(); - let m = Mnemonic::from_entropy(hash.as_ref()).expect("Failed to create mnemonic from hash"); - let seed = m.to_string(); + let seed = broadcast_seed(&addresses); let (account, broadcast_address) = loop { // Check if the account already exists diff --git a/rust/src/frost/sign.rs b/rust/src/frost/sign.rs index 1caacac08..7ff3d8e64 100644 --- a/rust/src/frost/sign.rs +++ b/rust/src/frost/sign.rs @@ -39,7 +39,6 @@ use crate::{ coin::Network, frost::{FrostSignParams, SigningStatus}, pay::PcztPackage, - sync::SYNCING, }, frost::dkg::{ delete_frost_state, get_coordinator_broadcast_account, get_dkg_params, get_mailbox_account, @@ -236,12 +235,6 @@ pub async fn do_sign_impl( }; info!("sign: found PCZT, signing is in progress"); - let guard = SYNCING.try_lock(); - if guard.is_err() { - info!("sign: sync already in progress, skipping"); - return Ok(()); - } - let birth_height = height.saturating_sub(10000) + 1; let params = get_sign_params(&mut *connection).await?; info!( @@ -382,7 +375,7 @@ pub async fn do_sign_impl( recipients.len() ); status.send(SigningStatus::SendingCommitment).await; - let txid = publish( + let txid = match publish( network, &mut tx, params.funding_account, @@ -390,7 +383,18 @@ pub async fn do_sign_impl( height, &recipients, ) - .await?; + .await + { + core::result::Result::Ok(txid) => txid, + // Funding note locked and its change not mined yet: drop the tx + // (nothing persisted) and wait for the next block. + Err(e) if crate::pay::plan::is_no_feasible_selection(&e) => { + info!("sign: commitment publish deferred; retry next block"); + status.send(SigningStatus::WaitingForFunds).await; + return Ok(()); + } + Err(e) => return Err(e), + }; info!("Published commitment transaction: {}", txid); } tx.commit().await?; @@ -521,7 +525,7 @@ pub async fn do_sign_impl( // we send all the sigpackages in one zcash transaction // with one output/memo per input/signature needed status.send(SigningStatus::SendingSigningPackage).await; - let txid = publish( + let txid = match publish( network, &mut tx, params.funding_account, @@ -529,7 +533,16 @@ pub async fn do_sign_impl( height, &recipients, ) - .await?; + .await + { + core::result::Result::Ok(txid) => txid, + Err(e) if crate::pay::plan::is_no_feasible_selection(&e) => { + info!("sign: sigpackage publish deferred; retry next block"); + status.send(SigningStatus::WaitingForFunds).await; + return Ok(()); + } + Err(e) => return Err(e), + }; info!("Published sigpackages transaction: {}", txid); // we got all the sigshares, commit them tx.commit().await?; @@ -590,7 +603,7 @@ pub async fn do_sign_impl( if dkg_params.id as u8 != params.coordinator { status.send(SigningStatus::SendingSignatureShare).await; - let txid = publish( + let txid = match publish( network, &mut tx, params.funding_account, @@ -598,7 +611,16 @@ pub async fn do_sign_impl( height, &recipients, ) - .await?; + .await + { + core::result::Result::Ok(txid) => txid, + Err(e) if crate::pay::plan::is_no_feasible_selection(&e) => { + info!("sign: sigshare publish deferred; retry next block"); + status.send(SigningStatus::WaitingForFunds).await; + return Ok(()); + } + Err(e) => return Err(e), + }; status.send(SigningStatus::SigningCompleted).await; info!("Published sigshares transaction: {}", txid); diff --git a/rust/src/graphql/frost.rs b/rust/src/graphql/frost.rs index 592f25199..b4f58a278 100644 --- a/rust/src/graphql/frost.rs +++ b/rust/src/graphql/frost.rs @@ -1,12 +1,10 @@ use bincode::config; use juniper::{FieldError, FieldResult}; -use sqlx::{query, sqlite::SqliteRow, Row}; use crate::{ api::{coin::Coin, frost::get_funding_account}, frost::{dkg::in_dkg, sign::in_sign}, graphql::Context, - sync::{synchronize_impl, DEFAULT_ACTIONS_PER_SYNC}, }; pub async fn dkg_start( @@ -67,32 +65,16 @@ pub async fn new_block(coin: Coin) -> anyhow::Result<()> { let account = get_funding_account(&mut connection).await?; tracing::info!("funding: {account}"); - let mut frost_accounts = - query("SELECT id_account FROM accounts WHERE name LIKE 'frost-%' AND internal = 1") - .map(|r: SqliteRow| r.get::<u32, _>(0)) - .fetch_all(&mut *connection) - .await?; - frost_accounts.push(account); - let height = synchronize_impl( - (), - frost_accounts, - height, - DEFAULT_ACTIONS_PER_SYNC, - 1, - 100, - false, - &coin, - ) - .await?; + let height = + crate::api::frost::sync_frost_accounts(&coin, &mut connection, account, height).await?; if in_dkg { - crate::frost::dkg::do_dkg_impl( + crate::frost::dkg::step::dkg_step( &coin.network(), &mut connection, - account, &mut client, height, - (), + account, ) .await?; } @@ -110,13 +92,14 @@ pub async fn do_dkg(context: &Context) -> FieldResult<bool> { let mut client = coin.client().await?; let height = client.latest_height().await?; let account = get_funding_account(&mut connection).await?; - crate::frost::dkg::do_dkg_impl( + let height = + crate::api::frost::sync_frost_accounts(coin, &mut connection, account, height).await?; + crate::frost::dkg::step::dkg_step( &coin.network(), &mut connection, - account, &mut client, height, - (), + account, ) .await?; Ok(true) diff --git a/rust/src/pay/error.rs b/rust/src/pay/error.rs index 51f7637b4..e2799e1b4 100644 --- a/rust/src/pay/error.rs +++ b/rust/src/pay/error.rs @@ -6,6 +6,12 @@ pub enum Error { InvalidPoolMask, #[error("Not enough funds, {0} more ZEC required")] NotEnoughFunds(String), + /// No spendable notes could be selected. In the FROST rounds this is a + /// transient "the change we just spent has not been mined yet" condition, + /// so it is a distinct variant the callers can recognize and treat as a + /// wait rather than a hard failure. + #[error("No feasible note selection found")] + NoFeasibleSelection, #[error("No Signing Key")] NoSigningKey, #[error(transparent)] diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index ccdf40324..d6b316d8c 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -232,6 +232,20 @@ fn decompose_address( anyhow::bail!("Unrecognized address pool"); } +/// Whether `e` (anywhere in its cause chain) is the transient +/// [`Error::NoFeasibleSelection`] raised by [`plan_transaction`]. The FROST +/// rounds use this to treat "the change we just spent is not mined yet" as a +/// wait instead of a hard error; the chain is walked so wrapping the error in +/// `.context(..)` does not hide it. +pub fn is_no_feasible_selection(e: &anyhow::Error) -> bool { + e.chain().any(|c| { + matches!( + c.downcast_ref::<crate::pay::error::Error>(), + Some(crate::pay::error::Error::NoFeasibleSelection) + ) + }) +} + #[allow(clippy::too_many_arguments)] pub async fn plan_transaction( network: &Network, @@ -493,7 +507,7 @@ pub async fn plan_transaction( recipient_pays_fee, recipients.first().map(|r| r.amount).unwrap_or(0), ) - .ok_or_else(|| anyhow!("No feasible note selection found"))?; + .ok_or_else(|| anyhow::Error::new(crate::pay::error::Error::NoFeasibleSelection))?; info!( "plan: select_notes succeeded — fee={}, change_pool={}, selected_inputs={}", diff --git a/tests/tests/test_dkg_2_of_3.py b/tests/tests/test_dkg_2_of_3.py new file mode 100644 index 000000000..b410d847f --- /dev/null +++ b/tests/tests/test_dkg_2_of_3.py @@ -0,0 +1,321 @@ +"""Test 2-of-3 FROST DKG using GraphQL API. + +The DKG is run by ALL n participants regardless of the threshold: rounds +advance only when every participant's package has arrived, so each wallet +materializes the same complete key set and any t-subset is valid for signing +later. This test proves the DKG completes for n=3, t=2. +""" + +import asyncio +import os + +import pytest +from gql import GraphQLRequest, gql + +from conftest import gql_client_factory +from dkg import DkgParticipant, poll_with_block_mining +from utils import get_current_height, mine_blocks, wait_for_blocks + + +@pytest.mark.asyncio +async def test_dkg_2_of_3(graphql_url, rpc_url, seed, zkool_binary, gql_client_factory): + """Test 2-of-3 FROST DKG: all 3 participants run the DKG, t=2 for signing.""" + if not seed: + pytest.skip("SEED not set") + + if not os.path.exists(zkool_binary): + pytest.skip(f"zkool_graphql binary not found at {zkool_binary}") + + N = 3 + T = 2 + DEFAULT_PORT = 8000 + PORT_BASE = 8101 + LWD_URL = "http://localhost:8137" + + participants = [] + default_participant = None + + async def cleanup(): + for p in participants: + await p.stop() + if default_participant: + await default_participant.stop() + for i in range(1, N + 1): + log_path = f"/tmp/graphql_{PORT_BASE + i - 1}.log" + if os.path.exists(log_path): + os.remove(log_path) + default_log = "/tmp/graphql_default_2of3.log" + if os.path.exists(default_log): + os.remove(default_log) + + try: + from utils import kill_existing_zkool_processes + + await kill_existing_zkool_processes() + + print("=== Setting up 2-of-3 FROST DKG Test ===") + print(f"Starting default instance on port {DEFAULT_PORT}") + default_db = "/tmp/regtest_dkg_default_2of3.db" + default_participant = DkgParticipant(DEFAULT_PORT, default_db, LWD_URL) + default_participant.start(zkool_binary) + await asyncio.sleep(2) + + print("\n=== Step 1: Start participant instances ===") + for i in range(1, N + 1): + port = PORT_BASE + i - 1 + db_path = f"/tmp/regtest_dkg_2of3_{i}.db" + participant = DkgParticipant(port, db_path, LWD_URL) + participant.start(zkool_binary) + participants.append(participant) + print(f"Started participant {i} on port {port}") + await asyncio.sleep(2) + + print("\n=== Step 2: Create funded wallet on default instance ===") + async with gql_client_factory(graphql_url) as client: + create_account_mutation = gql( + """ + mutation ($main: String!) { + createAccount(newAccount: { + name: "Main" + key: $main + aindex: 0 + useInternal: false + birth: 1 + }) + } + """ + ) + result = await client.execute_async( + GraphQLRequest(create_account_mutation, variable_values={"main": seed}) + ) + main_wallet = int(result["createAccount"]) + print(f"Funding wallet: {main_wallet}") + + sync_mutation = gql( + """ + mutation ($account: Int!) { + synchronizeAccount(idAccount: $account) + } + """ + ) + await client.execute_async( + GraphQLRequest(sync_mutation, variable_values={"account": main_wallet}) + ) + + balance_query = gql( + """ + query ($account: Int!) { + balanceByAccount(idAccount: $account) { + ironwood + } + } + """ + ) + result = await client.execute_async( + GraphQLRequest(balance_query, variable_values={"account": main_wallet}) + ) + funding_balance = result["balanceByAccount"]["ironwood"] + print(f"Funding wallet balance: {funding_balance}") + + print("\n=== Step 3: Initialize DKG for each participant (n=3, t=2) ===") + for i, participant in enumerate(participants, 1): + create_account_mutation = gql( + """ + mutation { + createAccount(newAccount: { + name: "DKG-Fund" + key: "" + aindex: 0 + useInternal: false + birth: 1 + }) + } + """ + ) + result = await participant.execute(GraphQLRequest(create_account_mutation)) + participant.funding_account = int(result["createAccount"]) + + address_query = gql( + """ + query ($account: Int!) { + addressByAccount(idAccount: $account) { + ironwood + } + } + """ + ) + result = await participant.execute( + GraphQLRequest( + address_query, variable_values={"account": participant.funding_account} + ) + ) + participant.funding_address = result["addressByAccount"]["ironwood"] + + print(f"Participant {i} funding account: {participant.funding_account}") + print(f"Participant {i} funding address: {participant.funding_address}") + + dkg_start_mutation = gql( + """ + mutation ($name: String!, $t: Int!, $n: Int!, $funding: Int!, $id: Int!) { + dkgStart( + name: $name + threshold: $t + participants: $n + messageAccount: $funding + idParticipant: $id + ) + } + """ + ) + result = await participant.execute( + GraphQLRequest( + dkg_start_mutation, + variable_values={ + "name": f"Dkg-Test-2of3-{i}", + "t": T, + "n": N, + "funding": participant.funding_account, + "id": i, + }, + ) + ) + participant.dkg_address = result["dkgStart"] + print(f"Participant {i} DKG address: {participant.dkg_address}") + + print("\n=== Step 4: Fund each participant's funding address ===") + async with gql_client_factory(graphql_url) as client: + recipients = [{"address": p.funding_address, "amount": "0.01"} for p in participants] + + pay_mutation = gql( + """ + mutation ($account: Int!, $recipients: [Recipient!]!) { + pay(idAccount: $account, payment: {recipients: $recipients}) + } + """ + ) + result = await client.execute_async( + GraphQLRequest( + pay_mutation, + variable_values={"account": main_wallet, "recipients": recipients}, + ) + ) + txid = result["pay"] + print(f"Funding transaction: {txid}") + + print("\n=== Step 5: Mine blocks for confirmation ===") + client = await participants[0].get_client() + height = await get_current_height(client) + await mine_blocks(rpc_url, 5) + await wait_for_blocks(client, height, 5) + print("Blocks mined") + + print("\n=== Step 6: Synchronize funding accounts ===") + sync_mutation = gql( + """ + mutation ($account: Int!) { + synchronizeAccount(idAccount: $account) + } + """ + ) + for i, participant in enumerate(participants, 1): + await participant.execute( + GraphQLRequest( + sync_mutation, variable_values={"account": participant.funding_account} + ) + ) + print(f"Synchronized participant {i} funding account") + + print("\n=== Step 7: Verify funding accounts received funds ===") + balance_query = gql( + """ + query ($account: Int!) { + balanceByAccount(idAccount: $account) { + ironwood + } + } + """ + ) + for i, participant in enumerate(participants, 1): + result = await participant.execute( + GraphQLRequest( + balance_query, variable_values={"account": participant.funding_account} + ) + ) + balance = result["balanceByAccount"]["ironwood"] + print(f"Participant {i} funding account balance: {balance}") + assert balance and balance != "0", f"Participant {i} has insufficient balance" + + print("\n=== Step 8: Exchange DKG addresses between participants ===") + set_address_mutation = gql( + """ + mutation ($id: Int!, $address: String!) { + dkgSetAddress(idParticipant: $id, address: $address) + } + """ + ) + for i, sender in enumerate(participants, 1): + for j, receiver in enumerate(participants, 1): + if i == j: + continue + + target_address = participants[j - 1].dkg_address + await sender.execute( + GraphQLRequest( + set_address_mutation, variable_values={"id": j, "address": target_address} + ) + ) + print(f"Participant {i} set address for participant {j}") + + print("\n=== Step 9: Execute DKG on all participants ===") + do_dkg_mutation = gql( + """ + mutation { + doDkg + } + """ + ) + for i, participant in enumerate(participants, 1): + await participant.execute(GraphQLRequest(do_dkg_mutation)) + print(f"Initiated DKG on participant {i}") + + print("\n=== Step 10: Wait for DKG completion ===") + + async def all_dkg_completed(): + return all(p.get_frost_account_id() is not None for p in participants) + + success = await poll_with_block_mining(all_dkg_completed, rpc_url, timeout=300) + if not success: + pytest.fail("DKG timed out") + print("All participants completed DKG successfully") + + print("\n=== Step 11: Verify shared address is same for all participants ===") + shared_address = None + address_query = gql( + """ + query ($account: Int!) { + addressByAccount(idAccount: $account) { + ironwood + } + } + """ + ) + for i, participant in enumerate(participants, 1): + frost_account = participant.get_frost_account_id() + assert frost_account is not None, f"Participant {i} has no FROST account" + result = await participant.execute( + GraphQLRequest(address_query, variable_values={"account": frost_account}) + ) + addr = result["addressByAccount"]["ironwood"] + print(f"Participant {i} shared address: {addr}") + if shared_address is None: + shared_address = addr + else: + assert addr == shared_address, f"Participant {i} has a different shared address" + + print(f"\n=== ✅ 2-of-3 DKG Test Passed! ===") + print(f"Shared FROST address: {shared_address}") + print("All 3 participants completed the DKG despite t=2:") + print(" - every wallet materialized the same complete key set") + + finally: + await cleanup() From e41ac43145bd62f4ced7e3aa3f7a3ee653aa8fa3 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Tue, 1 Sep 2026 14:44:53 +0800 Subject: [PATCH 138/189] test(pay): add unit tests for plan_transaction coin selection (#1238) Extract the pre-build half of plan_transaction into a pure, synchronous plan_outputs(PlanInputs) -> PlanOutputs so the note-selection and output-planning logic can be unit-tested without a DB, network client, or prover. This is a behavior-preserving refactor: plan_transaction fetches notes/height/DB context, calls plan_outputs, then builds/proves as before. Add coverage for the scenarios that regressed after the new coin-selection algorithm: - source pool selection (src_pools mask, confirmations, preselected) - unified addresses (single & mixed, explicit pool hint override) - TEX and transparent decomposition - max amount (smart-transparent sweep, recipient-pays-fee send-all) - locked/spent note exclusion (in-memory SQLite via create_schema) - memo encoding + per-recipient routing - multiple recipients across pools, fee deducted from first recipient only Also extend solve.rs with source-restriction, multi-output multi-pool, and all-notes-insufficient cases. 35 pay:: tests pass (was 10). --- build_number.txt | 2 +- rust/src/pay/plan.rs | 693 +++++++++++++++++++++++++++++++++++++++--- rust/src/pay/solve.rs | 101 ++++++ 3 files changed, 749 insertions(+), 47 deletions(-) diff --git a/build_number.txt b/build_number.txt index 53d5a5ad6..e5db9a27e 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -356 +362 diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index d6b316d8c..7fed6683b 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -246,26 +246,69 @@ pub fn is_no_feasible_selection(e: &anyhow::Error) -> bool { }) } -#[allow(clippy::too_many_arguments)] -pub async fn plan_transaction( - network: &Network, - connection: &mut SqliteConnection, - client: &mut Client, - account: u32, - src_pools: u8, - recipients: &[Recipient], - recipient_pays_fee: bool, - confirmations: Option<u32>, - smart_transparent: bool, - category: Option<u32>, - issuance: Option<&IssuanceInfo>, - migration: bool, - preselected: Option<&[u32]>, - anchor_height: Option<u32>, -) -> Result<PcztPackage> { - let mut input_pools = fetch_unspent_notes_by_pool(connection, account).await?; - let height = client.latest_height().await?; - let confirmations = confirmations.unwrap_or_default(); +/// Inputs to the pure planning core [`plan_outputs`]. +/// +/// Carries everything the note-selection and output-planning logic needs +/// without touching the DB, the network client, or the prover. `input_pools` +/// and `height` are the only values [`plan_transaction`] must fetch first; +/// everything else is passed straight through from its arguments. Isolating +/// this state is what lets the selection logic be unit-tested deterministically. +pub(crate) struct PlanInputs<'a> { + pub network: &'a Network, + pub height: u32, + pub input_pools: Vec<Vec<InputNote>>, + pub recipients: Vec<Recipient>, + pub src_pools: u8, + pub recipient_pays_fee: bool, + pub confirmations: u32, + pub smart_transparent: bool, + pub migration: bool, + pub issuance: Option<&'a IssuanceInfo>, + pub preselected: Option<&'a [u32]>, +} + +/// Result of the pure planning core: the selected inputs (with `remaining` +/// stamped on consumed notes), the recipient/change outputs, and the derived +/// quantities the builder half of [`plan_transaction`] still needs. +pub(crate) struct PlanOutputs { + pub input_pools: Vec<Vec<InputNote>>, + pub recipient_states: Vec<RecipientState>, + pub change: u64, + pub change_pool: u8, + /// Planned ZIP-317 fee. The builder recomputes the on-chain fee from its + /// own `FeeRule`, so this is not consumed by `plan_transaction`; it is + /// exposed for tests and callers that want to inspect the plan. + #[allow(dead_code)] + pub fee: u64, + pub has_pool: [bool; NUM_POOLS], + pub ironwood_active: bool, + pub orchard_note_version: orchard::NoteVersion, + pub price: Option<f64>, +} + +/// Pure note-selection and output-planning core of [`plan_transaction`]. +/// +/// Runs everything between "notes have been fetched" and "fetch tree states and +/// build the PCZT": source-pool masking, the smart-transparent / max-amount +/// transform, address decomposition, dust filtering, the [`solve::select_notes`] +/// coin-selection call, and the recipient/change/fee accounting. It performs no +/// I/O, so its behaviour is fully determined by [`PlanInputs`] and can be tested +/// without a database, network client, or proving keys. +pub(crate) fn plan_outputs(inp: PlanInputs) -> Result<PlanOutputs> { + let PlanInputs { + network, + height, + mut input_pools, + recipients, + src_pools, + recipient_pays_fee, + confirmations, + smart_transparent, + migration, + issuance, + preselected, + } = inp; + let max_height = height.saturating_sub(confirmations); for pool in 0..NUM_POOLS { if src_pools & (1 << pool) == 0 { @@ -282,7 +325,6 @@ pub async fn plan_transaction( } } - let recipients = recipients.to_vec(); let (mut input_pools, recipients, recipient_pays_fee) = if smart_transparent { let mut notes = std::mem::take(&mut input_pools[0]); // Group by taddress, pick one random address to shield @@ -359,10 +401,6 @@ pub async fn plan_transaction( .filter_map(|b| b.try_into().ok()) .collect(); - // ── Compute additional context ─────────────────────────────────────── - let dindex = get_account_dindex(connection, account).await?; - let hw = get_account_hw(&mut *connection, account).await?; - // Compute weighted average price from recipients that have a price set let mut total_amount = 0; let mut total_fiat = 0.0; @@ -378,12 +416,6 @@ pub async fn plan_transaction( None }; - let (use_internal,): (bool,) = - sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") - .bind(account) - .fetch_one(&mut *connection) - .await?; - // Remove ZEC dust notes (too small to pay for a single logical action). // ZSA amounts are denominated in their own asset and cannot pay fees, so // comparing them against the zatoshi fee threshold is meaningless. @@ -627,6 +659,92 @@ pub async fn plan_transaction( ); } + // Determine which pools are active in this transaction + let mut has_pool = [false; NUM_POOLS as usize]; + for pool in 1..NUM_POOLS { + let p = pool as u8; + has_pool[pool] = input_pools[pool].iter().any(|inp| inp.is_used()) + || recipient_states + .iter() + .any(|r| r.pool_mask.to_best_pool() == Some(p)) + || change_pool == p; + } + has_pool[3] &= ironwood_active; + // ZSA assets only exist in Orchard pool; ensure pool 2 is active + // when ZSA is present (covers issuance-only case with no ZSA notes). + has_pool[2] |= has_zsa; + + Ok(PlanOutputs { + input_pools, + recipient_states, + change, + change_pool, + fee, + has_pool, + ironwood_active, + orchard_note_version, + price, + }) +} + +#[allow(clippy::too_many_arguments)] +pub async fn plan_transaction( + network: &Network, + connection: &mut SqliteConnection, + client: &mut Client, + account: u32, + src_pools: u8, + recipients: &[Recipient], + recipient_pays_fee: bool, + confirmations: Option<u32>, + smart_transparent: bool, + category: Option<u32>, + issuance: Option<&IssuanceInfo>, + migration: bool, + preselected: Option<&[u32]>, + anchor_height: Option<u32>, +) -> Result<PcztPackage> { + let input_pools = fetch_unspent_notes_by_pool(connection, account).await?; + let height = client.latest_height().await?; + let confirmations = confirmations.unwrap_or_default(); + + // DB-sourced context needed only by the builder half below (change address + // and keys); the pure planning core does not touch the database. + let dindex = get_account_dindex(connection, account).await?; + let hw = get_account_hw(&mut *connection, account).await?; + let (use_internal,): (bool,) = + sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") + .bind(account) + .fetch_one(&mut *connection) + .await?; + + // ── Note selection and output planning (pure; unit-tested) ──────────── + let PlanOutputs { + input_pools, + mut recipient_states, + change, + change_pool, + has_pool, + ironwood_active, + orchard_note_version, + price, + .. + } = plan_outputs(PlanInputs { + network, + height, + input_pools, + recipients: recipients.to_vec(), + src_pools, + recipient_pays_fee, + confirmations, + smart_transparent, + migration, + issuance, + preselected, + })?; + + let zec_key = [0u8; 32]; + // ── Fetch tree states and anchors ──────────────────────────────────── let h = crate::sync::get_db_height(connection, account).await?; let anchor_height = anchor_height.unwrap_or(h.height); @@ -648,21 +766,6 @@ pub async fn plan_transaction( let orchard_anchor = eo.root(&OrchardHasher::default()); let ironwood_anchor = ei.root(&OrchardHasher::default()); - // Determine which pools are active in this transaction - let mut has_pool = [false; NUM_POOLS as usize]; - for pool in 1..NUM_POOLS { - let p = pool as u8; - has_pool[pool] = input_pools[pool].iter().any(|inp| inp.is_used()) - || recipient_states - .iter() - .any(|r| r.pool_mask.to_best_pool() == Some(p)) - || change_pool == p; - } - has_pool[3] &= ironwood_active; - // ZSA assets only exist in Orchard pool; ensure pool 2 is active - // when ZSA is present (covers issuance-only case with no ZSA notes). - has_pool[2] |= has_zsa; - // ── Fetch change address ───────────────────────────────────────────── let change_scope = if use_internal { 1 } else { 0 }; let mut change_address = @@ -1680,4 +1783,502 @@ mod tests { .unwrap()); assert!(!is_tex(&Network::Test, "tm9ofD7kHR7AF8MsJomEzLqGcrLCBkD9gDj").unwrap()); } + + // ------------------------------------------------------------------ + // Fixtures and helpers for the pure planning-core tests below. + // These exercise `plan_outputs` — the note-selection and output-planning + // logic lifted out of `plan_transaction` — with no DB, client, or prover. + // ------------------------------------------------------------------ + mod planning { + use super::super::*; + use crate::api::coin::Network; + use crate::pay::pool::ALL_POOLS; + use zcash_keys::address::UnifiedAddress; + + // Mainnet single-pool address fixtures. + const T_ADDR: &str = "t1VmmGiyjVNeCjxDZzg7vZmd99WyzVby9yC"; + const S_ADDR: &str = + "zs157m24pkqcq09edxz9p0p653xcsfpdpcspcad5wkkp3pq29hvc7h2uvs7wncakwqtl6jqkxn939p"; + const TEX_ADDR: &str = "tex1s2rt77ggv6q989lr49rkgzmh5slsksa9khdgte"; + + fn net() -> Network { + Network::Main + } + + /// A deterministic Orchard address derived from a fixed spending key. + fn orchard_addr() -> orchard::Address { + let sk = orchard::keys::SpendingKey::from_bytes([7u8; 32]) + .into_option() + .expect("valid orchard spending key"); + let fvk = orchard::keys::FullViewingKey::from(&sk); + fvk.address_at(0u32, orchard::keys::Scope::External) + } + + fn sapling_addr() -> sapling_crypto::PaymentAddress { + sapling_crypto::PaymentAddress::decode(&net(), S_ADDR).expect("valid sapling address") + } + + /// Orchard-only unified address. + fn ua_orchard() -> String { + UnifiedAddress::from_receivers(Some(orchard_addr()), None, None) + .unwrap() + .encode(&net()) + } + + /// Sapling-only unified address (still a UA container). + fn ua_sapling() -> String { + UnifiedAddress::from_receivers(None, Some(sapling_addr()), None) + .unwrap() + .encode(&net()) + } + + /// Mixed unified address carrying Orchard + Sapling receivers. + fn ua_mixed() -> String { + UnifiedAddress::from_receivers(Some(orchard_addr()), Some(sapling_addr()), None) + .unwrap() + .encode(&net()) + } + + fn note(id: u32, pool: u8, amount: u64, height: u32) -> InputNote { + InputNote { + id, + height, + amount, + remaining: amount, + pool, + id_asset: None, + asset_base: vec![], + taddress: (pool == 0).then_some(0), + } + } + + /// Wrap flat notes into the per-pool layout `plan_outputs` expects. + fn pools(notes: Vec<InputNote>) -> Vec<Vec<InputNote>> { + let mut p = vec![vec![]; NUM_POOLS]; + for n in notes { + p[n.pool as usize].push(n); + } + p + } + + fn recipient(address: &str, amount: u64) -> Recipient { + Recipient { + address: address.to_string(), + amount, + ..Recipient::default() + } + } + + /// Default `PlanInputs` for a plain (non-ZSA, non-migration) send at a + /// mainnet height where neither Ironwood nor NU7 is active. + fn plan_inputs<'a>( + network: &'a Network, + input_pools: Vec<Vec<InputNote>>, + recipients: Vec<Recipient>, + ) -> PlanInputs<'a> { + PlanInputs { + network, + height: 1_000_000, + input_pools, + recipients, + src_pools: ALL_POOLS, + recipient_pays_fee: false, + confirmations: 0, + smart_transparent: false, + migration: false, + issuance: None, + preselected: None, + } + } + + fn selected_ids(out: &PlanOutputs) -> Vec<u32> { + out.input_pools + .iter() + .flatten() + .filter(|n| n.is_used()) + .map(|n| n.id) + .collect() + } + + fn total_selected(out: &PlanOutputs) -> u64 { + out.input_pools + .iter() + .flatten() + .filter(|n| n.is_used()) + .map(|n| n.amount) + .sum() + } + + // Broad invariants every feasible plan must satisfy — the cheapest way + // to catch the "subtle" over/under-spend bugs. + fn assert_plan_balances(out: &PlanOutputs) { + let total_output: u64 = out.recipient_states.iter().map(|r| r.recipient.amount).sum(); + let total_input = total_selected(out); + assert!( + total_input >= total_output + out.fee, + "inputs {total_input} must cover outputs {total_output} + fee {}", + out.fee + ); + assert_eq!( + out.change, + total_input - total_output - out.fee, + "change must reconcile inputs, outputs and fee", + ); + // No selected ZEC note may sit below the per-action dust threshold. + for n in out.input_pools.iter().flatten().filter(|n| n.is_used()) { + let is_zec = n.asset_base.is_empty() || n.asset_base.iter().all(|&b| b == 0); + if is_zec { + assert!(n.amount >= COST_PER_ACTION, "dust note {} selected", n.id); + } + } + } + + // ---- Address decomposition: pool selection, UA single & mixed, TEX ---- + + #[test] + fn decompose_transparent_and_tex_target_pool_zero() { + let n = net(); + assert_eq!(decompose_address(T_ADDR, &n, false).unwrap().pool, 0); + let tex = decompose_address(TEX_ADDR, &n, false).unwrap(); + assert_eq!(tex.pool, 0); + assert!(matches!(tex.receiver, Receiver::P2pkh(_))); + } + + #[test] + fn decompose_sapling_targets_pool_one() { + assert_eq!(decompose_address(S_ADDR, &net(), false).unwrap().pool, 1); + } + + #[test] + fn decompose_ua_single_orchard_and_sapling() { + let n = net(); + assert_eq!(decompose_address(&ua_orchard(), &n, false).unwrap().pool, 2); + assert_eq!(decompose_address(&ua_sapling(), &n, false).unwrap().pool, 1); + } + + #[test] + fn decompose_ua_mixed_prefers_orchard() { + let n = net(); + // Mixed O+S UA prefers the Orchard receiver. + assert_eq!(decompose_address(&ua_mixed(), &n, false).unwrap().pool, 2); + // When Ironwood is active the same receiver routes to pool 3. + assert_eq!(decompose_address(&ua_mixed(), &n, true).unwrap().pool, 3); + } + + #[test] + fn ua_orchard_routes_output_through_orchard_pool() { + let n = net(); + let ua = ua_orchard(); + let input = plan_inputs( + &n, + pools(vec![note(1, 2, 1_000_000, 100)]), + vec![recipient(&ua, 100_000)], + ); + let out = plan_outputs(input).unwrap(); + assert_eq!(out.recipient_states.len(), 1); + assert_eq!(out.recipient_states[0].pool_mask.to_best_pool(), Some(2)); + assert_plan_balances(&out); + } + + #[test] + fn explicit_pool_hint_overrides_address_pool() { + let n = net(); + // Mixed UA would default to Orchard, but an explicit Sapling hint + // (bit 1) forces the output into the Sapling pool. + let mut r = recipient(&ua_mixed(), 100_000); + r.pools = Some(0b0010); + let input = plan_inputs( + &n, + pools(vec![note(1, 2, 1_000_000, 100)]), + vec![r], + ); + let out = plan_outputs(input).unwrap(); + assert_eq!(out.recipient_states[0].pool_mask.to_best_pool(), Some(1)); + } + + // ---- Source pool selection ---- + + #[test] + fn src_pools_mask_restricts_candidate_notes() { + let n = net(); + // Notes in every pool, but only Orchard (bit 2) is allowed. + let mut input = plan_inputs( + &n, + pools(vec![ + note(1, 0, 1_000_000, 100), + note(2, 1, 1_000_000, 100), + note(3, 2, 1_000_000, 100), + note(4, 3, 1_000_000, 100), + ]), + vec![recipient(S_ADDR, 100_000)], + ); + input.src_pools = 0b0100; // Orchard only + let out = plan_outputs(input).unwrap(); + // Every selected note must come from the Orchard pool. + for id in selected_ids(&out) { + assert_eq!(id, 3, "only the Orchard note may be selected"); + } + assert!(!selected_ids(&out).is_empty()); + assert_plan_balances(&out); + } + + #[test] + fn confirmations_filter_excludes_unconfirmed_notes() { + let n = net(); + // The only funding note is above max_height (height - confirmations), + // so no feasible selection exists. + let mut input = plan_inputs( + &n, + pools(vec![note(1, 2, 1_000_000, 999_999)]), + vec![recipient(S_ADDR, 100_000)], + ); + input.height = 1_000_000; + input.confirmations = 10; // max_height = 999_990 < note height + assert!(plan_outputs(input).is_err()); + } + + #[test] + fn preselected_restricts_to_given_note_ids() { + let n = net(); + let ids = [2u32]; + let mut input = plan_inputs( + &n, + pools(vec![ + note(1, 2, 1_000_000, 100), + note(2, 2, 1_000_000, 100), + ]), + vec![recipient(S_ADDR, 100_000)], + ); + input.preselected = Some(&ids); + let out = plan_outputs(input).unwrap(); + // Note 1 was filtered out entirely; only note 2 survives as a candidate. + let remaining: Vec<u32> = out.input_pools.iter().flatten().map(|n| n.id).collect(); + assert_eq!(remaining, vec![2]); + } + + // ---- Max amount (send-all) ---- + + #[test] + fn smart_transparent_sends_full_taddress_balance() { + let n = net(); + // Two t-notes on the same taddress form a single shielding group. + let mut input = plan_inputs( + &n, + pools(vec![note(1, 0, 300_000, 100), note(2, 0, 200_000, 100)]), + vec![recipient(S_ADDR, 0)], + ); + input.smart_transparent = true; + let out = plan_outputs(input).unwrap(); + // Everything is swept: the whole 500_000 becomes input, the recipient + // absorbs the fee, and no change is left behind. + assert_eq!(total_selected(&out), 500_000); + assert_eq!(out.recipient_states.len(), 1); + assert_eq!(out.recipient_states[0].recipient.amount, 500_000 - out.fee); + assert_eq!(out.change, 0); + assert_plan_balances(&out); + } + + #[test] + fn recipient_pays_fee_send_all_leaves_no_change() { + let n = net(); + // Send the entire single-note balance with the recipient paying the fee. + let mut input = plan_inputs( + &n, + pools(vec![note(1, 2, 1_000_000, 100)]), + vec![recipient(&ua_orchard(), 1_000_000)], + ); + input.recipient_pays_fee = true; + let out = plan_outputs(input).unwrap(); + assert_eq!(total_selected(&out), 1_000_000); + assert_eq!(out.recipient_states[0].recipient.amount, 1_000_000 - out.fee); + assert_eq!(out.change, 0); + assert_plan_balances(&out); + } + + // ---- Memos ---- + + #[test] + fn encode_memo_prefers_text_then_bytes() { + // Text memo wins. + let mut r = Recipient::default(); + r.user_memo = Some("hello".to_string()); + r.memo_bytes = Some(vec![1, 2, 3]); + assert!(encode_memo(&r).unwrap().is_some()); + + // Bytes memo used when no text. + let mut r = Recipient::default(); + r.memo_bytes = Some(vec![0xf6]); // canonical empty-memo byte + assert!(encode_memo(&r).unwrap().is_some()); + + // Nothing set → no memo. + assert!(encode_memo(&Recipient::default()).unwrap().is_none()); + } + + #[test] + fn memos_are_routed_to_the_right_recipient() { + let n = net(); + let mut r0 = recipient(S_ADDR, 100_000); + r0.user_memo = Some("first".to_string()); + let mut r1 = recipient(&ua_orchard(), 100_000); + r1.user_memo = Some("second".to_string()); + let input = plan_inputs(&n, pools(vec![note(1, 2, 2_000_000, 100)]), vec![r0, r1]); + let out = plan_outputs(input).unwrap(); + assert_eq!( + out.recipient_states[0].recipient.user_memo.as_deref(), + Some("first") + ); + assert_eq!( + out.recipient_states[1].recipient.user_memo.as_deref(), + Some("second") + ); + } + + // ---- Multiple recipients ---- + + #[test] + fn multi_recipient_across_pools_builds_one_output_each() { + let n = net(); + let input = plan_inputs( + &n, + pools(vec![note(1, 2, 5_000_000, 100)]), + vec![ + recipient(S_ADDR, 700_000), // Sapling output + recipient(&ua_orchard(), 300_000), // Orchard output + recipient(T_ADDR, 200_000), // transparent output + ], + ); + let out = plan_outputs(input).unwrap(); + assert_eq!(out.recipient_states.len(), 3); + assert_eq!(out.recipient_states[0].pool_mask.to_best_pool(), Some(1)); + assert_eq!(out.recipient_states[1].pool_mask.to_best_pool(), Some(2)); + assert_eq!(out.recipient_states[2].pool_mask.to_best_pool(), Some(0)); + assert_plan_balances(&out); + } + + #[test] + fn recipient_pays_fee_deducts_from_first_recipient_only() { + let n = net(); + let input = { + let mut i = plan_inputs( + &n, + pools(vec![note(1, 2, 5_000_000, 100)]), + vec![recipient(S_ADDR, 1_000_000), recipient(&ua_orchard(), 500_000)], + ); + i.recipient_pays_fee = true; + i + }; + let out = plan_outputs(input).unwrap(); + assert_eq!( + out.recipient_states[0].recipient.amount, + 1_000_000 - out.fee, + "fee comes out of the first recipient", + ); + assert_eq!( + out.recipient_states[1].recipient.amount, 500_000, + "later recipients are untouched", + ); + assert_plan_balances(&out); + } + + // ---- Failure path ---- + + #[test] + fn insufficient_funds_returns_no_feasible_selection() { + let n = net(); + let input = plan_inputs( + &n, + pools(vec![note(1, 2, 50_000, 100)]), + vec![recipient(S_ADDR, 10_000_000)], + ); + let err = match plan_outputs(input) { + Ok(_) => panic!("expected NoFeasibleSelection"), + Err(e) => e, + }; + assert!(is_no_feasible_selection(&err)); + } + } + + // ------------------------------------------------------------------ + // DB-backed test: the `locked = 0` / unspent filter in + // `fetch_unspent_notes_by_pool` — the one place the locked-note guard is + // actually exercised. Uses an in-memory SQLite so it stays fast. + // ------------------------------------------------------------------ + mod db { + use super::super::fetch_unspent_notes_by_pool; + use sqlx::{Connection, SqliteConnection}; + + async fn insert_note( + conn: &mut SqliteConnection, + id: u32, + account: u32, + pool: u8, + value: i64, + locked: bool, + id_asset: Option<i64>, + ) { + sqlx::query( + "INSERT INTO notes (id_note, height, account, pool, nullifier, tx, value, locked, id_asset) + VALUES (?, 100, ?, ?, ?, 0, ?, ?, ?)", + ) + .bind(id) + .bind(account) + .bind(pool) + .bind(vec![id as u8; 32]) // distinct, non-empty nullifier + .bind(value) + .bind(locked) + .bind(id_asset) + .execute(&mut *conn) + .await + .unwrap(); + } + + #[tokio::test] + async fn fetch_excludes_locked_spent_and_other_accounts() { + let mut conn = SqliteConnection::connect(":memory:").await.unwrap(); + crate::db::create_schema(&mut conn).await.unwrap(); + + // A ZSA asset so we can check the asset_base COALESCE branch. + let asset_base = vec![0xABu8; 32]; + sqlx::query( + "INSERT INTO assets (id_asset, asset_desc_hash, ik, asset_base, first_seen_height) + VALUES (1, X'00', X'00', ?, 1)", + ) + .bind(asset_base.clone()) + .execute(&mut conn) + .await + .unwrap(); + + insert_note(&mut conn, 1, 1, 1, 100_000, false, None).await; // included (Sapling) + insert_note(&mut conn, 2, 1, 2, 100_000, true, None).await; // excluded: locked + insert_note(&mut conn, 3, 1, 2, 100_000, false, None).await; // excluded: spent + insert_note(&mut conn, 4, 1, 0, 100_000, false, None).await; // included (transparent) + insert_note(&mut conn, 5, 2, 1, 100_000, false, None).await; // excluded: other account + insert_note(&mut conn, 6, 1, 2, 100_000, false, Some(1)).await; // included, ZSA asset + + // Note 3 has been spent. + sqlx::query( + "INSERT INTO spends (id_note, height, account, pool, tx, value) + VALUES (3, 101, 1, 2, 0, 100000)", + ) + .execute(&mut conn) + .await + .unwrap(); + + let pools = fetch_unspent_notes_by_pool(&mut conn, 1).await.unwrap(); + + let ids: Vec<u32> = pools.iter().flatten().map(|n| n.id).collect(); + assert_eq!(ids, vec![4, 1, 6], "only unspent, unlocked, own-account notes"); + + // Grouped by pool. + assert_eq!(pools[0].iter().map(|n| n.id).collect::<Vec<_>>(), vec![4]); + assert_eq!(pools[1].iter().map(|n| n.id).collect::<Vec<_>>(), vec![1]); + assert_eq!(pools[2].iter().map(|n| n.id).collect::<Vec<_>>(), vec![6]); + + // asset_base COALESCE: no id_asset → 32-zero ZEC sentinel; id_asset → real base. + let zec = &pools[1][0]; + assert_eq!(zec.asset_base, vec![0u8; 32]); + let zsa = &pools[2][0]; + assert_eq!(zsa.asset_base, vec![0xABu8; 32]); + } + } } diff --git a/rust/src/pay/solve.rs b/rust/src/pay/solve.rs index 35e1424da..1c8e4464b 100644 --- a/rust/src/pay/solve.rs +++ b/rust/src/pay/solve.rs @@ -1183,4 +1183,105 @@ mod tests { assert!(is_better_solution(100, 10, 100, 20)); assert!(!is_better_solution(101, 5, 100, 20)); } + + #[test] + fn test_source_restriction_only_uses_supplied_pool() { + // Caller has already masked out every pool except Orchard (pool 2), so + // the solver only ever sees Orchard candidates and must fund from them. + let notes = vec![ + Note { + pool: 2, + amount: 400_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 2, + amount: 300_000, + pool_index: 1, + asset_index: 0, + }, + ]; + let outputs = vec![Output { + pool: 1, + amount: 250_000, + asset_index: 0, + }]; + + let sel = select_notes(¬es, &outputs, 5_000, false, false, 0) + .expect("Orchard-only inputs should fund a Sapling output"); + + assert!( + sel.inputs.iter().all(|n| n.pool == 2), + "every selected note must come from the supplied Orchard pool", + ); + let total_input: u64 = sel.inputs.iter().map(|n| n.amount).sum(); + assert!(total_input >= 250_000 + sel.fee); + } + + #[test] + fn test_multi_output_multi_pool_selection() { + // Outputs land in two different pools; a single large Orchard note must + // cover both plus the fee, with change assigned to some pool. + let notes = vec![ + Note { + pool: 2, + amount: 5_000_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 1, + amount: 50_000, + pool_index: 0, + asset_index: 0, + }, + ]; + let outputs = vec![ + Output { + pool: 1, + amount: 700_000, + asset_index: 0, + }, + Output { + pool: 2, + amount: 300_000, + asset_index: 0, + }, + ]; + + let sel = select_notes(¬es, &outputs, 5_000, false, false, 0) + .expect("should fund both outputs"); + + let total_input: u64 = sel.inputs.iter().map(|n| n.amount).sum(); + let total_output: u64 = outputs.iter().map(|o| o.amount).sum(); + assert!(total_input >= total_output + sel.fee); + assert!((0..N_POOLS as u8).contains(&sel.change_pool)); + } + + #[test] + fn test_all_notes_still_insufficient_returns_none() { + // Even spending every note cannot reach the target: no solution exists. + let notes = vec![ + Note { + pool: 2, + amount: 100_000, + pool_index: 0, + asset_index: 0, + }, + Note { + pool: 1, + amount: 100_000, + pool_index: 0, + asset_index: 0, + }, + ]; + let outputs = vec![Output { + pool: 2, + amount: 1_000_000, + asset_index: 0, + }]; + + assert!(select_notes(¬es, &outputs, 5_000, false, false, 0).is_none()); + } } From afd46d2f495869b831ac9263c5f024280ff37804 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Tue, 1 Sep 2026 15:05:57 +0800 Subject: [PATCH 139/189] chore(main): release zkool 6.29.0 (#1239) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 18 ++++++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0f128e4fa..515ac7d61 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.28.1" + ".": "6.29.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 505b8cf4a..4d6d731b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [6.29.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.28.1...zkool-v6.29.0) (2026-09-01) + + +### Features + +* **frost:** drive DKG and signing from autosync instead of self-syncing ([#1236](https://github.com/hhanh00/zkool2/issues/1236)) ([623ded0](https://github.com/hhanh00/zkool2/commit/623ded005f7eb6b8aa448ff1247ad5b4c3a41103)) +* **vault:** sign out of Google when Cloud Vault is turned off ([277929a](https://github.com/hhanh00/zkool2/commit/277929a6cb55cc266a694d3b4aa157f23f3513df)) + + +### Bug Fixes + +* **frost:** lock spent notes at broadcast to stop duplicate-nullifier double-spends ([f80f27a](https://github.com/hhanh00/zkool2/commit/f80f27a7e248456e9e1e1a04e50e3483192e5839)) +* **frost:** report DKG round 0 and broadcast statuses in the UI ([#1230](https://github.com/hhanh00/zkool2/issues/1230)) ([deff307](https://github.com/hhanh00/zkool2/commit/deff307ce6312f26287d672111f7de5df8ea7fba)) +* **frost:** sync inside doDkg/doSign and hold off autosync ([0d0bbe3](https://github.com/hhanh00/zkool2/commit/0d0bbe3875417099e9e3d0755bade5dbf81a37c5)) +* **migrate:** stop migration stalling on Orchard totals of 0.005-0.0062 ZEC ([ef4db48](https://github.com/hhanh00/zkool2/commit/ef4db48157d545420936a9ee1903a3ff5972d3f5)) +* **pay:** serialize PCZTs with bincode standard() for interop ([381bb1d](https://github.com/hhanh00/zkool2/commit/381bb1d8a4d367518da5aabd8a569dd94a22c2b2)) +* **sync:** guard fetch_tx_details with the SYNCING lock ([f44c220](https://github.com/hhanh00/zkool2/commit/f44c220406f190ae6789f337b61653f179bf73a5)) + ## [6.28.1](https://github.com/hhanh00/zkool2/compare/zkool-v6.28.0...zkool-v6.28.1) (2026-08-27) diff --git a/build_number.txt b/build_number.txt index e5db9a27e..8c0a18696 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -362 +363 diff --git a/pubspec.yaml b/pubspec.yaml index 2380b296a..2d83958fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.28.1 # x-release-please-version +version: 6.29.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 8993da977..94ae9e992 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.28.1 +6.29.0 From 7639054bcc6f542e90a961d853ed610dfc786d22 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Wed, 2 Sep 2026 02:22:04 +0800 Subject: [PATCH 140/189] feat(account): collapse pool balances on tap, persisted in DB settings Tapping the pool-balance chips on the account page now toggles a collapsed view (compact "Pool Balances" row) in their place. The flag is persisted via the wallet-DB props table (collapse_pool_balances), following the same getProp/putProp pattern as other DB-backed settings. Claude-Session: https://claude.ai/code/session_01L2NZ7FoNCjY5ocStk25zwn --- lib/pages/account.dart | 20 +++++++++++++++++++- lib/store.dart | 12 ++++++++++++ lib/store.freezed.dart | 32 ++++++++++++++++++++++++++++++-- lib/store.g.dart | 2 +- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/pages/account.dart b/lib/pages/account.dart index 9ce8e1375..4f0d21252 100644 --- a/lib/pages/account.dart +++ b/lib/pages/account.dart @@ -341,7 +341,25 @@ class AccountViewPageState extends ConsumerState<AccountViewPage> with SingleTic const Gap(4), const ExchangeRateButton(), Gap(8), - BalanceWidget(account.balance), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => ref + .read(appSettingsProvider.notifier) + .setCollapsePoolBalances(!settings.collapsePoolBalances), + child: SizedBox( + width: double.infinity, + child: settings.collapsePoolBalances + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.expand_more, size: 18), + const Gap(4), + Text("Pool Balances", style: tt.bodySmall), + ], + ) + : BalanceWidget(account.balance), + ), + ), ]), ), Gap(8), diff --git a/lib/store.dart b/lib/store.dart index b905bdd6c..40d7a87db 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -398,6 +398,8 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { final paletteName = await prefs.getString("palette_name") ?? 'blue'; final darkMode = await prefs.getBool("dark_mode") ?? true; final txTableMode = await prefs.getBool("tx_table_mode") ?? false; + final collapsePoolBalances = + (hasDb ? await getProp(key: "collapse_pool_balances", c: c) : null) == "true"; final currency = (hasDb ? await getProp(key: "currency", c: c) : null) ?? "usd"; final price = ref.watch(priceProvider.notifier); price.setAutoFetchFx(getFx, coingecko, currency); @@ -426,6 +428,7 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { votingConfigUrl: votingConfigUrl, voteNodeUrl: voteNodeUrl, transactionTableMode: txTableMode, + collapsePoolBalances: collapsePoolBalances, currency: currency, ); } @@ -454,6 +457,13 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { )); } + Future<void> setCollapsePoolBalances(bool collapsed) async { + await putProp(key: "collapse_pool_balances", value: collapsed.toString(), c: coinContext.coin); + state = state.whenData((s) => s.copyWith( + collapsePoolBalances: collapsed, + )); + } + Future<void> setVotingConfigUrl(String url) async { await putProp(key: "voting_config_url", value: url, c: coinContext.coin); state = state.whenData((s) => s.copyWith( @@ -495,6 +505,7 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { await prefs.setString("palette_name", settings.paletteName); await prefs.setBool("dark_mode", settings.darkMode); await putProp(key: "currency", value: settings.currency, c: c); + await putProp(key: "collapse_pool_balances", value: settings.collapsePoolBalances.toString(), c: c); await putProp(key: "voting_config_url", value: settings.votingConfigUrl, c: c); await putProp(key: "vote_node_url", value: settings.voteNodeUrl, c: c); coinContext.set( @@ -583,6 +594,7 @@ sealed class AppSettings with _$AppSettings { required String paletteName, required bool darkMode, required bool transactionTableMode, + required bool collapsePoolBalances, required String currency, required String votingConfigUrl, required String voteNodeUrl, diff --git a/lib/store.freezed.dart b/lib/store.freezed.dart index b416a86da..aa97b2602 100644 --- a/lib/store.freezed.dart +++ b/lib/store.freezed.dart @@ -1346,6 +1346,7 @@ mixin _$AppSettings { String get paletteName; bool get darkMode; bool get transactionTableMode; + bool get collapsePoolBalances; String get currency; String get votingConfigUrl; String get voteNodeUrl; @@ -1396,6 +1397,8 @@ mixin _$AppSettings { other.darkMode == darkMode) && (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && + (identical(other.collapsePoolBalances, collapsePoolBalances) || + other.collapsePoolBalances == collapsePoolBalances) && (identical(other.currency, currency) || other.currency == currency) && (identical(other.votingConfigUrl, votingConfigUrl) || @@ -1428,6 +1431,7 @@ mixin _$AppSettings { paletteName, darkMode, transactionTableMode, + collapsePoolBalances, currency, votingConfigUrl, voteNodeUrl @@ -1435,7 +1439,7 @@ mixin _$AppSettings { @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, collapsePoolBalances: $collapsePoolBalances, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; } } @@ -1467,6 +1471,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> { String paletteName, bool darkMode, bool transactionTableMode, + bool collapsePoolBalances, String currency, String votingConfigUrl, String voteNodeUrl}); @@ -1507,6 +1512,7 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { Object? paletteName = null, Object? darkMode = null, Object? transactionTableMode = null, + Object? collapsePoolBalances = null, Object? currency = null, Object? votingConfigUrl = null, Object? voteNodeUrl = null, @@ -1596,6 +1602,10 @@ class _$AppSettingsCopyWithImpl<$Res> implements $AppSettingsCopyWith<$Res> { ? _self.transactionTableMode : transactionTableMode // ignore: cast_nullable_to_non_nullable as bool, + collapsePoolBalances: null == collapsePoolBalances + ? _self.collapsePoolBalances + : collapsePoolBalances // ignore: cast_nullable_to_non_nullable + as bool, currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable @@ -1735,6 +1745,7 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, + bool collapsePoolBalances, String currency, String votingConfigUrl, String voteNodeUrl)? @@ -1766,6 +1777,7 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, + _that.collapsePoolBalances, _that.currency, _that.votingConfigUrl, _that.voteNodeUrl); @@ -1811,6 +1823,7 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, + bool collapsePoolBalances, String currency, String votingConfigUrl, String voteNodeUrl) @@ -1841,6 +1854,7 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, + _that.collapsePoolBalances, _that.currency, _that.votingConfigUrl, _that.voteNodeUrl); @@ -1883,6 +1897,7 @@ extension AppSettingsPatterns on AppSettings { String paletteName, bool darkMode, bool transactionTableMode, + bool collapsePoolBalances, String currency, String votingConfigUrl, String voteNodeUrl)? @@ -1913,6 +1928,7 @@ extension AppSettingsPatterns on AppSettings { _that.paletteName, _that.darkMode, _that.transactionTableMode, + _that.collapsePoolBalances, _that.currency, _that.votingConfigUrl, _that.voteNodeUrl); @@ -1947,6 +1963,7 @@ class _AppSettings implements AppSettings { required this.paletteName, required this.darkMode, required this.transactionTableMode, + required this.collapsePoolBalances, required this.currency, required this.votingConfigUrl, required this.voteNodeUrl}); @@ -1995,6 +2012,8 @@ class _AppSettings implements AppSettings { @override final bool transactionTableMode; @override + final bool collapsePoolBalances; + @override final String currency; @override final String votingConfigUrl; @@ -2048,6 +2067,8 @@ class _AppSettings implements AppSettings { other.darkMode == darkMode) && (identical(other.transactionTableMode, transactionTableMode) || other.transactionTableMode == transactionTableMode) && + (identical(other.collapsePoolBalances, collapsePoolBalances) || + other.collapsePoolBalances == collapsePoolBalances) && (identical(other.currency, currency) || other.currency == currency) && (identical(other.votingConfigUrl, votingConfigUrl) || @@ -2080,6 +2101,7 @@ class _AppSettings implements AppSettings { paletteName, darkMode, transactionTableMode, + collapsePoolBalances, currency, votingConfigUrl, voteNodeUrl @@ -2087,7 +2109,7 @@ class _AppSettings implements AppSettings { @override String toString() { - return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; + return 'AppSettings(dbName: $dbName, net: $net, isLightNode: $isLightNode, lwd: $lwd, blockExplorer: $blockExplorer, syncInterval: $syncInterval, actionsPerSync: $actionsPerSync, transport: $transport, proxy: $proxy, coingecko: $coingecko, recovery: $recovery, needPin: $needPin, pinUnlockedAt: $pinUnlockedAt, offline: $offline, getFx: $getFx, qrSettings: $qrSettings, vault: $vault, expertMode: $expertMode, paletteName: $paletteName, darkMode: $darkMode, transactionTableMode: $transactionTableMode, collapsePoolBalances: $collapsePoolBalances, currency: $currency, votingConfigUrl: $votingConfigUrl, voteNodeUrl: $voteNodeUrl)'; } } @@ -2121,6 +2143,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> String paletteName, bool darkMode, bool transactionTableMode, + bool collapsePoolBalances, String currency, String votingConfigUrl, String voteNodeUrl}); @@ -2162,6 +2185,7 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { Object? paletteName = null, Object? darkMode = null, Object? transactionTableMode = null, + Object? collapsePoolBalances = null, Object? currency = null, Object? votingConfigUrl = null, Object? voteNodeUrl = null, @@ -2251,6 +2275,10 @@ class __$AppSettingsCopyWithImpl<$Res> implements _$AppSettingsCopyWith<$Res> { ? _self.transactionTableMode : transactionTableMode // ignore: cast_nullable_to_non_nullable as bool, + collapsePoolBalances: null == collapsePoolBalances + ? _self.collapsePoolBalances + : collapsePoolBalances // ignore: cast_nullable_to_non_nullable + as bool, currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable diff --git a/lib/store.g.dart b/lib/store.g.dart index 49d9f781d..d455bf5e5 100644 --- a/lib/store.g.dart +++ b/lib/store.g.dart @@ -619,7 +619,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'2892f9bcc456a390e78cdbc18d88bd913c00158c'; + r'ba8be8ca0f58edb24235312c2b9f3be1c11b0a30'; abstract class _$AppSettingsNotifier extends $AsyncNotifier<AppSettings> { FutureOr<AppSettings> build(); From 694a5c20de8ac0eec8b24f027885636d589f723d Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Wed, 2 Sep 2026 10:41:36 +0800 Subject: [PATCH 141/189] fix(vote): show ballot proposals immediately instead of after the vote-tree pre-sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The proposal page parsed the round status early but only painted after awaiting the best-effort vote-tree sync, which for a fresh round downloads the whole commitment tree with 60 s per-request timeouts — presenting as "No proposals found" for over a minute. Show proposals as soon as they parse, run the tree sync unawaited, add a loading state, and keep enrichment failures (weight/params/drafts) from blanking the ballot. --- lib/pages/voting_proposal.dart | 147 ++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 46 deletions(-) diff --git a/lib/pages/voting_proposal.dart b/lib/pages/voting_proposal.dart index 40e8dd759..a80ef686e 100644 --- a/lib/pages/voting_proposal.dart +++ b/lib/pages/voting_proposal.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; @@ -52,6 +53,7 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { List<_Proposal> _proposals = []; Map<int, int> _choices = {}; // proposal id -> option id final Set<int> _skipped = {}; + bool _loading = true; String? _error; String? _roundParamsJson; String? _roundName; @@ -77,6 +79,9 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { } Future<void> _load() async { + // Phase 1: fetch + parse the round status — the ballot content itself. + // Show it as soon as it parses; the slow best-effort work below must not + // delay the proposals. try { final c = coinContext.coin; final res = await votechainRoundStatus( @@ -97,69 +102,95 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { .whereType<_Proposal>() .toList(); - // Derive the authenticated round params for delegation_prepare from the - // cached config + the chain-reported snapshot fields. + // Snapshot fields and the round title come from the same response, so + // they can be shown immediately too. final snapshotHeight = _find(round, "snapshot_height"); final ncRoot = _find(round, "nc_root"); final nullifierImtRoot = _find(round, "nullifier_imt_root"); if (snapshotHeight is int && ncRoot is String && nullifierImtRoot is String) { _snapshotHeight = snapshotHeight; - _votingPower = - await votingEligibleWeight(snapshotHeight: snapshotHeight, c: c); _roundName = (_find(round, "title") ?? _find(round, "round_name") ?? _find(round, "name")) ?.toString() ?? widget.roundId; + } + _loading = false; + if (mounted) setState(() {}); + + // Phase 2: enrichment that must not block or blank the ballot. + // Failures surface as a dialog; the ballot stays usable. + try { final settings = await ref.read(appSettingsProvider.future); - if (settings.votingConfigUrl.isNotEmpty) { - _roundParamsJson = await votingRoundParamsJson( - source: settings.votingConfigUrl, - roundId: widget.roundId, - snapshotHeight: BigInt.from(snapshotHeight), - ncRoot: base64Decode(ncRoot), - nullifierImtRoot: base64Decode(nullifierImtRoot), - c: c, - ); + // Derive the authenticated round params for delegation_prepare from + // the cached config + the chain-reported snapshot fields. + if (snapshotHeight is int && ncRoot is String && nullifierImtRoot is String) { + _votingPower = + await votingEligibleWeight(snapshotHeight: snapshotHeight, c: c); + if (settings.votingConfigUrl.isNotEmpty) { + _roundParamsJson = await votingRoundParamsJson( + source: settings.votingConfigUrl, + roundId: widget.roundId, + snapshotHeight: BigInt.from(snapshotHeight), + ncRoot: base64Decode(ncRoot), + nullifierImtRoot: base64Decode(nullifierImtRoot), + c: c, + ); + } + if (mounted) setState(() {}); } - } - // Best-effort vote-tree pre-sync so the commit step doesn't wait on it. - // An unset Vote Node URL falls back to the vote chain server: the same - // REST API serves the commitment tree the sync pulls from. - final settings = await ref.read(appSettingsProvider.future); - final voteNodeUrl = - settings.voteNodeUrl.isNotEmpty ? settings.voteNodeUrl : widget.chainUrl; - if (voteNodeUrl.isNotEmpty) { - try { - await votingSyncTree( - roundId: widget.roundId, - voteNodeUrl: voteNodeUrl, - c: c, - ); - } on AnyhowException catch (_) { - // The round may not exist locally yet; the commit step syncs anyway. + // Best-effort vote-tree pre-sync so the commit step doesn't wait on + // it. An unset Vote Node URL falls back to the vote chain server: the + // same REST API serves the commitment tree the sync pulls from. Runs + // unawaited — the sync only warms the process-local tree, and the + // commit step syncs again if needed. + final voteNodeUrl = settings.voteNodeUrl.isNotEmpty + ? settings.voteNodeUrl + : widget.chainUrl; + if (voteNodeUrl.isNotEmpty) { + unawaited(() async { + try { + await votingSyncTree( + roundId: widget.roundId, + voteNodeUrl: voteNodeUrl, + c: c, + ); + } on AnyhowException catch (_) { + // The round may not exist locally yet; the commit step syncs + // anyway. + } + }()); } - } - final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); - if (drafts != null && drafts.isNotEmpty) { - final list = jsonDecode(drafts) as List<dynamic>; - for (final d in list) { - final map = d as Map<String, dynamic>; - final pid = map['proposal_id'] as int? ?? 0; - final choice = map['choice'] as int? ?? 0; - final numOptions = map['num_options'] as int? ?? 2; - if (choice == numOptions) { - _skipped.add(pid); - } else { - _choices[pid] = choice; + final drafts = await votingDraftsLoad(roundId: widget.roundId, c: c); + if (drafts != null && drafts.isNotEmpty) { + final list = jsonDecode(drafts) as List<dynamic>; + for (final d in list) { + final map = d as Map<String, dynamic>; + final pid = map['proposal_id'] as int? ?? 0; + final choice = map['choice'] as int? ?? 0; + final numOptions = map['num_options'] as int? ?? 2; + if (choice == numOptions) { + _skipped.add(pid); + } else { + _choices[pid] = choice; + } } } + if (mounted) setState(() {}); + } on AnyhowException catch (e) { + if (mounted) await showException(context, e.message); + } catch (e) { + if (mounted) await showException(context, "$e"); } - if (mounted) setState(() {}); } on AnyhowException catch (e) { + _loading = false; if (mounted) setState(() => _error = e.message); + } catch (e) { + // Decode/shape errors must not leave the page silently empty. + _loading = false; + if (mounted) setState(() => _error = "$e"); } } @@ -239,9 +270,31 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { return Scaffold( appBar: AppBar(title: Text(_roundName ?? widget.roundId)), body: _error != null - ? Center(child: Text(_error!)) + ? Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Text(_error!), + ), + FilledButton.tonal( + onPressed: () { + setState(() { + _error = null; + _loading = true; + }); + Future(_load); + }, + child: const Text("Retry"), + ), + ], + ), + ) : _proposals.isEmpty - ? const Center(child: Text("No proposals found for this round")) + ? (_loading + ? const Center(child: CircularProgressIndicator()) + : const Center(child: Text("No proposals found for this round"))) : ListView.builder( itemCount: _proposals.length, itemBuilder: (context, i) { @@ -287,7 +340,9 @@ class VotingProposalPageState extends ConsumerState<VotingProposalPage> { ); }, ), - bottomNavigationBar: SafeArea( + bottomNavigationBar: _loading || _error != null + ? null + : SafeArea( child: Padding( padding: const EdgeInsets.all(12), child: Column( From 059e980588554626add21ebb5da79acf9fc66cd2 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 3 Sep 2026 19:46:15 +0800 Subject: [PATCH 142/189] fix: scope witness consistency check to synced accounts The check ran against all accounts in the DB, including disabled ones with stale witness data, aborting syncs of unrelated accounts. --- rust/src/sync.rs | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/rust/src/sync.rs b/rust/src/sync.rs index c8ae2b0f5..d554b2c03 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -741,6 +741,7 @@ async fn shielded_sync_range( rx_cancel: broadcast::Receiver<()>, ) -> Result<()> { let accounts = accounts.to_vec(); + let account_ids: Vec<u32> = accounts.iter().map(|(a, _)| *a).collect(); let db_writer_task = { let (s, o, i) = get_tree_state(network, client, start - 1).await?; @@ -801,7 +802,7 @@ async fn shielded_sync_range( db_tx.commit().await.unwrap(); debug!("[db handler] stopped"); - check_witness_consistency(&mut writer_connection).await?; + check_witness_consistency(&mut writer_connection, &account_ids).await?; Ok::<_, anyhow::Error>(()) }); @@ -1129,24 +1130,37 @@ pub async fn trim_sync_data( } #[cfg(debug_assertions)] -pub async fn check_witness_consistency(connection: &mut SqliteConnection) -> Result<()> { - let notes = sqlx::query( - "WITH utxo AS (SELECT * FROM notes n LEFT JOIN spends s ON n.id_note = s.id_note WHERE s.id_note IS NULL), +pub async fn check_witness_consistency( + connection: &mut SqliteConnection, + accounts: &[u32], +) -> Result<()> { + if accounts.is_empty() { + return Ok(()); + } + let placeholders = vec!["?"; accounts.len()].join(", "); + let query = format!( + "WITH utxo AS (SELECT * FROM notes n LEFT JOIN spends s ON n.id_note = s.id_note WHERE s.id_note IS NULL), db_height AS (SELECT * FROM sync_heights) SELECT u.account, u.pool, u.height, u.value, d.height FROM utxo u JOIN db_height d ON d.account = u.account AND d.pool = u.pool LEFT JOIN witnesses w ON u.id_note = w.note AND w.account = u.account AND w.height = d.height - WHERE w.id_witness IS NULL AND u.pool <> 0 AND u.id_asset IS NULL") - .map(|r: SqliteRow| { - let account: u32 = r.get(0); - let pool: u8 = r.get(1); - let height: u32 = r.get(2); - let value: u64 = r.get(3); - let db_height: u32 = r.get(4); - (account, pool, height, value, db_height) - }) - .fetch_all(connection).await?; + WHERE w.id_witness IS NULL AND u.pool <> 0 AND u.id_asset IS NULL + AND u.account IN ({placeholders})"); + let mut q = sqlx::query(&query); + for account in accounts { + q = q.bind(account); + } + let notes = q + .map(|r: SqliteRow| { + let account: u32 = r.get(0); + let pool: u8 = r.get(1); + let height: u32 = r.get(2); + let value: u64 = r.get(3); + let db_height: u32 = r.get(4); + (account, pool, height, value, db_height) + }) + .fetch_all(connection).await?; for (account, pool, height, value, db_height) in notes.iter() { debug!("Missing witness for note {pool} {height} {value} of account {account} at height {db_height}"); @@ -1159,7 +1173,10 @@ pub async fn check_witness_consistency(connection: &mut SqliteConnection) -> Res } #[cfg(not(debug_assertions))] -pub async fn check_witness_consistency(_connection: &mut SqliteConnection) -> Result<()> { +pub async fn check_witness_consistency( + _connection: &mut SqliteConnection, + _accounts: &[u32], +) -> Result<()> { Ok(()) } From abc24fcc32c7ec42f9d0d00f26f0041976851d25 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Thu, 3 Sep 2026 23:59:27 +0800 Subject: [PATCH 143/189] test: add speculos-based Ledger emulator setup - default emulator endpoint 127.0.0.1:9999, overridable via ZEMU_HOST/ZEMU_PORT - drop obsolete Zondax CLA 0x85 tests; add ledger_app_version smoke test for the new Rust app-zcash protocol (CLA 0xE0), ignored unless emulator is up - misc/ledger scripts (setup, build, run-emulator) and README documenting the full setup for replication on other machines --- .gitignore | 1 + misc/ledger/build.sh | 15 ++ misc/ledger/run-emulator.sh | 42 ++++ misc/ledger/setup.sh | 15 ++ rust/src/ledger/README.md | 134 +++++++++++ rust/src/ledger/tests.rs | 436 ++--------------------------------- rust/src/ledger/transport.rs | 7 +- 7 files changed, 229 insertions(+), 421 deletions(-) create mode 100755 misc/ledger/build.sh create mode 100755 misc/ledger/run-emulator.sh create mode 100755 misc/ledger/setup.sh create mode 100644 rust/src/ledger/README.md diff --git a/.gitignore b/.gitignore index 6f32bf77d..393281904 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ docs/ ios/build/ *.sh +!misc/ledger/*.sh .env /certs/ node_modules/ diff --git a/misc/ledger/build.sh b/misc/ledger/build.sh new file mode 100755 index 000000000..478d76c93 --- /dev/null +++ b/misc/ledger/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Build the Zcash Ledger app in the dockerized toolchain. +# APP_DIR: app checkout (default: ~/projects/ledger-dev/app-zcash) +# MODEL: build model (nanox | nanosplus | stax | flex | apex_p), default nanosplus + +APP_DIR="${APP_DIR:-$HOME/projects/ledger-dev/app-zcash}" +MODEL="${MODEL:-nanosplus}" + +docker run --rm -v "$APP_DIR":/app \ + ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest \ + cargo ledger build "$MODEL" + +echo "Built: $APP_DIR/target/$MODEL/release/zcash" diff --git a/misc/ledger/run-emulator.sh b/misc/ledger/run-emulator.sh new file mode 100755 index 000000000..7fe990c98 --- /dev/null +++ b/misc/ledger/run-emulator.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Start the speculos emulator running the built Zcash Ledger app. +# APP_DIR: app checkout (default: ~/projects/ledger-dev/app-zcash) +# MODEL: speculos model (nanox | nanosp | stax | flex | apex_p), default nanosp +# BUILD_MODEL: build model directory under target/ (default nanosplus for nanosp) +# SEED: device seed (deterministic test seed by default) +# +# Endpoints: +# http://localhost:9999 JSON APDU (POST {"apduHex": "<hex>"}) - what zkool speaks +# http://localhost:5000 device screen / REST API + +APP_DIR="${APP_DIR:-$HOME/projects/ledger-dev/app-zcash}" +MODEL="${MODEL:-nanosp}" +BUILD_MODEL="${BUILD_MODEL:-nanosplus}" +SEED="${SEED:-glory promote mansion idle axis finger extra february uncover one trip resource lawn turtle enact monster seven myth punch hobby comfort wild raise skin}" +ELF="$APP_DIR/target/$BUILD_MODEL/release/zcash" + +if [ ! -f "$ELF" ]; then + echo "Not found: $ELF (run build.sh first)" >&2 + exit 1 +fi + +docker rm -f speculos-zcash >/dev/null 2>&1 || true + +docker run -d --name speculos-zcash \ + -p 9999:9998 -p 5000:5000 \ + -v "$APP_DIR/target":/app/target \ + -w /speculos \ + --entrypoint bash \ + ghcr.io/ledgerhq/speculos:latest -c " + sed 's/HOST = \"127.0.0.1\"/HOST = \"0.0.0.0\"/' /speculos/tools/ledger-live-http-proxy.py > /tmp/proxy.py && + python ./speculos.py --model $MODEL --seed \"$SEED\" --display headless /app/target/$BUILD_MODEL/release/zcash & + exec python /tmp/proxy.py" >/dev/null + +sleep 5 +docker logs speculos-zcash 2>&1 | tail -5 +echo +echo "APDU endpoint : http://localhost:9999" +echo "Screen UI : http://localhost:5000" +echo "Stop : docker rm -f speculos-zcash" diff --git a/misc/ledger/setup.sh b/misc/ledger/setup.sh new file mode 100755 index 000000000..f9ed66348 --- /dev/null +++ b/misc/ledger/setup.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# One-time setup: clone the Zcash Ledger app and pull the Docker images. +# APP_DIR overrides where the app is cloned (default: ~/projects/ledger-dev/app-zcash) + +APP_DIR="${APP_DIR:-$HOME/projects/ledger-dev/app-zcash}" + +mkdir -p "$(dirname "$APP_DIR")" +if [ ! -d "$APP_DIR" ]; then + git clone --depth 1 https://github.com/LedgerHQ/app-zcash.git "$APP_DIR" +fi + +docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest +docker pull ghcr.io/ledgerhq/speculos:latest diff --git a/rust/src/ledger/README.md b/rust/src/ledger/README.md new file mode 100644 index 000000000..9f8a806a2 --- /dev/null +++ b/rust/src/ledger/README.md @@ -0,0 +1,134 @@ +# Ledger emulator dev setup + +How to build the Zcash Ledger app, run it in the speculos emulator, and verify +it from zkool's Rust test suite. Everything runs in Docker; no local toolchain +or physical Ledger is needed. + +The helper scripts live in `misc/ledger/` (`setup.sh`, `build.sh`, +`run-emulator.sh`). Their knobs (`APP_DIR`, `MODEL`, `BUILD_MODEL`, `SEED`) +are documented at the top of each script. + +## Architecture + +``` +zkool (cargo test --features zemu) + | HTTP POST {"apduHex": "<hex>"} (ledger_transport_zemu::TransportZemuHttp) + v +host port 9999 --> container port 9998: JSON-HTTP proxy (ledger-live-http-proxy.py) + | binary length-prefixed frames + v + container port 9999: speculos APDU server + v + speculos (QEMU, model nanosp) running app-zcash +``` + +The app under emulation is the Rust rewrite of +[LedgerHQ/app-zcash](https://github.com/LedgerHQ/app-zcash) (v3.9.3+). It +speaks CLA `0xE0` (Bitcoin-app style) with Zcash extensions (INS `0x50` VK, +`0x51` shielded address, `0x52`-`0x59` PCZT/Ironwood). zkool's app-layer code +(`builder.rs`, `fvk.rs`, ...) still speaks the legacy Zondax CLA `0x85` +protocol and needs migration; only the version smoke test speaks `0xE0` today. +The transport layer is protocol-agnostic and unchanged. + +## Prerequisites + +- Docker Desktop installed and running (`docker info` succeeds). +- Git. + +Do NOT pull the images with `--platform linux/amd64` on Apple Silicon: both +images are multi-arch and a plain pull selects the native arm64 variant. +Forcing amd64 fails at runtime with `exec format error` unless Rosetta is +enabled in Docker Desktop. + +## 1. One-time setup + +```bash +misc/ledger/setup.sh +``` + +Clones the app to `~/projects/ledger-dev/app-zcash` (override with `APP_DIR`) +and pulls both images. + +## 2. Build the app + +```bash +misc/ledger/build.sh +``` + +Build model names: `nanox`, `nanosplus`, `stax`, `flex`, `apex_p` (default +`nanosplus`). Output: `~/projects/ledger-dev/app-zcash/target/nanosplus/release/zcash`. + +## 3. Run the emulator + +```bash +misc/ledger/run-emulator.sh +``` + +Why the container is started the way it is (do not simplify): + +- Build model `nanosplus` maps to speculos model `nanosp`. +- The JSON-HTTP proxy (`ledger-live-http-proxy.py`) is what serves the + `{"apduHex": ...}` protocol zkool's transport speaks; speculos' own port + 9999 is binary-framed. +- The proxy binds `127.0.0.1` by default, which Docker port-forwarding cannot + reach — hence the `sed` to `0.0.0.0` inside the container. +- `-p 9999:9998`: host 9999 (what zkool connects to) -> proxy on container 9998. +- The seed is a fixed test seed so derived addresses are reproducible. + +The device screen is available for approvals at `http://localhost:5000` +(open `/swagger`, use the screenshot/button endpoints). + +## 4. Verify the emulator + +```bash +curl -s -m 5 -X POST http://127.0.0.1:9999 \ + -H 'Content-Type: application/json' -d '{"apduHex": "e0c4000000"}' +``` + +Expected: + +```json +{"data": "38300309030100039000", "error": null} +``` + +`e0c4000000` is `GET_FIRMWARE_VERSION` (CLA 0xE0, INS 0xC4); the answer is the +legacy Zondax version format (`0x38 0x30`, version 3.9.3) plus SW `0x9000`. + +## 5. Run the zkool test + +From `rust/`: + +```bash +cargo test --features zemu -- --ignored --nocapture ledger_app_version +``` + +Expected: + +``` +app version response: 3830030903010003 +test ledger::tests::ledger_app_version ... ok +``` + +The test lives in `rust/src/ledger/tests.rs` and is `#[ignore]`-gated so +regular `cargo test` runs do not require the emulator. + +- `ZEMU_HOST` / `ZEMU_PORT` env vars override the endpoint (defaults + `127.0.0.1:9999`), e.g. to point at an emulator on another machine. +- On macOS this hits the local speculos container by design; a physical + device is not part of this setup. + +## 6. Stop + +```bash +docker rm -f speculos-zcash +``` + +## Troubleshooting + +| Symptom | Cause / fix | +| --- | --- | +| `exec /usr/local/bin/python: exec format error` | amd64 image pulled on Apple Silicon: re-pull without `--platform`, or enable Rosetta in Docker Desktop | +| `invalid choice: 'nanosplus'` from speculos | speculos model is `nanosp`; build model is `nanosplus` | +| curl connects but empty reply | proxy not running or still bound to `127.0.0.1` (see step 3), or wrong port mapping (`9999:9998`, not `9999:9999`) | +| `Connection refused` on container 9998 | the proxy crashed; check `docker logs speculos-zcash` | +| test hangs | emulator not up: `docker ps --filter name=speculos-zcash`, then re-run step 4 | diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index 64b9c0593..a0836e968 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -1,435 +1,31 @@ -use bech32::{Bech32m, Hrp}; -use byteorder::LE; -use pczt::{ - roles::{ - low_level_signer::Signer, spend_finalizer::SpendFinalizer, - tx_extractor::TransactionExtractor, - }, - Pczt, -}; -use secp256k1::{ecdsa::Signature, PublicKey}; -use sqlx::{Acquire, SqlitePool}; -use std::{fs::File, io::BufReader}; -use zcash_keys::encoding::AddressCodec as _; -use zcash_script::script::Evaluable; -use zcash_transparent::address::TransparentAddress; - -use sapling_crypto::{keys::FullViewingKey, Diversifier, PaymentAddress}; -use zcash_address::unified::{self, Encoding, Ufvk}; -use zcash_protocol::consensus::MainNetwork; - -use crate::{ - api::{coin::Network, pay::PcztPackage}, - ledger::{ - hashers::{ - create_hasher, header_hasher, orchard_hasher, output_hasher, prevout_hasher, - sequence_hasher, spend_hasher, transparent_hasher, zoutput_hasher, - }, - transport::{APDUCommand, Device, LEDGER_ZEMU}, - }, - IntoAnyhow as _, -}; +use crate::ledger::transport::{APDUCommand, Device, LEDGER_ZEMU}; use super::*; +/// Smoke test for the speculos emulator (or a device via ZEMU_HOST/ZEMU_PORT). +/// Speaks the new app-zcash protocol (CLA 0xE0) and only checks that the app +/// answers GET_FIRMWARE_VERSION with the legacy Zondax version format. +/// Run with the emulator up: `cargo test --features zemu -- --ignored` #[tokio::test] -pub async fn get_device_info() -> LedgerResult<()> { - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - let res = ledger - .long_execute( - &APDUCommand { - cla: 0x85, - ins: 0x00, - p1: 0, - p2: 0, - data: vec![], - }, - &[vec![]], - ) - .await?; - assert_eq!(res.retcode, 0x9000); - println!("{}", hex::encode(&res.data)); - Ok(()) -} - -#[tokio::test] -pub async fn get_taddress() -> LedgerResult<()> { - let get_address = APDUCommand { - cla: 0x85, - ins: 0x01, - p1: 0, - p2: 0, - data: vec![], - }; - let mut data = vec![]; - data.write_u32::<LE>(44 | 0x80000000)?; - data.write_u32::<LE>(133 | 0x80000000)?; - data.write_u32::<LE>(0x80000000)?; - data.write_u32::<LE>(0)?; - data.write_u32::<LE>(0)?; - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - let res = ledger.long_execute(&get_address, &[data]).await?; - assert_eq!(res.retcode, 0x9000); - let pk = &res.data[0..33]; - println!("{}", hex::encode(pk)); - let address = &res.data[33..]; - let pk = bech32::encode::<Bech32m>(Hrp::parse_unchecked("zpk"), pk).anyhow()?; - println!("{pk}"); - let address = String::from_utf8(address.to_vec()).anyhow()?; - println!("{address}"); - assert_eq!(address, "t1h31WzbruQhnwHg4XDJ5anLM7CAtwjXmPt"); - Ok(()) -} - -#[tokio::test] -pub async fn get_fvk() -> LedgerResult<()> { - // this test will fail with "Inner Ledger error" the first time it runs - // because user needs to confirm on the device - // Run it once, then go to the web ui and confirm the operation - // Run it again and it should pass +#[ignore] +pub async fn ledger_app_version() -> LedgerResult<()> { let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); let res = ledger .execute(APDUCommand { - cla: 0x85, - ins: 0xF3, - p1: 1, - p2: 0, - data: 0x80000000u32.to_le_bytes().to_vec(), - }) - .await?; - assert_eq!(res.retcode, 0x9000); - let fvk = hex::encode(&res.data); - println!("{fvk}"); - assert_eq!(fvk, "d17091f057e2d641328172642f06f821893a564ec8ab98fdd4ca462b8791de5c788c96b31e5e476e954c1a18bd4f1278358924ec9a22d096fe3954d815e353605940cfcf8388fb5e54ebc6f1c9f75a5eddf35227e3d1c4ef003e6f64cd7672db"); - Ok(()) -} - -#[tokio::test] -pub async fn get_address() -> LedgerResult<()> { - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - let res = ledger - .execute(APDUCommand { - cla: 0x85, - ins: 0x11, + cla: 0xE0, + ins: 0xC4, p1: 0, p2: 0, - data: 0x80000000u32.to_le_bytes().to_vec(), + data: vec![], }) .await?; - assert_eq!(res.retcode, 0x9000); - let address = hex::encode(&res.data); - println!("{address}"); - assert_eq!(address, "a7b6aa86c0c01e5cb4c2285e1d5226c4121687100e3ada3ad60c420516ecc7aeae321e74f1db380bfea40b7a733135376d3234706b71637130396564787a397030703635337863736670647063737063616435776b6b70337071323968766337683275767337776e63616b7771746c366a716b786e39333970"); - Ok(()) -} - -#[test] -fn payment_address() -> LedgerResult<()> { - let address_hex = hex::decode("a7b6aa86c0c01e5cb4c2285e1d5226c4121687100e3ada3ad60c420516ecc7aeae321e74f1db380bfea40b7a733135376d3234706b71637130396564787a397030703635337863736670647063737063616435776b6b70337071323968766337683275767337776e63616b7771746c366a716b786e39333970").anyhow()?; - let address = &address_hex[0..43]; - let div = hex::encode(&address_hex[0..11]); - println!("{div}"); - let pa = PaymentAddress::from_bytes(&address.try_into().unwrap()).unwrap(); - println!("{}", pa.encode(&MainNetwork)); - let address = String::from_utf8(address_hex[43..].to_vec()).anyhow()?; - println!("{address}"); + assert_eq!(res.retcode, 0x9000, "app did not answer 0x9000"); assert_eq!( - address, - "zs157m24pkqcq09edxz9p0p653xcsfpdpcspcad5wkkp3pq29hvc7h2uvs7wncakwqtl6jqkxn939p" - ); - Ok(()) -} - -#[test] -pub fn ufvk() -> LedgerResult<()> { - let fvk = hex::decode("de514bb8eba2793731926578513d8ea724d1e4b21fcf8a53b7236711a27ba7bf05eda7736c88143790f66a1793f117100b8b7d0c60c115ee7a2d0e189c4fb416a5077c6d42e7c18de0353751b361a55e90fccbbef3d12fafba1d43a4367feefa").anyhow()?; - let sapfvk = FullViewingKey::read(&*fvk)?; - let div: [u8; 11] = hex::decode("a7b6aa86c0c01e5cb4c228") - .anyhow()? - .try_into() - .unwrap(); - let pa = sapfvk.vk.to_payment_address(Diversifier(div)).unwrap(); - println!("{}", pa.encode(&MainNetwork)); - let mut dk = [42u8; 128]; // arbitrary dk because we don't know the real one from the Ledger - dk[0..96].clone_from_slice(&fvk); - let sfvk = unified::Fvk::Sapling(dk); - let ufvk = Ufvk::try_from_items(vec![sfvk]).anyhow()?; - let ufvk = ufvk.encode(&zcash_protocol::consensus::NetworkType::Main); - println!("{ufvk}"); - assert_eq!(ufvk, "uview1hytkw2afs80j0zvj3w0nutqs58rpf2qvuygw47k3qmjqj8w9vlwxjp00dpk8tfp6e5jdq0zavetsu5jugxpsqqwssjeh9lxsnugenctuyjhf6my639pv7agspcsvmgk5upj2zjkwm3u98h807sdj5dkvtrle5x2uajl6gzj4ryhuz0sfm2j3g95hm6az2an4tknu0yecmefsrrwqxv6fxgwqpf44awj6fnrhxlytcut20faw"); - Ok(()) -} - -#[tokio::test] -pub async fn sign_transparent() -> LedgerResult<()> { - let stage = 2; - let network = Network::Main; - let pool = SqlitePool::connect("ledger.db").await.anyhow()?; - let mut connection = pool.acquire().await.anyhow()?; - let connection = connection.acquire().await.anyhow()?; - let mut db_tx = connection.begin().await.anyhow()?; - let account = 1; - let s_account = 2; - - let file = File::open("t2s.bin")?; - let package = bincode::decode_from_reader::<PcztPackage, _, _>( - BufReader::new(file), - bincode::config::legacy(), - ) - .anyhow()?; - let pczt = Pczt::parse(&package.pczt).unwrap(); - let (pk, address): (Vec<u8>, String) = - sqlx::query_as("SELECT pk, address FROM transparent_address_accounts WHERE account = ?1") - .bind(account) - .fetch_one(&mut *db_tx) - .await - .anyhow()?; - let pk = PublicKey::from_slice(&pk).anyhow()?; - let address = TransparentAddress::decode(&network, &address).anyhow()?; - - let (xvk,): (Vec<u8>,) = sqlx::query_as("SELECT xvk FROM sapling_accounts WHERE account = ?1") - .bind(s_account) - .fetch_one(&mut *db_tx) - .await - .anyhow()?; - let xvk = FullViewingKey::read(&*xvk)?; - let ovk = xvk.ovk; - - let mut buffers = vec![]; - buffers.push(vec![]); - - let mut data = vec![]; - data.write_u8(pczt.transparent().inputs().len() as u8)?; - data.write_u8(pczt.transparent().outputs().len() as u8)?; - data.write_u8(pczt.sapling().spends().len() as u8)?; - data.write_u8(pczt.sapling().outputs().len() as u8)?; - buffers.push(data); - - println!( - "{} {}", - pczt.transparent().inputs().len(), - pczt.transparent().outputs().len() - ); - println!( - "{} {}", - pczt.sapling().spends().len(), - pczt.sapling().outputs().len() + &res.data[..2], + &[0x38, 0x30], + "unexpected version format: {}", + hex::encode(&res.data) ); - - let tbundle = pczt.transparent(); - for tin in tbundle.inputs() { - let mut data = vec![]; - data.write_u32::<LE>(44 + 0x80000000)?; - data.write_u32::<LE>(133 + 0x80000000)?; - data.write_u32::<LE>(0x80000000)?; - data.write_u32::<LE>(0)?; // scope - data.write_u32::<LE>(0)?; // dindex - let script = address.script(); - data.write_u8(script.byte_len() as u8)?; - data.write_all(&script.to_bytes())?; - data.write_u64::<LE>(*tin.value())?; - assert_eq!(data.len(), 54); - buffers.push(data); - } - - for tout in tbundle.outputs() { - let mut data = vec![]; - let script = tout.script_pubkey(); - data.write_u8(script.len() as u8)?; - data.write_all(script)?; - data.write_u64::<LE>(*tout.value())?; - assert_eq!(data.len(), 34); - buffers.push(data); - } - - let sbundle = pczt.sapling(); - for sout in sbundle.outputs() { - let mut data = vec![]; - let recipient = sout.recipient().expect("Must have a recipient"); - data.write_all(&recipient)?; - data.write_u64::<LE>(sout.value().expect("Must have value"))?; - data.write_u8(0xF6)?; // Memo type - data.write_u8(0x01)?; // Have OVK - data.write_all(&ovk.0)?; - assert_eq!(data.len(), 85); - buffers.push(data); - } - - let init_tx = APDUCommand { - cla: 0x85, - ins: 0xA0, - p1: 0, - p2: 5, - data: vec![], - }; - - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - if stage == 1 { - let total_len = buffers.iter().map(|b| b.len()).sum::<usize>(); - assert_eq!( - total_len, - 4 + 54 * tbundle.inputs().len() - + 34 * tbundle.outputs().len() - + 85 * sbundle.outputs().len() - ); - let res = ledger.long_execute(&init_tx, &buffers).await?; - assert_eq!(res.retcode, 0x9000); - } - - let mut buffers = vec![]; - buffers.push(vec![]); - for tin in tbundle.inputs() { - let mut data = vec![]; - data.write_all(tin.prevout_txid())?; - data.write_u32::<LE>(*tin.prevout_index())?; - data.write_u8(0x19)?; - data.write_all(tin.script_pubkey())?; - data.write_u64::<LE>(*tin.value())?; - data.write_u32::<LE>(tin.sequence().unwrap_or(0xFFFFFFFFu32))?; - assert_eq!(data.len(), 74); - buffers.push(data); - } - /* hashes - header: - version, group, consensus, locktime, expiry: 5*4 = 20 - transparent: - prevout, sequence, output: 3*32 = 96 - sapling: - spends, outputs, net: 2*32 + 8 = 72 - orchard: 32 - = 220 - */ - let mut sighashes = vec![]; - let header = pczt.global(); - let expiration = header.expiry_height(); - let version = header.tx_version() | 0x80000000; - let version_group = header.version_group_id(); - let branch = header.consensus_branch_id(); - sighashes.write_u32::<LE>(version)?; - sighashes.write_u32::<LE>(*version_group)?; - sighashes.write_u32::<LE>(*branch)?; - sighashes.write_u32::<LE>(0)?; - sighashes.write_u32::<LE>(*expiration)?; - - println!("H: {}", hex::encode(header_hasher(&pczt)?)); - println!("T: {}", hex::encode(transparent_hasher(&pczt)?)); - println!("S: {}", hex::encode(sapling_hasher(&pczt)?)); - println!("O: {}", hex::encode(orchard_hasher(&pczt)?)); - println!("Sig: {}", hex::encode(sig_hasher(&pczt)?)); - - sighashes.write_all(&prevout_hasher(&pczt)?)?; - sighashes.write_all(&sequence_hasher(&pczt)?)?; - sighashes.write_all(&output_hasher(&pczt)?)?; - - sighashes.write_all(&spend_hasher(&pczt)?)?; - sighashes.write_all(&zoutput_hasher(&pczt)?)?; - sighashes.write_i64::<LE>(0)?; - - sighashes.write_all(&orchard_hasher(&pczt)?)?; - buffers.push(sighashes); - - let check_sign = APDUCommand { - cla: 0x85, - ins: 0xA3, - p1: 0, - p2: 5, - data: vec![], - }; - - if stage == 3 { - let res = ledger.long_execute(&check_sign, &buffers).await?; - assert_eq!(res.retcode, 0x9000); - println!(">> {}", hex::encode(&res.data)); - } - - let mut signatures = vec![]; - for _ in tbundle.inputs() { - let get_signature = APDUCommand { - cla: 0x85, - ins: 0xA5, - p1: 0, - p2: 0, - data: vec![], - }; - if stage == 3 { - let res = ledger.long_execute(&get_signature, &[vec![]]).await?; - assert_eq!(res.retcode, 0x9000); - let signature = res.data[..64].to_vec(); - let signature = Signature::from_compact(&signature).anyhow()?; - signatures.push(signature); - } - } - - let sig_hex = "b154b87733d9040a995880a54e3575b0169920775c080eb71f4c2b9143ca4c454085a5665f997cc8d2652560ee9f775a705500a5236c25f989c70d213ed6b7de"; - if stage == 3 { - let sig = hex::encode(signatures[0].serialize_compact()); - assert_eq!(sig, sig_hex); - } - - if stage == 4 { - let signature = Signature::from_compact(&hex::decode(sig_hex).unwrap()).anyhow()?; - let signer = Signer::new(pczt.clone()); - let signer = signer - .sign_transparent_with(|_pczt, tbundle, _| { - tbundle.inputs_mut()[0].apply_signature(&pk, &signature); - Ok::<_, zcash_transparent::pczt::ParseError>(()) - }) - .unwrap(); - let pczt = signer.finish(); - let pczt = SpendFinalizer::new(pczt).finalize_spends().unwrap(); - - let tx_extractor = TransactionExtractor::new(pczt); - let tx = tx_extractor.extract().unwrap(); - println!("{}", tx.txid()); - let mut tx_bytes = vec![]; - tx.write(&mut tx_bytes).unwrap(); - println!("{}", hex::encode(&tx_bytes)); - } - Ok(()) -} - -#[tokio::test] -pub async fn sign_tx() -> LedgerResult<()> { - let file = File::open("ledger.bin")?; - let package = bincode::decode_from_reader::<PcztPackage, _, _>( - BufReader::new(file), - bincode::config::legacy(), - ) - .anyhow()?; - let pczt = Pczt::parse(&package.pczt).unwrap(); - - APDUCommand { - cla: 0x85, - ins: 0xA0, - p1: 0, - p2: 0, - data: vec![], - }; - - let mut data = vec![]; - data.write_u8(pczt.transparent().inputs().len() as u8)?; - data.write_u8(pczt.transparent().outputs().len() as u8)?; - data.write_u8(pczt.sapling().spends().len() as u8)?; - data.write_u8(pczt.sapling().outputs().len() as u8)?; - - assert!(pczt.sapling().spends().is_empty()); - assert!(pczt.sapling().outputs().is_empty()); - + println!("app version response: {}", hex::encode(&res.data)); Ok(()) } - -pub fn sapling_hasher(_pczt: &Pczt) -> LedgerResult<[u8; 32]> { - let hasher = create_hasher(b"ZTxIdSaplingHash"); - Ok(hasher.finalize().as_bytes().try_into().unwrap()) -} - -pub fn sig_hasher(pczt: &Pczt) -> LedgerResult<[u8; 32]> { - let mut perso = b"ZcashTxHash_0000".to_vec(); - perso[12..].copy_from_slice(&pczt.global().consensus_branch_id().to_le_bytes()); - let mut hasher = create_hasher(&perso); - hasher.update(&header_hasher(pczt)?); - hasher.update(&transparent_hasher(pczt)?); - hasher.update(&sapling_hasher(pczt)?); - hasher.update(&orchard_hasher(pczt)?); - Ok(hasher.finalize().as_bytes().try_into().unwrap()) -} diff --git a/rust/src/ledger/transport.rs b/rust/src/ledger/transport.rs index af7c34dca..1f5e027f4 100644 --- a/rust/src/ledger/transport.rs +++ b/rust/src/ledger/transport.rs @@ -260,7 +260,12 @@ pub static LEDGER_ZEMU: LazyLock<tokio::sync::Mutex<Option<LedgerDeviceZEMU>>> = { use std::sync::Arc; - let device = ledger_transport_zemu::TransportZemuHttp::new("192.168.18.13", 9999); + let host = std::env::var("ZEMU_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); + let port: u16 = std::env::var("ZEMU_PORT") + .ok() + .and_then(|p| p.parse().ok()) + .unwrap_or(9999); + let device = ledger_transport_zemu::TransportZemuHttp::new(&host, port); let ledger = LedgerDeviceZEMU { device: Arc::new(device), }; From 2d893b96903c7249035344d207fa62aaa4095870 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 00:04:30 +0800 Subject: [PATCH 144/189] ci: add manual-only Ledger emulator workflow --- .github/workflows/test-ledger.yml | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/test-ledger.yml diff --git a/.github/workflows/test-ledger.yml b/.github/workflows/test-ledger.yml new file mode 100644 index 000000000..203531478 --- /dev/null +++ b/.github/workflows/test-ledger.yml @@ -0,0 +1,36 @@ +name: Test Ledger + +on: + workflow_dispatch: + +jobs: + emulator: + runs-on: ubuntu-latest + steps: + - name: Install RUST + uses: dtolnay/rust-toolchain@stable + - name: Checkout code + uses: actions/checkout@v6 + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libudev-dev pkg-config + - name: Cache cargo artifacts + uses: Swatinem/rust-cache@v2 + with: + workspaces: rust + - name: Setup emulator + run: | + misc/ledger/setup.sh + misc/ledger/build.sh + misc/ledger/run-emulator.sh + - name: Verify emulator + run: | + response=$(curl -s -m 5 -X POST http://127.0.0.1:9999 \ + -H 'Content-Type: application/json' -d '{"apduHex": "e0c4000000"}') + echo "$response" + echo "$response" | grep -qE '"data": "3830[0-9a-f]*9000", "error": null' + - name: Run ledger tests + run: | + cd rust + cargo test --features zemu -- --ignored --nocapture ledger_app_version From c2e22d15c09ef2f13515fa9c12932efd6223d2e1 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 00:35:23 +0800 Subject: [PATCH 145/189] ci: install protobuf-compiler for ledger tests --- .github/workflows/test-ledger.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-ledger.yml b/.github/workflows/test-ledger.yml index 203531478..8816da703 100644 --- a/.github/workflows/test-ledger.yml +++ b/.github/workflows/test-ledger.yml @@ -14,7 +14,7 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install -y libudev-dev pkg-config + sudo apt-get install -y libudev-dev pkg-config protobuf-compiler - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: From 1588b96b43df840e640d0c8c3ff3b612b58a5602 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Fri, 4 Sep 2026 13:29:14 +0800 Subject: [PATCH 146/189] feat: support multiple Ledger app types (Official, Zondax) (#1242) * feat: support multiple Ledger app types (Official, Zondax) - encode the app kind in accounts.hw (0 software, 1 Zondax, 2 Official); NewAccount carries a single hw field - introduce LedgerApp trait (replaces HWAPI) with kind-specific defaults; ZondaxApp wraps the legacy CLA 0x85 device code, StubLedger returns clear errors for software accounts, builds without the ledger feature and Official device operations (vk import, PCZT signing not implemented yet) - Official accounts (transparent + ironwood pools) are created locally from the recovery seed via standard ZIP-32; pool masks are validated per app and pool mask literals are replaced by named POOL_* constants - New Account form gains a Zondax/Official selector with per-app pool masks (T+S / T+Ironwood) synced into the form field - drop obsolete Zondax-protocol device tests; add no-device creation tests for both app types * fix(ledger): treat seed-based Official Ledger accounts as software --- integration_test/support.dart | 2 +- lib/pages/new_account.dart | 61 ++++++++++++-- lib/settings.dart | 4 +- lib/src/rust/api/account.dart | 2 +- lib/src/rust/api/account.freezed.dart | 54 ++++++------ lib/src/rust/frb_generated.dart | 8 +- lib/widgets/pool_select.dart | 37 +++----- rust/src/account.rs | 70 +++++++++++----- rust/src/api/account.rs | 44 +++++----- rust/src/db.rs | 2 +- rust/src/frb_generated.rs | 8 +- rust/src/frost/protocol.rs | 4 +- rust/src/graphql/mutation.rs | 2 +- rust/src/ledger/README.md | 16 ++++ rust/src/ledger/fvk.rs | 68 --------------- rust/src/ledger/mock.rs | 73 +++++++++++----- rust/src/ledger/mod.rs | 116 ++++++++++++++++++-------- rust/src/ledger/nano.rs | 27 +++--- rust/src/pay/pool.rs | 5 ++ rust/src/sync.rs | 2 +- rust/tests/ledger_accounts_test.rs | 113 +++++++++++++++++++++++++ rust/tests/zsa_transfer_test.rs | 10 +-- 22 files changed, 470 insertions(+), 258 deletions(-) create mode 100644 rust/tests/ledger_accounts_test.rs diff --git a/integration_test/support.dart b/integration_test/support.dart index 1f6533508..909d45e81 100644 --- a/integration_test/support.dart +++ b/integration_test/support.dart @@ -151,7 +151,7 @@ Future<int> setUpTestWallet({ folder: "", useInternal: false, internal: false, - ledger: false, + hw: 0, ), c: coinContext.coin, ); diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index d82055a5e..538e98dd8 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -34,6 +34,13 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { var key = ""; var isSeed = false; var ledger = false; + var ledgerApp = 0; // 0 = Zondax (Sapling), 1 = Official (Ironwood) + + int getPools() => ledger + ? (ledgerApp == 0 + ? Pool.transparent.bit | Pool.sapling.bit // T+S + : Pool.transparent.bit | Pool.ironwood.bit) // T+I + : getKeyPools(key: key, c: c); var isFvk = false; var _showAdvanced = false; Uint8List? iconBytes; @@ -47,7 +54,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { final ib = iconBytes; isSeed = isValidPhrase(phrase: key); isFvk = isValidFvk(fvk: key, c: c); - final keyPools = ledger ? 3 : getKeyPools(key: key, c: c); // 3 is T+S + final keyPools = getPools(); // 3 is T+S, 9 is T+Ironwood return Scaffold( appBar: AppBar( @@ -299,8 +306,50 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { ], ), initialValue: ledger, - onChanged: (v) => setState(() => ledger = v ?? false), + onChanged: (v) { + setState(() { + ledger = v ?? false; + }); + formKey.currentState?.fields["pools"]?.didChange(getPools()); + }, ), + if (ledger) ...[ + Gap(8), + SegmentedButton<int>( + segments: const [ + ButtonSegment( + value: 1, + label: Text("Official (Ironwood)"), + ), + ButtonSegment( + value: 0, + label: Text("Zondax (Sapling)"), + ), + ], + selected: {ledgerApp}, + onSelectionChanged: (s) { + setState(() { + ledgerApp = s.first; + }); + formKey.currentState?.fields["pools"]?.didChange(getPools()); + }, + ), + if (isSeed && ledgerApp == 1) ...[ + Gap(8), + Row( + children: [ + Icon(Icons.warning_amber_rounded, size: 16, color: Colors.orange), + Gap(4), + Expanded( + child: Text( + "Official Ledger is discarded: its derivation is identical to a regular account, so this account will be created as a regular seed phrase account", + style: TextStyle(color: Colors.orange, fontSize: 12), + ), + ), + ], + ), + ], + ], ], ], ], @@ -332,6 +381,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { final String? name = formData?["name"]; final bool? restore = formData?["restore"]; final bool ledger = formData?["ledger"] as bool? ?? false; + final hw = ledger ? ledgerApp + 1 : 0; final String? passphrase = formData?["passphrase"]; final String? aindex = formData?["aindex"]; final String? birth = formData?["birth"]; @@ -354,7 +404,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { AwesomeDialog? dialog; try { String message = "Please wait while we create the account"; - if (ledger) message += "\nConfirm on your Ledger device"; + if (ledger && ledgerApp == 0 && !isSeed) message += "\nConfirm on your Ledger device"; dialog = showLoadingDialog(context, message); final account = await newAccount( na: NewAccount( @@ -369,9 +419,10 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { pools: pools, useInternal: useInternal ?? false, internal: false, - ledger: ledger, + hw: hw, ), - c: c); + c: c, + ); dialog.dismiss(); dialog = null; final settings = ref.read(appSettingsProvider).requireValue; diff --git a/lib/settings.dart b/lib/settings.dart index 0202b20b3..d7962b130 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -931,7 +931,7 @@ class SettingsFormState extends ConsumerState<SettingsForm> { folder: "", useInternal: ra.useInternal, internal: false, - ledger: false, + hw: 0, ), c: coin, ); @@ -1091,7 +1091,7 @@ class SettingsFormState extends ConsumerState<SettingsForm> { folder: "", useInternal: ra.useInternal, internal: false, - ledger: false, + hw: 0, ), c: coin, ); diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index d13212c6a..cabe13ddb 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -312,7 +312,7 @@ sealed class NewAccount with _$NewAccount { int? pools, required bool useInternal, required bool internal, - required bool ledger, + required int hw, }) = _NewAccount; } diff --git a/lib/src/rust/api/account.freezed.dart b/lib/src/rust/api/account.freezed.dart index 20e59b151..bea274294 100644 --- a/lib/src/rust/api/account.freezed.dart +++ b/lib/src/rust/api/account.freezed.dart @@ -2729,7 +2729,7 @@ mixin _$NewAccount { int? get pools; bool get useInternal; bool get internal; - bool get ledger; + int get hw; /// Create a copy of NewAccount /// with the given fields replaced by the non-null parameter values. @@ -2759,7 +2759,7 @@ mixin _$NewAccount { other.useInternal == useInternal) && (identical(other.internal, internal) || other.internal == internal) && - (identical(other.ledger, ledger) || other.ledger == ledger)); + (identical(other.hw, hw) || other.hw == hw)); } @override @@ -2777,11 +2777,11 @@ mixin _$NewAccount { pools, useInternal, internal, - ledger); + hw); @override String toString() { - return 'NewAccount(icon: $icon, name: $name, restore: $restore, key: $key, passphrase: $passphrase, fingerprint: $fingerprint, aindex: $aindex, birth: $birth, folder: $folder, pools: $pools, useInternal: $useInternal, internal: $internal, ledger: $ledger)'; + return 'NewAccount(icon: $icon, name: $name, restore: $restore, key: $key, passphrase: $passphrase, fingerprint: $fingerprint, aindex: $aindex, birth: $birth, folder: $folder, pools: $pools, useInternal: $useInternal, internal: $internal, hw: $hw)'; } } @@ -2804,7 +2804,7 @@ abstract mixin class $NewAccountCopyWith<$Res> { int? pools, bool useInternal, bool internal, - bool ledger}); + int hw}); } /// @nodoc @@ -2831,7 +2831,7 @@ class _$NewAccountCopyWithImpl<$Res> implements $NewAccountCopyWith<$Res> { Object? pools = freezed, Object? useInternal = null, Object? internal = null, - Object? ledger = null, + Object? hw = null, }) { return _then(_self.copyWith( icon: freezed == icon @@ -2882,10 +2882,10 @@ class _$NewAccountCopyWithImpl<$Res> implements $NewAccountCopyWith<$Res> { ? _self.internal : internal // ignore: cast_nullable_to_non_nullable as bool, - ledger: null == ledger - ? _self.ledger - : ledger // ignore: cast_nullable_to_non_nullable - as bool, + hw: null == hw + ? _self.hw + : hw // ignore: cast_nullable_to_non_nullable + as int, )); } } @@ -2994,7 +2994,7 @@ extension NewAccountPatterns on NewAccount { int? pools, bool useInternal, bool internal, - bool ledger)? + int hw)? $default, { required TResult orElse(), }) { @@ -3014,7 +3014,7 @@ extension NewAccountPatterns on NewAccount { _that.pools, _that.useInternal, _that.internal, - _that.ledger); + _that.hw); case _: return orElse(); } @@ -3048,7 +3048,7 @@ extension NewAccountPatterns on NewAccount { int? pools, bool useInternal, bool internal, - bool ledger) + int hw) $default, ) { final _that = this; @@ -3067,7 +3067,7 @@ extension NewAccountPatterns on NewAccount { _that.pools, _that.useInternal, _that.internal, - _that.ledger); + _that.hw); } } @@ -3098,7 +3098,7 @@ extension NewAccountPatterns on NewAccount { int? pools, bool useInternal, bool internal, - bool ledger)? + int hw)? $default, ) { final _that = this; @@ -3117,7 +3117,7 @@ extension NewAccountPatterns on NewAccount { _that.pools, _that.useInternal, _that.internal, - _that.ledger); + _that.hw); case _: return null; } @@ -3140,7 +3140,7 @@ class _NewAccount implements NewAccount { this.pools, required this.useInternal, required this.internal, - required this.ledger}); + required this.hw}); @override final Uint8List? icon; @@ -3167,7 +3167,7 @@ class _NewAccount implements NewAccount { @override final bool internal; @override - final bool ledger; + final int hw; /// Create a copy of NewAccount /// with the given fields replaced by the non-null parameter values. @@ -3198,7 +3198,7 @@ class _NewAccount implements NewAccount { other.useInternal == useInternal) && (identical(other.internal, internal) || other.internal == internal) && - (identical(other.ledger, ledger) || other.ledger == ledger)); + (identical(other.hw, hw) || other.hw == hw)); } @override @@ -3216,11 +3216,11 @@ class _NewAccount implements NewAccount { pools, useInternal, internal, - ledger); + hw); @override String toString() { - return 'NewAccount(icon: $icon, name: $name, restore: $restore, key: $key, passphrase: $passphrase, fingerprint: $fingerprint, aindex: $aindex, birth: $birth, folder: $folder, pools: $pools, useInternal: $useInternal, internal: $internal, ledger: $ledger)'; + return 'NewAccount(icon: $icon, name: $name, restore: $restore, key: $key, passphrase: $passphrase, fingerprint: $fingerprint, aindex: $aindex, birth: $birth, folder: $folder, pools: $pools, useInternal: $useInternal, internal: $internal, hw: $hw)'; } } @@ -3245,7 +3245,7 @@ abstract mixin class _$NewAccountCopyWith<$Res> int? pools, bool useInternal, bool internal, - bool ledger}); + int hw}); } /// @nodoc @@ -3272,7 +3272,7 @@ class __$NewAccountCopyWithImpl<$Res> implements _$NewAccountCopyWith<$Res> { Object? pools = freezed, Object? useInternal = null, Object? internal = null, - Object? ledger = null, + Object? hw = null, }) { return _then(_NewAccount( icon: freezed == icon @@ -3323,10 +3323,10 @@ class __$NewAccountCopyWithImpl<$Res> implements _$NewAccountCopyWith<$Res> { ? _self.internal : internal // ignore: cast_nullable_to_non_nullable as bool, - ledger: null == ledger - ? _self.ledger - : ledger // ignore: cast_nullable_to_non_nullable - as bool, + hw: null == hw + ? _self.hw + : hw // ignore: cast_nullable_to_non_nullable + as int, )); } } diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 482886d89..2488dd698 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -9356,7 +9356,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pools: dco_decode_opt_box_autoadd_u_8(arr[9]), useInternal: dco_decode_bool(arr[10]), internal: dco_decode_bool(arr[11]), - ledger: dco_decode_bool(arr[12]), + hw: dco_decode_u_8(arr[12]), ); } @@ -11995,7 +11995,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_pools = sse_decode_opt_box_autoadd_u_8(deserializer); var var_useInternal = sse_decode_bool(deserializer); var var_internal = sse_decode_bool(deserializer); - var var_ledger = sse_decode_bool(deserializer); + var var_hw = sse_decode_u_8(deserializer); return NewAccount( icon: var_icon, name: var_name, @@ -12009,7 +12009,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pools: var_pools, useInternal: var_useInternal, internal: var_internal, - ledger: var_ledger); + hw: var_hw); } @protected @@ -14658,7 +14658,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_8(self.pools, serializer); sse_encode_bool(self.useInternal, serializer); sse_encode_bool(self.internal, serializer); - sse_encode_bool(self.ledger, serializer); + sse_encode_u_8(self.hw, serializer); } @protected diff --git a/lib/widgets/pool_select.dart b/lib/widgets/pool_select.dart index 468c093e3..bc1cd9b97 100644 --- a/lib/widgets/pool_select.dart +++ b/lib/widgets/pool_select.dart @@ -17,16 +17,18 @@ class PoolSelect extends StatefulWidget { enum Pool { transparent, sapling, orchard, ironwood } +extension PoolBit on Pool { + int get bit => 1 << index; +} + +int poolMask(Iterable<Pool> pools) => + pools.fold(0, (mask, pool) => mask | pool.bit); + class _PoolSelectState extends State<PoolSelect> { late Set<Pool> pools; Set<Pool> _valueToPools(int value) { - return { - if (value & 1 != 0) Pool.transparent, - if (value & 2 != 0) Pool.sapling, - if (value & 4 != 0) Pool.orchard, - if (value & 8 != 0) Pool.ironwood, - }; + return Pool.values.where((p) => value & p.bit != 0).toSet(); } @override @@ -63,22 +65,22 @@ class _PoolSelectState extends State<PoolSelect> { ButtonSegment<Pool>( value: Pool.transparent, label: Text('Trp'), - enabled: widget.enabled & 1 != 0, + enabled: widget.enabled & Pool.transparent.bit != 0, ), ButtonSegment<Pool>( value: Pool.sapling, label: Text('Sap'), - enabled: widget.enabled & 2 != 0, + enabled: widget.enabled & Pool.sapling.bit != 0, ), ButtonSegment<Pool>( value: Pool.orchard, label: Text('Orc'), - enabled: widget.enabled & 4 != 0, + enabled: widget.enabled & Pool.orchard.bit != 0, ), ButtonSegment<Pool>( value: Pool.ironwood, label: Text('Iwd'), - enabled: widget.enabled & 8 != 0, + enabled: widget.enabled & Pool.ironwood.bit != 0, ), ], selected: pools, @@ -86,20 +88,7 @@ class _PoolSelectState extends State<PoolSelect> { ? (Set<Pool> newSelection) { setState(() { pools = newSelection; - onChanged( - newSelection.fold(0, (previousValue, element) { - switch (element) { - case Pool.transparent: - return previousValue | 1; - case Pool.sapling: - return previousValue | 2; - case Pool.orchard: - return previousValue | 4; - case Pool.ironwood: - return previousValue | 8; - } - }), - ); + onChanged(poolMask(newSelection)); }); } : null, diff --git a/rust/src/account.rs b/rust/src/account.rs index 327e36948..6ab27d533 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -13,6 +13,7 @@ use crate::{ store_account_transparent_sk, store_account_transparent_vk, update_dindex, }, key::{is_valid_phrase, is_valid_sapling_key, is_valid_transparent_key, is_valid_ufvk}, + ledger::HwKind, keys::{sapling_dfvk_to_fvk, ScopeExt}, tiu, }; @@ -24,7 +25,9 @@ use crate::{ key::generate_seed, }, db::{get_account_hw, select_account_transparent, store_account_hw, store_account_metadata}, - pay::pool::ALL_POOLS, + pay::pool::{ + ALL_POOLS, POOL_IRONWOOD, POOL_ORCHARD, POOL_SAPLING, POOL_TRANSPARENT, + }, }; use secp256k1::{PublicKey, SecretKey}; use zcash_keys::keys::{sapling::ExtendedSpendingKey, UnifiedFullViewingKey, UnifiedSpendingKey}; @@ -87,16 +90,43 @@ pub async fn new_account( .await?; let mut key = na.key.clone(); - if key.is_empty() && !na.ledger { + let ledger_kind = HwKind::from_hw(na.hw); + if key.is_empty() && !ledger_kind.is_ledger() { key = generate_seed()?; } let pools = na.pools.unwrap_or(ALL_POOLS); - if na.ledger { + let ledger_kind = if ledger_kind.is_ledger() { + match ledger_kind { + HwKind::Official => { + if pools & !(POOL_TRANSPARENT | POOL_IRONWOOD) != 0 { + anyhow::bail!( + "Official Ledger accounts support transparent and ironwood pools only" + ); + } + if !is_valid_phrase(&key) { + anyhow::bail!( + "Official Ledger accounts require the recovery seed phrase. Importing the viewing key from the device is not supported yet" + ); + } + } + HwKind::Zondax => { + if pools & !(POOL_TRANSPARENT | POOL_SAPLING) != 0 { + anyhow::bail!("Zondax Ledger accounts support transparent and sapling pools only"); + } + } + _ => anyhow::bail!("unknown Ledger app"), + } + Some(ledger_kind) + } else { + None + }; + + if ledger_kind == Some(HwKind::Zondax) { let has_seed = !key.is_empty(); if !has_seed { - store_account_hw(&mut db_tx, account, 1, na.aindex).await?; + store_account_hw(&mut db_tx, account, HwKind::Zondax as u8, na.aindex).await?; } let ledger = get_ledger(&mut db_tx, account).await?; @@ -104,7 +134,7 @@ pub async fn new_account( // we must do sapling derivation first to know a valid dindex // because in sapling some indices are invalid let mut dindex = 0; - if pools & 2 != 0 { + if pools & POOL_SAPLING != 0 { init_account_sapling(network, &mut db_tx, account, birth).await?; if has_seed { let sxsk = crate::recover::recover_ledger_seed(&key, na.aindex).await?; @@ -116,7 +146,7 @@ pub async fn new_account( let address = derive_sapling_address(network, &sxvk, dindex); store_account_sapling_vk(&mut db_tx, account, &sxvk, &address).await?; } else { - let fvk = ledger.get_hw_fvk(network, na.aindex).await?; + let fvk = ledger.import_sapling_fvk(network, na.aindex).await?; let mut dfvk = fvk.to_bytes().to_vec(); dfvk.extend_from_slice(&[0u8; 32]); // add a dummy dk because we cannot get the one from the Ledger let xvk = DiversifiableFullViewingKey::from_bytes(&tiu!(dfvk)).unwrap(); @@ -124,14 +154,14 @@ pub async fn new_account( // api but it is currently not working // instead, we "assume" the dindex = 0 is the default sapling address // let (dindex, address) = get_hw_next_diversifier_address(&network, na.aindex, 0).await?; - let address = ledger.get_hw_sapling_address(network, na.aindex).await?; + let address = ledger.get_sapling_address(network, na.aindex).await?; store_account_sapling_vk(&mut db_tx, account, &xvk, &address).await?; } } - if pools & 1 != 0 && !has_seed { + if pools & POOL_TRANSPARENT != 0 && !has_seed { init_account_transparent(&mut db_tx, account, birth).await?; let (pk, taddr) = ledger - .get_hw_transparent_address(network, na.aindex, 0, dindex) + .get_transparent_pubkey(network, na.aindex, 0, dindex) .await?; store_account_transparent_addr( &mut db_tx, @@ -171,7 +201,7 @@ pub async fn new_account( let (_, di) = uvk.default_address(UnifiedAddressRequest::AllAvailableKeys)?; let dindex: u32 = di.try_into()?; - if pools & 1 != 0 { + if pools & POOL_TRANSPARENT != 0 { init_account_transparent(&mut db_tx, account, birth).await?; let tsk = usk.transparent(); store_account_transparent_sk(&mut db_tx, account, tsk).await?; @@ -198,7 +228,7 @@ pub async fn new_account( } } - if pools & 2 != 0 { + if pools & POOL_SAPLING != 0 { init_account_sapling(network, &mut db_tx, account, birth).await?; let sxsk = usk.sapling(); store_account_sapling_sk(&mut db_tx, account, sxsk).await?; @@ -207,7 +237,7 @@ pub async fn new_account( store_account_sapling_vk(&mut db_tx, account, &sxvk, &address).await?; } - if pools & 4 != 0 { + if pools & (POOL_ORCHARD | POOL_IRONWOOD) != 0 { init_account_orchard(network, &mut db_tx, account, birth).await?; let oxsk = usk.orchard(); store_account_orchard_sk(&mut db_tx, account, oxsk).await?; @@ -342,7 +372,7 @@ pub async fn new_account( let dindex: u32 = di.try_into()?; match uvk.transparent() { - Some(tvk) if pools & 1 != 0 => { + Some(tvk) if pools & POOL_TRANSPARENT != 0 => { init_account_transparent(&mut db_tx, account, birth).await?; store_account_transparent_vk(&mut db_tx, account, tvk).await?; let (pk, address) = derive_transparent_address(tvk, 0, dindex, false)?; @@ -361,7 +391,7 @@ pub async fn new_account( _ => {} } match uvk.sapling() { - Some(sxvk) if pools & 2 != 0 => { + Some(sxvk) if pools & POOL_SAPLING != 0 => { init_account_sapling(network, &mut db_tx, account, birth).await?; let address = ua.sapling().unwrap(); let address = address.encode(&network); @@ -370,7 +400,7 @@ pub async fn new_account( _ => {} } match uvk.orchard() { - Some(ovk) if pools & 4 != 0 => { + Some(ovk) if pools & POOL_ORCHARD != 0 => { init_account_orchard(network, &mut db_tx, account, birth).await?; store_account_orchard_vk(&mut db_tx, account, ovk).await?; } @@ -752,7 +782,7 @@ pub async fn generate_next_dindex( dindex += 1; let address = if hw != 0 { let (di, address) = ledger - .get_hw_next_diversifier_address(network, aindex, dindex) + .next_diversifier_address(network, aindex, dindex) .await?; dindex = di; address @@ -789,7 +819,7 @@ pub async fn generate_next_dindex( } None if hw != 0 => { let (pk, address) = ledger - .get_hw_transparent_address(network, aindex, 0, dindex) + .get_transparent_pubkey(network, aindex, 0, dindex) .await?; (None, pk, Some(address)) } @@ -909,9 +939,9 @@ pub async fn get_addresses( let ua_orchard = UnifiedAddress::from_receivers(oaddr, None, None); let ua = UnifiedAddress::from_receivers( - if ua_pools & 4 != 0 { oaddr } else { None }, - if ua_pools & 2 != 0 { saddr } else { None }, - if ua_pools & 1 != 0 { taddr } else { None }, + if ua_pools & POOL_ORCHARD != 0 { oaddr } else { None }, + if ua_pools & POOL_SAPLING != 0 { saddr } else { None }, + if ua_pools & POOL_TRANSPARENT != 0 { taddr } else { None }, ); // final fallback if we have a transparent address from a BIP 38 secret key diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index bb87032f0..372957385 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::str::FromStr; use crate::keys::{SaplingAddressDerivation, ScopeExt}; -use crate::pay::pool::PoolMask; +use crate::pay::pool::{PoolMask, POOL_IRONWOOD, POOL_ORCHARD, POOL_SAPLING, POOL_TRANSPARENT}; use anyhow::{anyhow, Result}; use bip39::Mnemonic; use csv_async::AsyncWriter; @@ -25,7 +25,7 @@ use crate::{ api::{coin::Coin, pay::SigningEvent}, db::{get_account_dindex, get_account_hw}, io::{decrypt, encrypt}, - ledger::HWAPI, + ledger::{HwKind, LedgerApp}, }; #[cfg_attr(feature = "flutter", frb)] @@ -39,15 +39,15 @@ pub async fn get_account_pools(account: u32, c: &Coin) -> Result<u8> { let mut pools = 0; if tkeys.xvk.is_some() || tkeys.address.is_some() { - pools |= 1; + pools |= POOL_TRANSPARENT; } if skeys.xvk.is_some() { - pools |= 2; + pools |= POOL_SAPLING; } if okeys.xvk.is_some() { - pools |= 4; + pools |= POOL_ORCHARD; // Ironwood uses the same keys as Orchard - pools |= 8; + pools |= POOL_IRONWOOD; } Ok(pools) } @@ -311,7 +311,7 @@ pub struct NewAccount { pub pools: Option<u8>, pub use_internal: bool, pub internal: bool, - pub ledger: bool, + pub hw: u8, } #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] @@ -858,7 +858,7 @@ pub async fn sign_ledger_transaction( ) -> Result<()> { let mut connection = c.get_connection().await?; let ledger = get_ledger(&mut connection, c.account).await?; - ledger.sign_ledger_transaction(sink, package, c).await?; + ledger.sign_pczt(sink, package, c).await?; Ok(()) } @@ -926,20 +926,22 @@ pub struct TxMemo { pub(crate) async fn get_ledger( connection: &mut SqliteConnection, account: u32, -) -> Result<Box<dyn HWAPI + Send + Sync>> { +) -> Result<Box<dyn LedgerApp + Send + Sync>> { let hw = get_account_hw(connection, account).await?; - let r: Box<dyn HWAPI + Send + Sync> = if hw == 1 { - #[cfg(feature = "ledger")] - let d = Box::new(crate::ledger::nano::NanoLedger {}); - - #[cfg(not(feature = "ledger"))] - let d = Box::new(()); - - d - } else { - Box::new(()) - }; - Ok(r) + Ok(match HwKind::from_hw(hw) { + HwKind::Zondax => { + #[cfg(feature = "ledger")] + { + Box::new(crate::ledger::nano::ZondaxApp {}) + } + #[cfg(not(feature = "ledger"))] + { + Box::new(crate::ledger::mock::StubLedger::no_support()) + } + } + HwKind::Official => Box::new(crate::ledger::mock::StubLedger::official()), + HwKind::Software => Box::new(crate::ledger::mock::StubLedger::software()), + }) } #[frb] diff --git a/rust/src/db.rs b/rust/src/db.rs index 9591234b9..7baac7212 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -888,7 +888,7 @@ pub const LEDGER_CODE: u32 = 1; pub async fn store_account_hw( connection: &mut SqliteConnection, account: u32, - hw_code: u32, + hw_code: u8, aindex: u32, ) -> Result<()> { sqlx::query("UPDATE accounts SET hw = ?2, aindex = ?3 WHERE id_account = ?1") diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 278d651a7..52ecbe661 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -10876,7 +10876,7 @@ impl SseDecode for crate::api::account::NewAccount { let mut var_pools = <Option<u8>>::sse_decode(deserializer); let mut var_useInternal = <bool>::sse_decode(deserializer); let mut var_internal = <bool>::sse_decode(deserializer); - let mut var_ledger = <bool>::sse_decode(deserializer); + let mut var_hw = <u8>::sse_decode(deserializer); return crate::api::account::NewAccount { icon: var_icon, name: var_name, @@ -10890,7 +10890,7 @@ impl SseDecode for crate::api::account::NewAccount { pools: var_pools, use_internal: var_useInternal, internal: var_internal, - ledger: var_ledger, + hw: var_hw, }; } } @@ -13665,7 +13665,7 @@ impl flutter_rust_bridge::IntoDart for crate::api::account::NewAccount { self.pools.into_into_dart().into_dart(), self.use_internal.into_into_dart().into_dart(), self.internal.into_into_dart().into_dart(), - self.ledger.into_into_dart().into_dart(), + self.hw.into_into_dart().into_dart(), ] .into_dart() } @@ -16343,7 +16343,7 @@ impl SseEncode for crate::api::account::NewAccount { <Option<u8>>::sse_encode(self.pools, serializer); <bool>::sse_encode(self.use_internal, serializer); <bool>::sse_encode(self.internal, serializer); - <bool>::sse_encode(self.ledger, serializer); + <u8>::sse_encode(self.hw, serializer); } } diff --git a/rust/src/frost/protocol.rs b/rust/src/frost/protocol.rs index cec9b9894..02e93c70e 100644 --- a/rust/src/frost/protocol.rs +++ b/rust/src/frost/protocol.rs @@ -554,7 +554,7 @@ pub async fn get_mailbox_account( pools: None, use_internal: false, internal: true, - ledger: false, + hw: 0, }; let mailbox_account = new_account(network, &mut *connection, &na).await?; let fvk = get_orchard_vk(&mut *connection, mailbox_account) @@ -690,7 +690,7 @@ pub async fn get_coordinator_broadcast_account( pools: None, use_internal: false, internal: true, - ledger: false, + hw: 0, }; new_account(network, &mut *connection, &na).await?; // Loop again to retrieve the account diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index b1bb3dc13..4aaf89538 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -90,7 +90,7 @@ impl Mutation { use_internal: new_account.use_internal, folder: String::new(), internal: false, - ledger: false, + hw: 0, }; let id_account = crate::api::account::new_account(&na, &context.coin).await?; Ok(id_account as i32) diff --git a/rust/src/ledger/README.md b/rust/src/ledger/README.md index 9f8a806a2..630b238cb 100644 --- a/rust/src/ledger/README.md +++ b/rust/src/ledger/README.md @@ -30,6 +30,22 @@ speaks CLA `0xE0` (Bitcoin-app style) with Zcash extensions (INS `0x50` VK, protocol and needs migration; only the version smoke test speaks `0xE0` today. The transport layer is protocol-agnostic and unchanged. +## Account types (`accounts.hw`) + +| hw | App | Pools | Device protocol | +| --- | --- | --- | --- | +| 0 | software | all | n/a | +| 1 | Zondax | transparent + sapling | CLA `0x85` | +| 2 | Official | transparent + ironwood | CLA `0xE0` (not implemented yet) | + +v1 Official behavior: accounts are created from the recovery seed with +standard ZIP-32 derivation (no device needed); device operations return clear +errors via `ledger::mock::StubLedger`. Ironwood shares its keys with Orchard +(see `api::account::get_account_pools`), so Official accounts are initialized +with the Orchard key set. Pool masks are validated at creation +(`account.rs`). Selection UI lives in the New Account form +(`lib/pages/new_account.dart`). + ## Prerequisites - Docker Desktop installed and running (`docker info` succeeds). diff --git a/rust/src/ledger/fvk.rs b/rust/src/ledger/fvk.rs index 990e96ee4..762791c57 100644 --- a/rust/src/ledger/fvk.rs +++ b/rust/src/ledger/fvk.rs @@ -235,71 +235,3 @@ pub async fn show_transparent_address( Ok(ta.encode(network)) } -#[cfg(test)] -mod tests { - use byteorder::{WriteBytesExt, LE}; - use sapling_crypto::PaymentAddress; - use zcash_keys::encoding::AddressCodec; - use zcash_protocol::consensus::MainNetwork; - - use crate::{ - ledger::transport::{APDUCommand, Device, LEDGER_ZEMU}, - tiu, - }; - use std::io::Write; - - #[tokio::test] - pub async fn get_taddress() -> anyhow::Result<()> { - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - // let ledger = connect_ledger().await?; - let aindex = 0u32; - let dindex = 0u32; - let mut data = vec![]; - data.write_all(&(0x8000_0000u32 | 44).to_le_bytes())?; - data.write_all(&(0x8000_0000u32 | 133).to_le_bytes())?; - data.write_all(&(0x8000_0000u32 | aindex).to_le_bytes())?; - data.write_all(&(aindex).to_le_bytes())?; - data.write_all(&(dindex).to_le_bytes())?; - let get_taddress = APDUCommand { - cla: 0x85, - ins: 0x01, - p1: 1, - p2: 0, - data, - }; - - println!("{}", get_taddress.ins); - let res = ledger.execute(get_taddress).await?; - println!("{}", res.retcode); - let address = String::from_utf8(res.data[33..].to_vec())?; - println!("{address}"); - Ok(()) - } - - #[tokio::test] - pub async fn get_zaddress() -> anyhow::Result<()> { - let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); - // let ledger = connect_ledger().await?; - let aindex = 0u32; - let mut data = vec![]; - data.write_u32::<LE>(0x8000_0000u32 | aindex)?; - let get_taddress = APDUCommand { - cla: 0x85, - ins: 0x11, - p1: 0, - p2: 0, - data, - }; - - let res = ledger.execute(get_taddress).await?; - assert_eq!(res.retcode, 0x9000); - let address: [u8; 43] = tiu!(res.data[0..43]); - let address = PaymentAddress::from_bytes(&address).unwrap(); - let address = address.encode(&MainNetwork); - assert_eq!( - address, - "zs157m24pkqcq09edxz9p0p653xcsfpdpcspcad5wkkp3pq29hvc7h2uvs7wncakwqtl6jqkxn939p" - ); - Ok(()) - } -} diff --git a/rust/src/ledger/mock.rs b/rust/src/ledger/mock.rs index ab9ed240b..524c1fa7d 100644 --- a/rust/src/ledger/mock.rs +++ b/rust/src/ledger/mock.rs @@ -1,5 +1,4 @@ use anyhow::Result; -use sapling_crypto::keys::FullViewingKey; use sqlx::SqliteConnection; use tonic::async_trait; use zcash_transparent::address::TransparentAddress; @@ -10,56 +9,84 @@ use crate::{ pay::{PcztPackage, SigningEvent}, }, frb_generated::StreamSink, - ledger::HWAPI, + ledger::{HwKind, LedgerApp}, }; -#[async_trait] -impl HWAPI for () { - async fn get_hw_fvk(&self, _network: &Network, _aindex: u32) -> Result<FullViewingKey> { - unimplemented!() +/// Placeholder device for accounts that cannot perform device operations: +/// software accounts, builds without the `ledger` feature, and the Official +/// Ledger app whose device protocol is not implemented yet. +pub struct StubLedger { + kind: HwKind, + error: &'static str, +} + +impl StubLedger { + pub fn software() -> Self { + Self { + kind: HwKind::Software, + error: "account is not a hardware wallet", + } + } + + pub fn no_support() -> Self { + Self { + kind: HwKind::Software, + error: "this build has no Ledger support", + } } - async fn get_hw_sapling_address(&self, _network: &Network, _aindex: u32) -> Result<String> { - unimplemented!() + + pub fn official() -> Self { + Self { + kind: HwKind::Official, + error: "not implemented yet for the Official Ledger app", + } + } +} + +#[async_trait] +impl LedgerApp for StubLedger { + fn kind(&self) -> HwKind { + self.kind } - async fn get_hw_transparent_address( + + async fn get_transparent_pubkey( &self, _network: &Network, _aindex: u32, _scope: u32, _dindex: u32, ) -> Result<(Vec<u8>, TransparentAddress)> { - unimplemented!() + anyhow::bail!("{}", self.error) } - async fn get_hw_next_diversifier_address( + + async fn next_diversifier_address( &self, _network: &Network, _aindex: u32, _dindex: u32, ) -> Result<(u32, String)> { - unimplemented!() + anyhow::bail!("{}", self.error) } - async fn show_sapling_address( + + async fn show_transparent_address( &self, _network: &Network, _connection: &mut SqliteConnection, _account: u32, ) -> Result<String> { - unimplemented!() + anyhow::bail!("{}", self.error) } - async fn show_transparent_address( + + async fn show_sapling_address( &self, _network: &Network, _connection: &mut SqliteConnection, _account: u32, ) -> Result<String> { - unimplemented!() + anyhow::bail!("{}", self.error) } - async fn sign_ledger_transaction( - &self, - _sink: StreamSink<SigningEvent>, - _package: PcztPackage, - _c: &Coin, - ) -> Result<()> { - unimplemented!() + + async fn sign_pczt(&self, _sink: StreamSink<SigningEvent>, _package: PcztPackage, _c: &Coin) -> Result<()> { + anyhow::bail!("{}", self.error) } } diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index fd84641b9..6953cab29 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -13,42 +13,25 @@ pub mod error; pub type LedgerError = error::Error; pub type LedgerResult<T> = std::result::Result<T, LedgerError>; -#[async_trait] -pub trait HWAPI { - async fn get_hw_fvk(&self, network: &Network, aindex: u32) -> Result<FullViewingKey>; - async fn get_hw_sapling_address(&self, network: &Network, aindex: u32) -> Result<String>; - async fn get_hw_transparent_address( - &self, - network: &Network, - aindex: u32, - scope: u32, - dindex: u32, - ) -> Result<(Vec<u8>, TransparentAddress)>; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum HwKind { + Software = 0, + Zondax = 1, + Official = 2, +} - async fn get_hw_next_diversifier_address( - &self, - network: &Network, - aindex: u32, - dindex: u32, - ) -> Result<(u32, String)>; - async fn show_sapling_address( - &self, - network: &Network, - connection: &mut SqliteConnection, - account: u32, - ) -> Result<String>; - async fn show_transparent_address( - &self, - network: &Network, - connection: &mut SqliteConnection, - account: u32, - ) -> Result<String>; - async fn sign_ledger_transaction( - &self, - sink: StreamSink<SigningEvent>, - package: PcztPackage, - c: &Coin, - ) -> Result<()>; +impl HwKind { + pub fn from_hw(hw: u8) -> Self { + match hw { + 1 => HwKind::Zondax, + 2 => HwKind::Official, + _ => HwKind::Software, + } + } + + pub fn is_ledger(self) -> bool { + self != HwKind::Software + } } pub mod mock; @@ -65,3 +48,66 @@ cfg_if::cfg_if! { mod tests; } } + +#[async_trait] +pub trait LedgerApp: Send + Sync { + fn kind(&self) -> HwKind; + + async fn get_transparent_pubkey( + &self, + _network: &Network, + _aindex: u32, + _scope: u32, + _dindex: u32, + ) -> Result<(Vec<u8>, TransparentAddress)> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn next_diversifier_address( + &self, + _network: &Network, + _aindex: u32, + _dindex: u32, + ) -> Result<(u32, String)> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn show_transparent_address( + &self, + _network: &Network, + _connection: &mut SqliteConnection, + _account: u32, + ) -> Result<String> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn import_sapling_fvk( + &self, + _network: &Network, + _aindex: u32, + ) -> Result<FullViewingKey> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn get_sapling_address(&self, _network: &Network, _aindex: u32) -> Result<String> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn show_sapling_address( + &self, + _network: &Network, + _connection: &mut SqliteConnection, + _account: u32, + ) -> Result<String> { + anyhow::bail!("not supported by this Ledger app") + } + + async fn sign_pczt( + &self, + _sink: StreamSink<SigningEvent>, + _package: PcztPackage, + _c: &Coin, + ) -> Result<()> { + anyhow::bail!("not supported by this Ledger app") + } +} diff --git a/rust/src/ledger/nano.rs b/rust/src/ledger/nano.rs index 54ea42b93..8aff78ef8 100644 --- a/rust/src/ledger/nano.rs +++ b/rust/src/ledger/nano.rs @@ -10,24 +10,30 @@ use crate::{ pay::{PcztPackage, SigningEvent}, }, frb_generated::StreamSink, - ledger::HWAPI, + ledger::{HwKind, LedgerApp}, }; -pub struct NanoLedger {} +pub struct ZondaxApp {} #[async_trait] -impl HWAPI for NanoLedger { - async fn get_hw_fvk(&self, _network: &Network, aindex: u32) -> Result<FullViewingKey> { +impl LedgerApp for ZondaxApp { + fn kind(&self) -> HwKind { + HwKind::Zondax + } + + async fn import_sapling_fvk(&self, _network: &Network, aindex: u32) -> Result<FullViewingKey> { let ledger = crate::ledger::transport::connect_ledger().await?; let fvk = crate::ledger::fvk::get_fvk(&ledger, aindex).await?; Ok(fvk) } - async fn get_hw_sapling_address(&self, network: &Network, aindex: u32) -> Result<String> { + + async fn get_sapling_address(&self, network: &Network, aindex: u32) -> Result<String> { let ledger = crate::ledger::transport::connect_ledger().await?; let address = crate::ledger::fvk::get_hw_sapling_address(&ledger, network, aindex).await?; Ok(address) } - async fn get_hw_transparent_address( + + async fn get_transparent_pubkey( &self, network: &Network, aindex: u32, @@ -41,7 +47,7 @@ impl HWAPI for NanoLedger { Ok((pk, address)) } - async fn get_hw_next_diversifier_address( + async fn next_diversifier_address( &self, network: &Network, aindex: u32, @@ -76,12 +82,7 @@ impl HWAPI for NanoLedger { Ok(address) } - async fn sign_ledger_transaction( - &self, - sink: StreamSink<SigningEvent>, - package: PcztPackage, - c: &Coin, - ) -> Result<()> { + async fn sign_pczt(&self, sink: StreamSink<SigningEvent>, package: PcztPackage, c: &Coin) -> Result<()> { let connection = c.get_connection().await?; crate::ledger::builder::sign_ledger_transaction( c.network(), diff --git a/rust/src/pay/pool.rs b/rust/src/pay/pool.rs index 3eba98b21..0556e510b 100644 --- a/rust/src/pay/pool.rs +++ b/rust/src/pay/pool.rs @@ -15,6 +15,11 @@ pub const NUM_POOLS: usize = 4; pub const ALL_POOLS: u8 = 0b1111; pub const ALL_SHIELDED_POOLS: u8 = 0b1110; +pub const POOL_TRANSPARENT: u8 = 1; +pub const POOL_SAPLING: u8 = 2; +pub const POOL_ORCHARD: u8 = 4; +pub const POOL_IRONWOOD: u8 = 8; + impl PoolMask { pub fn empty() -> Self { PoolMask(0) diff --git a/rust/src/sync.rs b/rust/src/sync.rs index d554b2c03..828b3a16f 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -1290,7 +1290,7 @@ pub async fn transparent_sweep( Some(xvk) => derive_transparent_address(xvk, scope, dindex, false)?, None if hw != 0 => { ledger - .get_hw_transparent_address(&network, aindex, scope, dindex) + .get_transparent_pubkey(&network, aindex, scope, dindex) .await? } _ => anyhow::bail!("Sweep needs an xpub key"), diff --git a/rust/tests/ledger_accounts_test.rs b/rust/tests/ledger_accounts_test.rs new file mode 100644 index 000000000..7cf6602a6 --- /dev/null +++ b/rust/tests/ledger_accounts_test.rs @@ -0,0 +1,113 @@ +//! Ledger account creation tests. +//! +//! No device or emulator is needed: whenever a seed is provided the account +//! is software (the Official derivation is identical to a regular account, +//! and the Zondax restore path replicates the device derivation in software +//! via `recover::recover_ledger_seed`). + +use rlz::api::account::{get_account_pools, list_accounts, new_account, NewAccount}; +use rlz::api::coin::Coin; +use rlz::ledger::HwKind; + +const SEED_PHRASE: &str = "equal clock rain latin plastic toss scrub modify clarify fold armor exchange gesture erase habit plug state forward demise demand limb risk only document"; + +async fn temp_coin(name: &str) -> Coin { + let db_path = format!("/tmp/ledger_accounts_test_{}_{name}.db", std::process::id()); + let _ = std::fs::remove_file(&db_path); + Coin::new(Some(3)) + .open_database(db_path, None) + .await + .expect("open database") +} + +fn na(name: &str, key: &str, hw: u8, pools: Option<u8>) -> NewAccount { + NewAccount { + icon: None, + name: name.to_string(), + restore: !key.is_empty(), + key: key.to_string(), + passphrase: Some("".to_string()), + fingerprint: None, + aindex: 0, + birth: None, + folder: "".to_string(), + pools, + use_internal: false, + internal: false, + hw, + } +} + +async fn created_hw(coin: &Coin, name: &str) -> u8 { + list_accounts(coin) + .await + .unwrap() + .into_iter() + .find(|a| a.name == name) + .unwrap() + .hw +} + +#[tokio::test] +async fn official_ledger_with_seed_stays_software() { + let coin = temp_coin("official_seed").await; + let id = new_account(&na("official", SEED_PHRASE, HwKind::Official as u8, Some(9)), &coin) + .await + .expect("create account from seed with Official Ledger selected"); + + // The Official Ledger derivation is identical to a regular account, so + // with a seed the hardware flag is discarded. + assert_eq!(created_hw(&coin, "official").await, HwKind::Software as u8); + let pools = get_account_pools(id, &coin).await.unwrap(); + assert_ne!(pools & 8, 0, "ironwood must be present"); + assert_eq!(pools & 2, 0, "sapling must be absent"); +} + +#[tokio::test] +async fn official_ledger_without_seed_is_rejected() { + let coin = temp_coin("official_noseed").await; + let r = new_account(&na("official", "", HwKind::Official as u8, Some(9)), &coin).await; + let err = r.err().expect("must be rejected without a seed"); + assert!( + err.to_string().contains("seed"), + "unexpected error: {err:#}" + ); +} + +#[tokio::test] +async fn zondax_restore_with_seed_stays_software() { + let coin = temp_coin("zondax_seed").await; + let id = new_account(&na("zondax", SEED_PHRASE, HwKind::Zondax as u8, Some(3)), &coin) + .await + .expect("create Zondax Ledger account from seed"); + + // Existing behavior: a Zondax account restored from seed keeps the + // Zondax-derived sapling sk in software and is NOT flagged as hardware. + // Only keyless (device-only) Zondax accounts are flagged hw=1. + assert_eq!(created_hw(&coin, "zondax").await, HwKind::Software as u8); + let pools = get_account_pools(id, &coin).await.unwrap(); + assert_ne!(pools & 2, 0, "sapling must be present"); + assert_eq!(pools & 4, 0, "orchard must be absent"); +} + +#[tokio::test] +async fn zondax_ledger_rejects_orchard_pools() { + let coin = temp_coin("zondax_orchard").await; + let r = new_account(&na("zondax", SEED_PHRASE, HwKind::Zondax as u8, Some(7)), &coin).await; + let err = r.err().expect("orchard pools must be rejected for Zondax"); + assert!( + err.to_string().contains("transparent and sapling"), + "unexpected error: {err:#}" + ); +} + +#[tokio::test] +async fn official_ledger_rejects_sapling_pools() { + let coin = temp_coin("official_sapling").await; + let r = new_account(&na("official", SEED_PHRASE, HwKind::Official as u8, Some(7)), &coin).await; + let err = r.err().expect("sapling pools must be rejected for Official"); + assert!( + err.to_string().contains("transparent and ironwood"), + "unexpected error: {err:#}" + ); +} diff --git a/rust/tests/zsa_transfer_test.rs b/rust/tests/zsa_transfer_test.rs index 6edc0b283..9260e6de3 100644 --- a/rust/tests/zsa_transfer_test.rs +++ b/rust/tests/zsa_transfer_test.rs @@ -59,7 +59,7 @@ async fn test_orchard_transfer() { pools: Some(ALL_POOLS), use_internal: false, internal: false, - ledger: false, + hw: 0, }; let sender_id = new_account(&na, &coin) .await @@ -168,7 +168,7 @@ async fn test_orchard_transfer() { pools: Some(ALL_POOLS), use_internal: false, internal: false, - ledger: false, + hw: 0, }; let recipient_id = new_account(&na2, &coin).await.expect("restore recipient"); println!("Recipient account restored: id={recipient_id}"); @@ -358,7 +358,7 @@ async fn test_zsa_issuance() { pools: Some(ALL_POOLS), use_internal: false, internal: false, - ledger: false, + hw: 0, }; let account_id = new_account(&na, &coin) .await @@ -530,7 +530,7 @@ async fn test_zsa_transfer() { pools: Some(ALL_POOLS), use_internal: false, internal: false, - ledger: false, + hw: 0, }; let sender_id = new_account(&na, &coin) .await @@ -664,7 +664,7 @@ async fn test_zsa_transfer() { pools: Some(ALL_POOLS), use_internal: false, internal: false, - ledger: false, + hw: 0, }; let recipient_id = new_account(&na2, &coin).await.expect("restore recipient"); let recipient = coin From 26d4668fb18f01343b58fef2a01b753096b2f376 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 13:37:45 +0800 Subject: [PATCH 147/189] ci: take ledger emulator seed from SEED secret --- .github/workflows/test-ledger.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-ledger.yml b/.github/workflows/test-ledger.yml index 8816da703..e0e678dd7 100644 --- a/.github/workflows/test-ledger.yml +++ b/.github/workflows/test-ledger.yml @@ -20,6 +20,8 @@ jobs: with: workspaces: rust - name: Setup emulator + env: + SEED: ${{ secrets.SEED }} run: | misc/ledger/setup.sh misc/ledger/build.sh From ae6de55f60bbeac1d7b749b81e34f544efcbff91 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 17:01:53 +0800 Subject: [PATCH 148/189] feat: import Official Ledger UFVK from the device Implement GET_VK (CLA 0xE0, INS 0x50) for the Official Ledger app: new ledger::official module with OfficialApp, exposed through a get_ufvk method on LedgerApp and selected for hw=2 accounts. new_account now accepts hw=Official with an empty key: the UFVK is exported from the device (user-approved on screen) and stored per pool (transparent + ironwood/orchard, dindex 0). Seed-phrase creation is unchanged. Reject pool mask 0 at the business layer. Test infra: ledger_get_ufvk and ledger_account_import run against speculos with an on-screen approval driven via its REST API (right pages, both confirms); run-emulator.sh gains a UI_PORT knob (macOS AirPlay squats on 5000). The ledger-transport-zemu [patch] raises its 5s per-APDU HTTP timeout to 120s (ZEMU_TIMEOUT_SECS), which GET_VK always exceeds while the review is pending. Official is now the default Ledger app in the New Account form. --- Cargo.lock | 3 +- Cargo.toml | 7 ++ lib/pages/new_account.dart | 4 +- misc/ledger/run-emulator.sh | 7 +- rust/src/account.rs | 45 ++++++- rust/src/api/account.rs | 11 +- rust/src/ledger/README.md | 41 +++++-- rust/src/ledger/mod.rs | 5 + rust/src/ledger/official.rs | 115 ++++++++++++++++++ rust/src/ledger/tests.rs | 232 ++++++++++++++++++++++++++++++++++++ 10 files changed, 449 insertions(+), 21 deletions(-) create mode 100644 rust/src/ledger/official.rs diff --git a/Cargo.lock b/Cargo.lock index 9a6ea9ada..4823e9901 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5218,8 +5218,7 @@ dependencies = [ [[package]] name = "ledger-transport-zemu" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47437f746d26ec42e7d51d9bf239ed40d12e83da03a1b687796842d7369e0f9a" +source = "git+https://github.com/hhanh00/ledger-rs?rev=75cec634d11c29f110d098a34d13e1c22eab895e#75cec634d11c29f110d098a34d13e1c22eab895e" dependencies = [ "glob", "grpc", diff --git a/Cargo.toml b/Cargo.toml index b92c19a89..ac44b40e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,4 +57,11 @@ voting-circuits = { git = "https://github.com/hhanh00/voting-circuits.git", rev # workspace root manifest. pir-client = { git = "https://github.com/hhanh00/vote-nullifier-pir.git", rev = "b704640df339a98330a5b8e4582144fde67d0b0c" } +# -- Ledger emulator transport -- +# Branch feat/zemu-timeout off 8e3e28f (last commit carrying the crate, +# 0.10.0; removed upstream right after). Raises the 5s per-APDU HTTP +# timeout to 120s (env ZEMU_TIMEOUT_SECS): GET_VK blocks on the +# on-device review, which always exceeds 5s. +ledger-transport-zemu = { git = "https://github.com/hhanh00/ledger-rs", rev = "75cec634d11c29f110d098a34d13e1c22eab895e" } + diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index 538e98dd8..3aed8ba59 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -34,7 +34,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { var key = ""; var isSeed = false; var ledger = false; - var ledgerApp = 0; // 0 = Zondax (Sapling), 1 = Official (Ironwood) + var ledgerApp = 1; // 0 = Zondax (Sapling), 1 = Official (Ironwood) int getPools() => ledger ? (ledgerApp == 0 @@ -404,7 +404,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { AwesomeDialog? dialog; try { String message = "Please wait while we create the account"; - if (ledger && ledgerApp == 0 && !isSeed) message += "\nConfirm on your Ledger device"; + if (ledger && !isSeed) message += "\nConfirm on your Ledger device"; dialog = showLoadingDialog(context, message); final account = await newAccount( na: NewAccount( diff --git a/misc/ledger/run-emulator.sh b/misc/ledger/run-emulator.sh index 7fe990c98..9a5e20807 100755 --- a/misc/ledger/run-emulator.sh +++ b/misc/ledger/run-emulator.sh @@ -6,6 +6,8 @@ set -euo pipefail # MODEL: speculos model (nanox | nanosp | stax | flex | apex_p), default nanosp # BUILD_MODEL: build model directory under target/ (default nanosplus for nanosp) # SEED: device seed (deterministic test seed by default) +# UI_PORT: host port for the screen/REST API (default 5000; macOS AirPlay +# Receiver squats on 5000, in which case use e.g. 5001) # # Endpoints: # http://localhost:9999 JSON APDU (POST {"apduHex": "<hex>"}) - what zkool speaks @@ -15,6 +17,7 @@ APP_DIR="${APP_DIR:-$HOME/projects/ledger-dev/app-zcash}" MODEL="${MODEL:-nanosp}" BUILD_MODEL="${BUILD_MODEL:-nanosplus}" SEED="${SEED:-glory promote mansion idle axis finger extra february uncover one trip resource lawn turtle enact monster seven myth punch hobby comfort wild raise skin}" +UI_PORT="${UI_PORT:-5000}" ELF="$APP_DIR/target/$BUILD_MODEL/release/zcash" if [ ! -f "$ELF" ]; then @@ -25,7 +28,7 @@ fi docker rm -f speculos-zcash >/dev/null 2>&1 || true docker run -d --name speculos-zcash \ - -p 9999:9998 -p 5000:5000 \ + -p 9999:9998 -p "$UI_PORT":5000 \ -v "$APP_DIR/target":/app/target \ -w /speculos \ --entrypoint bash \ @@ -38,5 +41,5 @@ sleep 5 docker logs speculos-zcash 2>&1 | tail -5 echo echo "APDU endpoint : http://localhost:9999" -echo "Screen UI : http://localhost:5000" +echo "Screen UI : http://localhost:$UI_PORT" echo "Stop : docker rm -f speculos-zcash" diff --git a/rust/src/account.rs b/rust/src/account.rs index 6ab27d533..4096fa303 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -96,6 +96,9 @@ pub async fn new_account( } let pools = na.pools.unwrap_or(ALL_POOLS); + if pools == 0 { + anyhow::bail!("an account must support at least one pool"); + } let ledger_kind = if ledger_kind.is_ledger() { match ledger_kind { @@ -105,9 +108,9 @@ pub async fn new_account( "Official Ledger accounts support transparent and ironwood pools only" ); } - if !is_valid_phrase(&key) { + if !key.is_empty() && !is_valid_phrase(&key) { anyhow::bail!( - "Official Ledger accounts require the recovery seed phrase. Importing the viewing key from the device is not supported yet" + "Official Ledger accounts accept a seed phrase or no key to import the viewing key from the device" ); } } @@ -176,6 +179,44 @@ pub async fn new_account( .await?; } update_dindex(&mut db_tx, account, dindex, true).await?; + } else if ledger_kind == Some(HwKind::Official) && key.is_empty() { + // import the viewing key from the Official Ledger device + store_account_hw(&mut db_tx, account, HwKind::Official as u8, na.aindex).await?; + let ledger = get_ledger(&mut db_tx, account).await?; + let ufvk = ledger.get_ufvk(network, na.aindex).await?; + let uvk = UnifiedFullViewingKey::decode(network, &ufvk) + .map_err(|_| anyhow!("Invalid viewing key from the device"))?; + + // no sapling key on the device, so there is no derived default + // diversifier index; use 0 + let dindex: u32 = 0; + if pools & POOL_TRANSPARENT != 0 { + let tvk = uvk + .transparent() + .ok_or_else(|| anyhow!("device viewing key has no transparent key"))?; + init_account_transparent(&mut db_tx, account, birth).await?; + store_account_transparent_vk(&mut db_tx, account, tvk).await?; + let (pk, address) = derive_transparent_address(tvk, 0, dindex, false)?; + store_account_transparent_addr( + &mut db_tx, + account, + 0, + dindex, + None, + &pk, + &address.encode(&network), + false, + ) + .await?; + } + if pools & (POOL_ORCHARD | POOL_IRONWOOD) != 0 { + let ovk = uvk + .orchard() + .ok_or_else(|| anyhow!("device viewing key has no orchard key"))?; + init_account_orchard(network, &mut db_tx, account, birth).await?; + store_account_orchard_vk(&mut db_tx, account, ovk).await?; + } + update_dindex(&mut db_tx, account, dindex, true).await?; } else if is_valid_phrase(&key) { let seed_phrase = bip39::Mnemonic::from_str(&key)?; let passphrase = na.passphrase.clone().unwrap_or_default(); diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index 372957385..954414c84 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -939,7 +939,16 @@ pub(crate) async fn get_ledger( Box::new(crate::ledger::mock::StubLedger::no_support()) } } - HwKind::Official => Box::new(crate::ledger::mock::StubLedger::official()), + HwKind::Official => { + #[cfg(feature = "ledger")] + { + Box::new(crate::ledger::official::OfficialApp {}) + } + #[cfg(not(feature = "ledger"))] + { + Box::new(crate::ledger::mock::StubLedger::official()) + } + } HwKind::Software => Box::new(crate::ledger::mock::StubLedger::software()), }) } diff --git a/rust/src/ledger/README.md b/rust/src/ledger/README.md index 630b238cb..9735d833f 100644 --- a/rust/src/ledger/README.md +++ b/rust/src/ledger/README.md @@ -26,9 +26,8 @@ The app under emulation is the Rust rewrite of [LedgerHQ/app-zcash](https://github.com/LedgerHQ/app-zcash) (v3.9.3+). It speaks CLA `0xE0` (Bitcoin-app style) with Zcash extensions (INS `0x50` VK, `0x51` shielded address, `0x52`-`0x59` PCZT/Ironwood). zkool's app-layer code -(`builder.rs`, `fvk.rs`, ...) still speaks the legacy Zondax CLA `0x85` -protocol and needs migration; only the version smoke test speaks `0xE0` today. -The transport layer is protocol-agnostic and unchanged. +speaks `0xE0` for GET_VK (`official.rs`, used by hw=2 accounts); the Zondax +`0x85` protocol remains for hw=1. The transport layer is protocol-agnostic. ## Account types (`accounts.hw`) @@ -36,15 +35,17 @@ The transport layer is protocol-agnostic and unchanged. | --- | --- | --- | --- | | 0 | software | all | n/a | | 1 | Zondax | transparent + sapling | CLA `0x85` | -| 2 | Official | transparent + ironwood | CLA `0xE0` (not implemented yet) | - -v1 Official behavior: accounts are created from the recovery seed with -standard ZIP-32 derivation (no device needed); device operations return clear -errors via `ledger::mock::StubLedger`. Ironwood shares its keys with Orchard -(see `api::account::get_account_pools`), so Official accounts are initialized -with the Orchard key set. Pool masks are validated at creation -(`account.rs`). Selection UI lives in the New Account form -(`lib/pages/new_account.dart`). +| 2 | Official | transparent + ironwood | CLA `0xE0`: GET_VK (`0x50`) implemented, PCZT signing not yet | + +Official accounts (hw=2): `new_account` accepts an empty key, in which case +the UFVK is imported from the device (GET_VK, user-approved on screen) and +the per-pool keys are stored from it — this is the v2 device-import flow +(`account.rs`). A seed phrase is still accepted and derived like a regular +account (v1). Ironwood shares its keys with Orchard (see +`api::account::get_account_pools`). The diversifier index is 0 for imported +accounts (the device UFVK carries no sapling `dk`, so there is no derived +default index). Pool masks are validated at creation (`account.rs`). +Selection UI lives in the New Account form (`lib/pages/new_account.dart`). ## Prerequisites @@ -128,6 +129,22 @@ test ledger::tests::ledger_app_version ... ok The test lives in `rust/src/ledger/tests.rs` and is `#[ignore]`-gated so regular `cargo test` runs do not require the emulator. +`ledger_get_ufvk` additionally needs: + +- The emulator seeded with the `EMULATOR_SEED` constant from the test: + `SEED="..." misc/ledger/run-emulator.sh` +- The REST API port: `ZEMU_UI_PORT` (default 5000; the script's `UI_PORT` + knob must match — use 5001 on macOS, where AirPlay Receiver squats on + 5000). +- The `ledger-transport-zemu` `[patch]` (workspace root `Cargo.toml`): it + raises the crate's 5s per-APDU HTTP timeout to 120s (`ZEMU_TIMEOUT_SECS`), + since GET_VK blocks on the on-device review. + +The test drives the NBGL review itself (right button pages, both buttons +confirms) via the speculos REST API and compares the device UFVK against +the key derived locally from the same seed. Failed runs can leave a pending +review on the emulator; restart it before re-running. + - `ZEMU_HOST` / `ZEMU_PORT` env vars override the endpoint (defaults `127.0.0.1:9999`), e.g. to point at an emulator on another machine. - On macOS this hits the local speculos container by design; a physical diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index 6953cab29..08f85d442 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -43,6 +43,7 @@ cfg_if::cfg_if! { pub mod fvk; pub mod hashers; pub mod nano; + pub mod official; #[cfg(test)] mod tests; @@ -93,6 +94,10 @@ pub trait LedgerApp: Send + Sync { anyhow::bail!("not supported by this Ledger app") } + async fn get_ufvk(&self, _network: &Network, _aindex: u32) -> Result<String> { + anyhow::bail!("not supported by this Ledger app") + } + async fn show_sapling_address( &self, _network: &Network, diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs new file mode 100644 index 000000000..1d42cdb66 --- /dev/null +++ b/rust/src/ledger/official.rs @@ -0,0 +1,115 @@ +// Official Ledger App (LedgerHQ/app-zcash, CLA 0xE0) + +use anyhow::Result; +use byteorder::{WriteBytesExt, BE}; +use tonic::async_trait; +use zcash_keys::keys::UnifiedFullViewingKey; +use zcash_protocol::consensus::NetworkConstants as _; + +use crate::{ + api::coin::Network, + ledger::{ + transport::{connect_ledger, APDUCommand, Device}, + HwKind, LedgerApp, LedgerError, LedgerResult, + }, +}; + +pub struct OfficialApp {} + +const CLA: u8 = 0xE0; +const INS_GET_VK: u8 = 0x50; +const P1_FIRST: u8 = 0x00; +const P1_CONTINUE: u8 = 0x80; +const P2_UFVK: u8 = 0x00; +const SW_OK: u16 = 0x9000; +const SW_DENY: u16 = 0x6985; +const HARDENED: u32 = 0x8000_0000; +const MAX_RESPONSE_LEN: usize = 4096; + +fn append_path(data: &mut Vec<u8>, purpose: u32, coin_type: u32, account: u32) -> LedgerResult<()> { + data.write_u8(3)?; + data.write_u32::<BE>(purpose | HARDENED)?; + data.write_u32::<BE>(coin_type | HARDENED)?; + data.write_u32::<BE>(account | HARDENED)?; + Ok(()) +} + +/// Ask the device for the account UFVK (Orchard + transparent receivers). +/// The user must approve the export on the device. +pub async fn get_ufvk<D: Device>(ledger: &D, network: &Network, aindex: u32) -> LedgerResult<String> { + let coin_type = network.coin_type(); + let mut data = vec![]; + // m/32'/coin'/account' (Orchard, ZIP-32) then m/44'/coin'/account' (transparent) + append_path(&mut data, 32, coin_type, aindex)?; + append_path(&mut data, 44, coin_type, aindex)?; + assert_eq!(data.len(), 26); + + let get_vk = APDUCommand { + cla: CLA, + ins: INS_GET_VK, + p1: P1_FIRST, + p2: P2_UFVK, + data, + }; + let res = ledger.execute(get_vk).await?; + if res.retcode == SW_DENY { + return Err(LedgerError::Generic( + SW_DENY, + "user refused to export the viewing key".into(), + )); + } + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, INS_GET_VK)); + } + + // response is len (u16 BE) || ufvk string, delivered in chunks + let mut payload = res.data; + if payload.len() < 2 { + return Err(LedgerError::Protocol("short vk response".into())); + } + let len = u16::from_be_bytes([payload[0], payload[1]]) as usize; + payload.drain(..2); + if len > payload.len() { + if len > MAX_RESPONSE_LEN { + return Err(LedgerError::Protocol("vk response too long".into())); + } + payload.reserve(len - payload.len()); + } + while payload.len() < len { + let next = APDUCommand { + cla: CLA, + ins: INS_GET_VK, + p1: P1_CONTINUE, + p2: P2_UFVK, + data: vec![], + }; + let res = ledger.execute(next).await?; + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, INS_GET_VK)); + } + payload.extend_from_slice(&res.data); + } + payload.truncate(len); + + let ufvk = String::from_utf8(payload).map_err(|_| LedgerError::Protocol("invalid utf8 in vk response".into()))?; + let uvk = UnifiedFullViewingKey::decode(network, &ufvk) + .map_err(|_| LedgerError::Protocol("device returned an invalid UFVK".into()))?; + if uvk.orchard().is_none() || uvk.transparent().is_none() { + return Err(LedgerError::Protocol( + "device UFVK is missing the orchard or transparent receiver".into(), + )); + } + Ok(ufvk) +} + +#[async_trait] +impl LedgerApp for OfficialApp { + fn kind(&self) -> HwKind { + HwKind::Official + } + + async fn get_ufvk(&self, network: &Network, aindex: u32) -> Result<String> { + let ledger = connect_ledger().await?; + Ok(get_ufvk(&ledger, network, aindex).await?) + } +} diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index a0836e968..5dfc03cc9 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -2,6 +2,238 @@ use crate::ledger::transport::{APDUCommand, Device, LEDGER_ZEMU}; use super::*; +/// Speculos REST API port for the device screen/buttons (see run-emulator.sh). +fn ui_port() -> u16 { + std::env::var("ZEMU_UI_PORT") + .ok() + .and_then(|p| p.parse().ok()) + .unwrap_or(5000) +} + +fn ui_post(path: &str, body: &str) { + use std::io::{Read as _, Write as _}; + + let req = format!( + "POST {path} HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", + body.len(), + body + ); + let Ok(mut s) = std::net::TcpStream::connect(("127.0.0.1", ui_port())) else { + return; + }; + if s.write_all(req.as_bytes()).is_ok() { + let _ = s.read_to_end(&mut vec![]); + } +} + +fn press_right() { + ui_post( + "/button/right", + r#"{"action": "press-and-release"}"#, + ); +} + +fn press_both() { + ui_post("/button/both", r#"{"action": "press-and-release"}"#); +} + +fn screen_text() -> String { + use std::io::{Read as _, Write as _}; + + let req = format!( + "GET /events?currentscreenonly=true HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n", + ); + let Ok(mut s) = std::net::TcpStream::connect(("127.0.0.1", ui_port())) else { + return String::new(); + }; + if s.write_all(req.as_bytes()).is_err() { + return String::new(); + } + let mut buf = vec![]; + if s.read_to_end(&mut buf).is_err() { + return String::new(); + } + let body = String::from_utf8_lossy(&buf); + let Ok(json) = serde_json::from_str::<serde_json::Value>(body.split("\r\n\r\n").nth(1).unwrap_or("")) else { + return String::new(); + }; + json["events"] + .as_array() + .map(|events| { + events + .iter() + .filter_map(|e| e["text"].as_str()) + .collect::<Vec<_>>() + .join(" ") + }) + .unwrap_or_default() +} + +/// Drive the NBGL review: advance pages with the right button and confirm +/// the export with a both-button press on the Confirm choice. Loops until +/// the deadline so stale reviews from earlier failed runs are approved too. +fn spawn_approval_driver() { + std::thread::spawn(|| { + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(120); + while std::time::Instant::now() < deadline { + let text = screen_text(); + if text.contains("Confirm") { + eprintln!("driver: both (screen: {text:?})"); + press_both(); + } else { + eprintln!("driver: right (screen: {text:?})"); + press_right(); + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } + }); +} + +/// Get the account UFVK from the Official Ledger app (GET_VK, CLA 0xE0) and +/// compare it against the same key derived locally from the emulator seed. +/// The expected value is therefore computed, not provided. +/// +/// Run with the emulator up (seeded with EMULATOR_SEED): +/// `cargo test --features zemu -- --ignored --nocapture ledger_get_ufvk` +#[tokio::test] +#[ignore] +pub async fn ledger_get_ufvk() -> LedgerResult<()> { + use std::str::FromStr as _; + + use zcash_address::unified::{Encoding as _, Fvk, Ufvk}; + use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey}; + use zip32::AccountId; + + const EMULATOR_SEED: &str = "display accident enable raw glimpse engine know fog bubble price bunker minimum entry tuna joy motor rate tennis evolve october verb jelly indoor dance"; + + let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); + let network = Network::Main; + + // expected UFVK (orchard + transparent receivers) from the emulator seed + let mnemonic = bip39::Mnemonic::from_str(EMULATOR_SEED) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("bad seed: {e}")))?; + let seed = mnemonic.to_seed(""); + let usk = UnifiedSpendingKey::from_seed(&network, &seed, AccountId::try_from(0).unwrap()) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("usk derivation failed: {e}")))?; + let uvk = usk.to_unified_full_viewing_key(); + let items = vec![ + Fvk::P2pkh(uvk.transparent().unwrap().serialize().try_into().unwrap()), + Fvk::Orchard(uvk.orchard().unwrap().to_bytes()), + ]; + let expected = UnifiedFullViewingKey::parse( + &Ufvk::try_from_items(items).map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?, + ) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))? + .encode(&network); + + spawn_approval_driver(); + + let ufvk = tokio::time::timeout( + std::time::Duration::from_secs(60), + official::get_ufvk(&ledger, &network, 0), + ) + .await + .map_err(|_| LedgerError::Protocol("timeout waiting for the device answer".into()))??; + + println!("device : {ufvk}"); + println!("expected : {expected}"); + assert_eq!(ufvk, expected, "device UFVK does not match the seed-derived key"); + Ok(()) +} + +/// Create an Official Ledger account (hw=2, no seed phrase) against the +/// device and check that the stored keys match the device UFVK. +/// Needs the emulator up, seeded with EMULATOR_SEED (see ledger_get_ufvk): +/// `ZEMU_UI_PORT=5001 cargo test --features zemu -- --ignored --nocapture ledger_account_import` +#[tokio::test] +#[ignore] +pub async fn ledger_account_import() -> LedgerResult<()> { + use std::str::FromStr as _; + + use sqlx::Connection as _; + use zcash_address::unified::Encoding as _; + use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey}; + use zip32::AccountId; + + const EMULATOR_SEED: &str = "display accident enable raw glimpse engine know fog bubble price bunker minimum entry tuna joy motor rate tennis evolve october verb jelly indoor dance"; + + let network = Network::Main; + let mut db = std::env::temp_dir(); + db.push(format!("zkool_ol_import_{}.db", std::process::id())); + let mut connection = sqlx::sqlite::SqliteConnection::connect_with( + &sqlx::sqlite::SqliteConnectOptions::new() + .filename(&db) + .create_if_missing(true), + ) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::create_schema(&mut connection) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + + let na = crate::api::account::NewAccount { + icon: None, + name: "ol".into(), + restore: false, + key: String::new(), + passphrase: None, + fingerprint: None, + aindex: 0, + birth: None, + folder: String::new(), + pools: Some(crate::pay::pool::POOL_TRANSPARENT | crate::pay::pool::POOL_IRONWOOD), + use_internal: false, + internal: false, + hw: HwKind::Official as u8, + }; + + spawn_approval_driver(); + let account = tokio::time::timeout( + std::time::Duration::from_secs(60), + crate::account::new_account(&network, &mut connection, &na), + ) + .await + .map_err(|_| LedgerError::Protocol("timeout waiting for the device answer".into()))? + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + + // stored keys must compose the same UFVK as the device exported + let dindex = crate::db::get_account_dindex(&mut connection, account) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + assert_eq!(dindex, 0); + let hw = crate::db::get_account_hw(&mut connection, account) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + assert_eq!(hw, HwKind::Official as u8); + let ufvk = crate::key::get_account_ufvk(&network, &mut connection, account, 5) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + + let mnemonic = bip39::Mnemonic::from_str(EMULATOR_SEED) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("bad seed: {e}")))?; + let seed = mnemonic.to_seed(""); + let usk = UnifiedSpendingKey::from_seed(&network, &seed, AccountId::try_from(0).unwrap()) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("usk derivation failed: {e}")))?; + let uvk = usk.to_unified_full_viewing_key(); + let expected = UnifiedFullViewingKey::parse( + &zcash_address::unified::Ufvk::try_from_items(vec![ + zcash_address::unified::Fvk::Orchard(uvk.orchard().unwrap().to_bytes()), + zcash_address::unified::Fvk::P2pkh( + uvk.transparent().unwrap().serialize().try_into().unwrap(), + ), + ]) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?, + ) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))? + .encode(&network); + + println!("db ufvk : {ufvk}"); + println!("expected : {expected}"); + assert_eq!(ufvk, expected, "stored keys do not match the device UFVK"); + std::fs::remove_file(&db).ok(); + Ok(()) +} + /// Smoke test for the speculos emulator (or a device via ZEMU_HOST/ZEMU_PORT). /// Speaks the new app-zcash protocol (CLA 0xE0) and only checks that the app /// answers GET_FIRMWARE_VERSION with the legacy Zondax version format. From 121b51d9737e7c3a5be8d99144578713582b4177 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 19:18:06 +0800 Subject: [PATCH 149/189] fix: build v6 for Official Ledger accounts and open the APDU HID interface - force v5 only for Zondax accounts; Official Ledger accounts can carry Ironwood spends, which require v6 (v5 with an Ironwood bundle is rejected by the builder as TargetIncompatible) - open only the APDU HID interface (usage page 0xFFA0); the console interface accepts writes but never answers, hanging the wallet --- rust/src/ledger/transport.rs | 6 ++++-- rust/src/pay/plan.rs | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/rust/src/ledger/transport.rs b/rust/src/ledger/transport.rs index 1f5e027f4..193408c35 100644 --- a/rust/src/ledger/transport.rs +++ b/rust/src/ledger/transport.rs @@ -16,8 +16,10 @@ use crate::{ pub fn open_ledger(api: &HidApi) -> LedgerResult<HidDevice> { for devinfo in api.device_list() { let vendor_id = devinfo.vendor_id(); - if vendor_id == 0x2C97 { - // Ledger + // Ledger devices expose two HID interfaces: the APDU one (usage page + // 0xFFA0) and a console one (0xFF00) that accepts writes but never + // answers, which would hang the wallet. + if vendor_id == 0x2C97 && devinfo.usage_page() == 0xFFA0 { let device = devinfo.open_device(api)?; let _ = device.set_blocking_mode(true); return Ok(device); diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 7fed6683b..fcb17766e 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -58,6 +58,7 @@ use crate::{ api::{coin::Network, issuance::IssuanceInfo, pay::PcztPackage}, db::{get_account_dindex, get_account_hw, select_account_transparent}, keys::{sapling_pgk_for_scope, sapling_ssk_for_scope, SaplingFullViewingKey}, + ledger::HwKind, pay::{ error::Error, fee::COST_PER_ACTION, @@ -819,8 +820,10 @@ pub async fn plan_transaction( // The Zondax "Zcash Shielded" app predates NU6.3 and cannot sign v6/Ironwood // transactions, so force a v5 tx while keeping consensus_branch_id = Nu6_3 // (V5 is valid in Nu6_3 per TxVersion::valid_in_branch). A v5 tx carrying the - // current Nu6_3 branch id is valid on the network. - if hw != 0 { + // current Nu6_3 branch id is valid on the network. The official Ledger app + // supports v6/Ironwood signing and must not be forced to v5, otherwise any + // tx carrying Ironwood spends fails to build. + if hw == HwKind::Zondax as u8 { builder .propose_version::<()>(TxVersion::V5) .map_err(|e| anyhow!("failed to force v5 for hardware signing: {e:?}"))?; From 6b353cf528666ef247c2d03ec45546c03e774cb6 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 19:18:06 +0800 Subject: [PATCH 150/189] chore: drop per-tx mempool debug log --- rust/src/mempool.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/src/mempool.rs b/rust/src/mempool.rs index fb8800266..fdd6c0882 100644 --- a/rust/src/mempool.rs +++ b/rust/src/mempool.rs @@ -105,7 +105,6 @@ pub async fn run_mempool_impl<S: Sink<MempoolMsg> + Send + 'static>( Some((_, tx, len)) => { let txid = tx.txid(); let tx_hash = txid.to_string(); - tracing::debug!("MP {tx_hash}"); let tx_data = tx.into_data(); From 1128d2c12fd5654a0eb889b7fe0f307799a6bfd6 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 19:18:23 +0800 Subject: [PATCH 151/189] ci: bump CI Flutter version to 3.47.2 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50bf3555f..09f9170b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - os: windows-latest target: windows env: - FLUTTER_VERSION: 3.47.1 + FLUTTER_VERSION: 3.47.2 permissions: id-token: write attestations: write From e6e462c6a71b7c3add7f823a280da9a69f525b84 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 23:35:25 +0800 Subject: [PATCH 152/189] feat: sign v6 transactions with the Official Ledger app Implement the app-zcash PCZT APDU protocol (CLA 0xE0): frame the PCZT into the compact APDU subset (header, transparent inputs with full BIP-44 paths, outputs, orchard/ironwood actions with chunked ciphertexts, trailers), collect transparent (DER + sighash byte, with the device's parity-in-tag quirk) and shielded spend authorization signatures, apply them via the PCZT signer, then compute proofs and the binding signature host-side. Includes a speculos test planning an ironwood-to-ironwood transaction from the emulator seed and verifying the device signatures against the host sighash. --- rust/src/ledger/mod.rs | 1 + rust/src/ledger/official.rs | 23 +- rust/src/ledger/official_sign.rs | 681 +++++++++++++++++++++++++++++++ rust/src/ledger/tests.rs | 257 +++++++++++- 4 files changed, 957 insertions(+), 5 deletions(-) create mode 100644 rust/src/ledger/official_sign.rs diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index 08f85d442..1c63275c1 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -44,6 +44,7 @@ cfg_if::cfg_if! { pub mod hashers; pub mod nano; pub mod official; + pub mod official_sign; #[cfg(test)] mod tests; diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs index 1d42cdb66..590ed8a5c 100644 --- a/rust/src/ledger/official.rs +++ b/rust/src/ledger/official.rs @@ -7,7 +7,11 @@ use zcash_keys::keys::UnifiedFullViewingKey; use zcash_protocol::consensus::NetworkConstants as _; use crate::{ - api::coin::Network, + api::{ + coin::{Coin, Network}, + pay::{PcztPackage, SigningEvent}, + }, + frb_generated::StreamSink, ledger::{ transport::{connect_ledger, APDUCommand, Device}, HwKind, LedgerApp, LedgerError, LedgerResult, @@ -112,4 +116,21 @@ impl LedgerApp for OfficialApp { let ledger = connect_ledger().await?; Ok(get_ufvk(&ledger, network, aindex).await?) } + + async fn sign_pczt( + &self, + sink: StreamSink<SigningEvent>, + package: PcztPackage, + c: &Coin, + ) -> Result<()> { + let connection = c.get_connection().await?; + crate::ledger::official_sign::sign_official_transaction( + c.network(), + sink, + connection, + c.account, + package, + )?; + Ok(()) + } } diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs new file mode 100644 index 000000000..678a4f89f --- /dev/null +++ b/rust/src/ledger/official_sign.rs @@ -0,0 +1,681 @@ +// Official Ledger app (LedgerHQ/app-zcash) signing over the PCZT APDU protocol. +// +// Wire contract: docs/PCZT_APDU.md in the app-zcash repository (CLA 0xE0). +// V6 (Ironwood) transactions only: the PCZT fields are framed by hand into the +// app's compact APDU subset, the device reviews and returns spend authorizing / +// transparent signatures, and proofs + binding signature are computed host-side. + +use std::collections::HashMap; +use std::io::Write as _; + +use anyhow::{anyhow, Result}; +use byteorder::{WriteBytesExt, BE, LE}; +use ff::PrimeField as _; +use orchard::pczt::Action; +use orchard::primitives::redpallas; +use pczt::roles::{prover::Prover, signer::Signer, spend_finalizer::SpendFinalizer}; +use sqlx::{pool::PoolConnection, Row, Sqlite, SqliteConnection}; +use zcash_note_encryption::Domain; +use zcash_protocol::consensus::NetworkConstants as _; + +use crate::{ + account::get_orchard_vk, + api::{ + coin::Network, + pay::{PcztPackage, SigningEvent}, + }, + db::{get_account_aindex, get_account_dindex}, + frb_generated::StreamSink, + ledger::{ + transport::{APDUCommand, Device}, + LedgerError, + }, + pay::plan::{get_orchard_pk, IRONWOOD_PK}, +}; + +const CLA: u8 = 0xE0; +const INS_PCZT_HEADER: u8 = 0x52; +const INS_PCZT_TRANSPARENT_INPUT: u8 = 0x53; +const INS_PCZT_TRANSPARENT_OUTPUT: u8 = 0x54; +const INS_PCZT_SIGN_TRANSPARENT: u8 = 0x55; +const INS_PCZT_ORCHARD_ACTION: u8 = 0x56; +const INS_PCZT_SIGN_ORCHARD: u8 = 0x57; +const INS_PCZT_IRONWOOD_ACTION: u8 = 0x58; +const INS_PCZT_SIGN_IRONWOOD: u8 = 0x59; + +const P1_FIRST: u8 = 0x00; +const P1_NEXT: u8 = 0x80; +const P1_LAST: u8 = 0x01; +const P2_CONTINUE: u8 = 0x00; +const P2_FINISHED: u8 = 0x01; + +const SW_OK: u16 = 0x9000; +const SW_DENY: u16 = 0x6985; + +const HARDENED: u32 = 0x8000_0000; +const SIGHASH_ALL: u8 = 0x01; +const PCZT_VERSION_V6: u32 = 2; +const NOTE_VERSION_IRONWOOD: u8 = 0x03; +// The device displays at most 4 shielded outputs across both pools. +const MAX_DISPLAYED_SHIELDED_OUTPUTS: usize = 4; + +fn write_compact_size(data: &mut Vec<u8>, n: usize) -> Result<()> { + if n < 253 { + data.write_u8(n as u8)?; + } else if n <= 0xFFFF { + data.write_u8(0xFD)?; + data.write_u16::<LE>(n as u16)?; + } else if n <= 0xFFFF_FFFF { + data.write_u8(0xFE)?; + data.write_u32::<LE>(n as u32)?; + } else { + data.write_u8(0xFF)?; + data.write_u64::<LE>(n as u64)?; + } + Ok(()) +} + +fn write_optional_u32(data: &mut Vec<u8>, value: Option<u32>) -> Result<()> { + match value { + None => data.write_u8(0x00)?, + Some(v) => { + data.write_u8(0x01)?; + data.write_u32::<LE>(v)?; + } + } + Ok(()) +} + +fn write_bip32_path(data: &mut Vec<u8>, path: &[u32]) -> Result<()> { + data.write_u8(path.len() as u8)?; + for component in path { + data.write_u32::<BE>(*component)?; + } + Ok(()) +} + +async fn send_command<D: Device>( + ledger: &D, + ins: u8, + packets: Vec<Vec<u8>>, + finished: bool, +) -> Result<()> { + let n = packets.len(); + for (i, data) in packets.into_iter().enumerate() { + if data.len() > 255 { + anyhow::bail!("APDU packet too long for instruction {ins:#x}"); + } + let p1 = if i == 0 { + P1_FIRST + } else if i == n - 1 { + P1_LAST + } else { + P1_NEXT + }; + let p2 = if finished && i == n - 1 { + P2_FINISHED + } else { + P2_CONTINUE + }; + let res = ledger + .execute(APDUCommand { + cla: CLA, + ins, + p1, + p2, + data, + }) + .await?; + if res.retcode == SW_DENY { + anyhow::bail!("the transaction was refused on the Ledger device"); + } + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, ins).into()); + } + } + Ok(()) +} + +async fn sign_one<D: Device>(ledger: &D, ins: u8, index: u32) -> Result<[u8; 64]> { + let res = ledger + .execute(APDUCommand { + cla: CLA, + ins, + p1: 0, + p2: index as u8, + data: vec![], + }) + .await?; + if res.retcode == SW_DENY { + anyhow::bail!("the transaction was refused on the Ledger device"); + } + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, ins).into()); + } + if res.data.len() != 64 { + anyhow::bail!("unexpected signature length for instruction {ins:#x}"); + } + Ok(res.data[..64].try_into().unwrap()) +} + +// The transparent signing command answers with a DER signature followed by the +// sighash type byte. +async fn sign_transparent_input<D: Device>( + ledger: &D, + index: u32, +) -> Result<secp256k1::ecdsa::Signature> { + let res = ledger + .execute(APDUCommand { + cla: CLA, + ins: INS_PCZT_SIGN_TRANSPARENT, + p1: 0, + p2: index as u8, + data: vec![], + }) + .await?; + if res.retcode == SW_DENY { + anyhow::bail!("the transaction was refused on the Ledger device"); + } + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, INS_PCZT_SIGN_TRANSPARENT).into()); + } + let (sighash_type, der) = res + .data + .split_last() + .ok_or_else(|| anyhow!("empty transparent signature response"))?; + if *sighash_type != SIGHASH_ALL { + anyhow::bail!("unexpected transparent sighash type {sighash_type:#x}"); + } + // The app folds the y-parity of the key into the LSB of the DER SEQUENCE + // tag byte (sig[0] |= 0x01). The parity is irrelevant here — the signature + // verifies against the pubkey from the PCZT's hash160 preimage — so clear + // it before parsing. + let mut der = der.to_vec(); + der[0] &= !0x01; + secp256k1::ecdsa::Signature::from_der(&der).map_err(|e| { + anyhow!( + "invalid DER transparent signature: {e} ({})", + hex::encode(&der) + ) + }) +} + +// Per-action spend fields: cv_net, nullifier, rk, recipient, value, rho, +// rseed, alpha — one packet. +fn frame_spend_small<D: Domain>(action: &Action<D>) -> Result<Vec<u8>> { + let spend = action.spend(); + let mut data = vec![]; + data.write_all(&action.cv_net().to_bytes())?; + data.write_all(&spend.nullifier().to_bytes())?; + data.write_all(&<[u8; 32]>::from(spend.rk()))?; + let recipient = spend + .recipient() + .as_ref() + .ok_or_else(|| anyhow!("orchard spend has no recipient"))?; + data.write_all(&recipient.to_raw_address_bytes())?; + data.write_u64::<LE>(spend.value().ok_or_else(|| anyhow!("orchard spend has no value"))?.inner())?; + data.write_all(&spend.rho().ok_or_else(|| anyhow!("orchard spend has no rho"))?.to_bytes())?; + data.write_all(spend.rseed().ok_or_else(|| anyhow!("orchard spend has no rseed"))?.as_bytes())?; + data.write_all( + &spend + .alpha() + .ok_or_else(|| anyhow!("orchard spend has no alpha"))? + .to_repr(), + )?; + Ok(data) +} + +// zip32 derivation packet: seed fingerprint + 32'/coin'/account'. The device +// derives the spending key from this path; the seed fingerprint is not +// validated by the app. +fn frame_zip32(coin_type: u32, aindex: u32) -> Result<Vec<u8>> { + let mut data = vec![0u8; 32]; + write_bip32_path(&mut data, &[32 | HARDENED, coin_type | HARDENED, aindex | HARDENED])?; + Ok(data) +} + +// Output small fields: cmx + ephemeral key — one packet. +fn frame_output_small<D: Domain>(action: &Action<D>) -> Result<Vec<u8>> { + let output = action.output(); + let mut data = vec![]; + data.write_all(&output.cmx().to_bytes())?; + data.write_all(&output.encrypted_note().epk_bytes)?; + Ok(data) +} + +// Large Vec<u8> fields are sent as their own APDU packet sequence: the first +// packet carries the CompactSize byte length followed by as many field bytes +// as fit, continuation packets carry field bytes only (docs/PCZT_APDU.md). +fn frame_large_field(packets: &mut Vec<Vec<u8>>, field: &[u8]) -> Result<()> { + let mut first = vec![]; + write_compact_size(&mut first, field.len())?; + let take = (255 - first.len()).min(field.len()); + first.extend_from_slice(&field[..take]); + packets.push(first); + let mut rest = &field[take..]; + while !rest.is_empty() { + let take = rest.len().min(255); + packets.push(rest[..take].to_vec()); + rest = &rest[take..]; + } + Ok(()) +} + +fn frame_enc_ciphertext<D: Domain>(packets: &mut Vec<Vec<u8>>, action: &Action<D>) -> Result<()> { + let enc: &[u8] = action.output().encrypted_note().enc_ciphertext.as_ref(); + frame_large_field(packets, enc) +} + +fn frame_out_ciphertext<D: Domain>(packets: &mut Vec<Vec<u8>>, action: &Action<D>) -> Result<()> { + let out: &[u8] = &action.output().encrypted_note().out_ciphertext; + frame_large_field(packets, out) +} + +// Output metadata: recipient, value, rseed, rcv (+ notePlaintextVersion 0x03 +// for ironwood, making the 116-byte form). +fn frame_output_metadata<D: Domain>(action: &Action<D>, ironwood: bool) -> Result<Vec<u8>> { + let output = action.output(); + let mut data = vec![]; + let recipient = output + .recipient() + .as_ref() + .ok_or_else(|| anyhow!("orchard output has no recipient"))?; + data.write_all(&recipient.to_raw_address_bytes())?; + data.write_u64::<LE>( + output + .value() + .ok_or_else(|| anyhow!("orchard output has no value"))? + .inner(), + )?; + data.write_all(output.rseed().ok_or_else(|| anyhow!("orchard output has no rseed"))?.as_bytes())?; + data.write_all( + &action + .rcv() + .as_ref() + .ok_or_else(|| anyhow!("orchard action has no rcv"))? + .to_bytes(), + )?; + if ironwood { + data.write_u8(NOTE_VERSION_IRONWOOD)?; + } + Ok(data) +} + +// Bundle trailer: flags, |value_sum|, negative flag, anchor — one packet. +fn frame_trailer<D: Domain>(bundle: &orchard::pczt::Bundle<D>) -> Result<Vec<u8>> { + let (magnitude, sign) = bundle.value_sum().magnitude_sign(); + let mut data = vec![]; + data.write_u8(bundle.flag_byte())?; + data.write_u64::<LE>(magnitude)?; + data.write_u8(matches!(sign, orchard::value::Sign::Negative) as u8)?; + data.write_all(&(*bundle.anchor()).to_bytes())?; + Ok(data) +} + +// ── Shielded bundle framing ─────────────────────────────────────────────── + +fn frame_shielded_bundle<D: Domain>( + bundle: &orchard::pczt::Bundle<D>, + coin_type: u32, + aindex: u32, + internal_change: Option<&[u8; 43]>, + ironwood: bool, +) -> Result<(Vec<Vec<u8>>, usize)> { + let mut displayed = 0usize; + let mut packets = vec![]; + + let mut count = vec![]; + write_compact_size(&mut count, bundle.actions().len())?; + packets.push(count); + + for action in bundle.actions() { + packets.push(frame_spend_small(action)?); + packets.push(frame_zip32(coin_type, aindex)?); + packets.push(frame_output_small(action)?); + frame_enc_ciphertext(&mut packets, action)?; + frame_out_ciphertext(&mut packets, action)?; + packets.push(frame_output_metadata(action, ironwood)?); + if let Some(recipient) = action.output().recipient().as_ref() { + let is_change = internal_change.is_some_and(|change| change == &recipient.to_raw_address_bytes()); + if !is_change && action.output().value().is_some_and(|v| v.inner() > 0) { + displayed += 1; + } + } + } + + if !bundle.actions().is_empty() { + packets.push(frame_trailer(bundle)?); + } + + Ok((packets, displayed)) +} + +pub async fn sign_transaction<D: Device + Sync>( + network: &Network, + connection: &mut SqliteConnection, + account: u32, + package: &PcztPackage, + sink: Option<&StreamSink<SigningEvent>>, + ledger: &D, +) -> Result<PcztPackage> { + use pczt::Pczt; + use pczt::roles::updater::Updater; + + let progress = |msg: String| { + if let Some(sink) = sink { + let _ = sink.add(SigningEvent::Progress(msg)); + } + }; + + progress("Preparing transaction".to_string()); + + if package.is_issuance { + anyhow::bail!("ZSA issuance is not supported on Official Ledger accounts"); + } + + let pczt = Pczt::parse(&package.pczt) + .map_err(|error| anyhow!("failed to parse PCZT: {error:?}"))?; + + if !pczt.sapling().spends().is_empty() || !pczt.sapling().outputs().is_empty() { + anyhow::bail!("Official Ledger accounts cannot spend Sapling notes"); + } + if *pczt.global().tx_version() != 6 { + anyhow::bail!("only v6 transactions are supported on Official Ledger accounts"); + } + + let coin_type = network.coin_type(); + let aindex = get_account_aindex(connection, account).await?; + let dindex = get_account_dindex(connection, account).await?; + + // Compressed pubkeys by address, for the transparent input derivation packets. + let pks: HashMap<String, Vec<u8>> = sqlx::query( + "SELECT address, pk FROM transparent_address_accounts WHERE account = ?", + ) + .bind(account) + .map(|row: sqlx::sqlite::SqliteRow| (row.get::<String, _>(0), row.get::<Vec<u8>, _>(1))) + .fetch_all(&mut *connection) + .await? + .into_iter() + .collect(); + + // The internal change address is hidden from the device review; every other + // positive shielded output counts against the device display budget. + let internal_change = get_orchard_vk(connection, account) + .await? + .map(|fvk| { + fvk.address_at(dindex, orchard::keys::Scope::Internal) + .to_raw_address_bytes() + }); + + // ── Transparent ─────────────────────────────────────────────────────── + let mut input_packets: Vec<Vec<u8>> = vec![]; + let mut output_packets: Vec<Vec<u8>> = vec![]; + { + let t = pczt.transparent(); + let mut count = vec![]; + write_compact_size(&mut count, t.inputs().len())?; + input_packets.push(count); + for input in t.inputs() { + let mut small = vec![]; + small.write_all(input.prevout_txid())?; + small.write_u32::<LE>(*input.prevout_index())?; + write_optional_u32(&mut small, *input.sequence())?; + small.write_u64::<LE>(*input.value())?; + input_packets.push(small); + + let script = input.script_pubkey(); + let mut script_packet = vec![]; + write_compact_size(&mut script_packet, script.len())?; + script_packet.write_all(script)?; + input_packets.push(script_packet); + + let address = input + .proprietary() + .get("address") + .ok_or_else(|| anyhow!("transparent input has no address"))?; + let address = String::from_utf8(address.clone()) + .map_err(|_| anyhow!("invalid transparent input address"))?; + let pk = pks + .get(&address) + .ok_or_else(|| anyhow!("no pubkey for transparent input {address}"))?; + if pk.len() != 33 { + anyhow::bail!("transparent input pubkey is not compressed"); + } + let scope = u32::from_le_bytes( + input + .proprietary() + .get("scope") + .ok_or_else(|| anyhow!("transparent input has no scope"))? + .clone() + .try_into() + .map_err(|_| anyhow!("invalid scope"))?, + ); + let input_dindex = u32::from_le_bytes( + input + .proprietary() + .get("dindex") + .ok_or_else(|| anyhow!("transparent input has no dindex"))? + .clone() + .try_into() + .map_err(|_| anyhow!("invalid dindex"))?, + ); + let mut signing = vec![SIGHASH_ALL]; + write_compact_size(&mut signing, 1)?; + signing.write_all(pk)?; + signing.write_all(&[0u8; 32])?; + write_bip32_path( + &mut signing, + &[ + 44 | HARDENED, + coin_type | HARDENED, + aindex | HARDENED, + scope, + input_dindex, + ], + )?; + input_packets.push(signing); + } + + let mut count = vec![]; + write_compact_size(&mut count, t.outputs().len())?; + output_packets.push(count); + for output in t.outputs() { + let mut value = vec![]; + value.write_u64::<LE>(*output.value())?; + output_packets.push(value); + + let script = output.script_pubkey(); + let mut script_packet = vec![]; + write_compact_size(&mut script_packet, script.len())?; + script_packet.write_all(script)?; + output_packets.push(script_packet); + + // No derivation on transparent outputs: they are displayed rather + // than hidden as change (the app requires an internal-scope path + // whose on-device derivation matches the output key). + output_packets.push(vec![0x00]); + } + } + + // ── Shielded bundles ────────────────────────────────────────────────── + let updater = Updater::new(pczt); + let mut orchard_framed: Result<(Vec<Vec<u8>>, usize)> = Ok((vec![], 0)); + let updater = updater + .update_orchard_with(|u| { + orchard_framed = + frame_shielded_bundle(u.bundle(), coin_type, aindex, internal_change.as_ref(), false); + Ok(()) + }) + .map_err(|error| anyhow!("failed to read the orchard bundle: {error:?}"))?; + let (orchard_packets, orchard_displayed) = orchard_framed?; + + let mut ironwood_framed: Result<(Vec<Vec<u8>>, usize)> = Ok((vec![], 0)); + let updater = updater + .update_ironwood_with(|u| { + ironwood_framed = + frame_shielded_bundle(u.bundle(), coin_type, aindex, internal_change.as_ref(), true); + Ok(()) + }) + .map_err(|error| anyhow!("failed to read the ironwood bundle: {error:?}"))?; + let (ironwood_packets, ironwood_displayed) = ironwood_framed?; + + let pczt = updater.finish(); + + let displayed_shielded_outputs = orchard_displayed + ironwood_displayed; + if displayed_shielded_outputs > MAX_DISPLAYED_SHIELDED_OUTPUTS { + anyhow::bail!( + "this transaction has {displayed_shielded_outputs} shielded outputs to display, \ + but the Ledger can show at most {MAX_DISPLAYED_SHIELDED_OUTPUTS}" + ); + } + + // ── Send to the device ──────────────────────────────────────────────── + progress("Confirm on your Ledger".to_string()); + + let header = { + let g = pczt.global(); + let mut data = vec![]; + data.write_all(b"PCZT")?; + data.write_u32::<LE>(PCZT_VERSION_V6)?; + data.write_u32::<LE>(*g.tx_version())?; + data.write_u32::<LE>(*g.version_group_id())?; + data.write_u32::<LE>(*g.consensus_branch_id())?; + data.write_u8(0x00)?; // fallback_lock_time: none (builder uses 0) + data.write_u32::<LE>(*g.expiry_height())?; + data.write_u32::<LE>(coin_type)?; + data.write_u8(0x00)?; // tx_modifiable: none + vec![data] + }; + + send_command(ledger, INS_PCZT_HEADER, header, false).await?; + send_command(ledger, INS_PCZT_TRANSPARENT_INPUT, input_packets, false).await?; + send_command(ledger, INS_PCZT_TRANSPARENT_OUTPUT, output_packets, false).await?; + // V6 defers the review to the ironwood command: it is always sent, even + // with 0 actions, and its last packet carries P2_FINISHED. + send_command(ledger, INS_PCZT_ORCHARD_ACTION, orchard_packets, false).await?; + send_command(ledger, INS_PCZT_IRONWOOD_ACTION, ironwood_packets, true).await?; + + // ── Collect signatures ──────────────────────────────────────────────── + progress("Signing on Ledger".to_string()); + + let ctin = pczt.transparent().inputs().len(); + + let mut tsigs = Vec::with_capacity(ctin); + for index in 0..ctin { + progress(format!( + "Signing transparent input {}/{}", + index + 1, + ctin + )); + tsigs.push(sign_transparent_input(ledger, index as u32).await?); + } + + let mut orchard_sigs = Vec::with_capacity(package.orchard_indices.len()); + for index in &package.orchard_indices { + progress("Signing orchard spend".to_string()); + orchard_sigs.push(sign_one(ledger, INS_PCZT_SIGN_ORCHARD, *index as u32).await?); + } + + let mut ironwood_sigs = Vec::with_capacity(package.ironwood_indices.len()); + for index in &package.ironwood_indices { + progress("Signing ironwood spend".to_string()); + ironwood_sigs.push(sign_one(ledger, INS_PCZT_SIGN_IRONWOOD, *index as u32).await?); + } + + // ── Apply signatures, proofs, binding signature ─────────────────────── + progress("Finalizing transaction".to_string()); + + let mut signer = Signer::new(pczt).map_err(|error| anyhow!("signer: {error:?}"))?; + for (index, sig) in tsigs.iter().enumerate() { + signer + .append_transparent_signature(index, *sig) + .map_err(|error| anyhow!("transparent signature {index}: {error:?}"))?; + } + for (index, sig) in package.orchard_indices.iter().zip(&orchard_sigs) { + let sig = redpallas::Signature::<redpallas::SpendAuth>::from(*sig); + signer + .apply_orchard_signature(*index, sig) + .map_err(|error| anyhow!("orchard signature {index}: {error:?}"))?; + } + for (index, sig) in package.ironwood_indices.iter().zip(&ironwood_sigs) { + let sig = redpallas::Signature::<redpallas::SpendAuth>::from(*sig); + signer + .apply_ironwood_signature(*index, sig) + .map_err(|error| anyhow!("ironwood signature {index}: {error:?}"))?; + } + let pczt = signer.finish(); + + let orchard_pk = get_orchard_pk(*pczt.global().consensus_branch_id())?; + let pczt = Prover::new(pczt) + .create_orchard_proof(orchard_pk) + .map_err(|error| anyhow!("orchard proof: {error:?}"))? + .create_ironwood_proof(&IRONWOOD_PK) + .map_err(|error| anyhow!("ironwood proof: {error:?}"))? + .finish(); + + let pczt = SpendFinalizer::new(pczt) + .finalize_spends() + .map_err(|error| anyhow!("failed to finalize spends: {error:?}"))?; + + let PcztPackage { + n_spends, + sapling_indices, + orchard_indices, + ironwood_indices, + can_sign, + can_broadcast, + price, + category, + is_issuance, + .. + } = package; + + Ok(PcztPackage { + pczt: pczt + .serialize() + .map_err(|error| anyhow!("failed to serialize PCZT: {error:?}"))?, + n_spends: *n_spends, + sapling_indices: sapling_indices.clone(), + orchard_indices: orchard_indices.clone(), + ironwood_indices: ironwood_indices.clone(), + can_sign: *can_sign, + can_broadcast: *can_broadcast, + price: *price, + category: *category, + is_issuance: *is_issuance, + }) +} + +pub fn sign_official_transaction( + network: Network, + sink: StreamSink<SigningEvent>, + mut connection: PoolConnection<Sqlite>, + account: u32, + package: PcztPackage, +) -> Result<()> { + tokio::spawn(async move { + let run = async { + let ledger = crate::ledger::transport::connect_ledger().await?; + sign_transaction( + &network, + &mut connection, + account, + &package, + Some(&sink), + &ledger, + ) + .await + } + .await; + match run { + Ok(new_package) => { + let _ = sink.add(SigningEvent::Result(new_package)); + } + Err(error) => { + let _ = sink.add_error(error); + } + } + Ok::<_, anyhow::Error>(()) + }); + Ok(()) +} diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index 5dfc03cc9..ac198684a 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -69,15 +69,23 @@ fn screen_text() -> String { .unwrap_or_default() } -/// Drive the NBGL review: advance pages with the right button and confirm -/// the export with a both-button press on the Confirm choice. Loops until -/// the deadline so stale reviews from earlier failed runs are approved too. +/// Drive the NBGL review: advance pages with the right button. The post-review +/// "Address verified" status and the "Sign transaction" approval page need a +/// both-button press; "Reject transaction" means the approval page was +/// overshot, so step back with left. Loops until the deadline so stale reviews +/// from earlier failed runs are approved too. fn spawn_approval_driver() { std::thread::spawn(|| { let deadline = std::time::Instant::now() + std::time::Duration::from_secs(120); while std::time::Instant::now() < deadline { let text = screen_text(); - if text.contains("Confirm") { + if text.contains("Reject transaction") { + eprintln!("driver: left (screen: {text:?})"); + ui_post("/button/left", r#"{"action": "press-and-release"}"#); + } else if text.contains("Sign transaction") + || text.contains("Confirm") + || text.contains("verified") + { eprintln!("driver: both (screen: {text:?})"); press_both(); } else { @@ -261,3 +269,244 @@ pub async fn ledger_app_version() -> LedgerResult<()> { println!("app version response: {}", hex::encode(&res.data)); Ok(()) } + +/// Sign an ironwood-to-ironwood v6 transaction with the Official Ledger PCZT +/// protocol against the emulator. The transaction is planned locally from the +/// emulator seed (one ironwood note spend, one recipient output, one hidden +/// internal change note), so the device must derive the same ask and produce +/// spend authorization signatures that verify against zkool's own v6 digest — +/// which is exactly what the PCZT signer checks when they are applied. +/// Needs the emulator up, seeded with EMULATOR_SEED: +/// `cargo test --features zemu -- --ignored --nocapture ledger_official_sign` +#[tokio::test] +#[ignore] +pub async fn ledger_official_sign() -> LedgerResult<()> { + use std::str::FromStr as _; + + use orchard::{ + note::AssetBase, + tree::MerkleHashOrchard, + }; + use pczt::roles::{creator::Creator, io_finalizer::IoFinalizer}; + use rand_core::OsRng; + use sqlx::Connection as _; + use zcash_keys::{ + encoding::AddressCodec as _, + keys::UnifiedSpendingKey, + }; + use zcash_primitives::transaction::{ + builder::{BuildConfig, Builder, BundlePadding}, + fees::zip317::FeeRule, + }; + use zcash_protocol::{ + consensus::{BlockHeight, BranchId}, + memo::MemoBytes, + value::Zatoshis, + }; + use zip32::AccountId; + + const EMULATOR_SEED: &str = "display accident enable raw glimpse engine know fog bubble price bunker minimum entry tuna joy motor rate tennis evolve october verb jelly indoor dance"; + + let network = Network::Main; + let ledger = LEDGER_ZEMU.lock().await.clone().unwrap(); + + // ── keys from the emulator seed ─────────────────────────────────────── + let mnemonic = bip39::Mnemonic::from_str(EMULATOR_SEED) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("bad seed: {e}")))?; + let seed = mnemonic.to_seed(""); + let usk = UnifiedSpendingKey::from_seed(&network, &seed, AccountId::try_from(0).unwrap()) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("usk derivation failed: {e}")))?; + let tsk = usk.transparent(); + let tvk = tsk.to_account_pubkey(); + let (tpk, taddr) = crate::account::derive_transparent_address(&tvk, 0, 0, false) + .map_err(|e| LedgerError::Anyhow(e))?; + let address_string = taddr.encode(&network); + + // ── plan an ironwood-to-ironwood v6 tx (spend → recipient + change) ─── + let height = BlockHeight::from_u32(3_500_000); + assert_eq!( + BranchId::for_height(&network, height), + BranchId::Nu6_3, + "test height must be past NU6.3" + ); + + // Synthetic ironwood note owned by the account (external scope), with a + // witness at position 0 of an otherwise-empty tree: the siblings are the + // empty subtrees of each height. + use incrementalmerkletree::Hashable as _; + let fvk = orchard::keys::FullViewingKey::from(usk.orchard()); + let spend_recipient = fvk.address_at(zip32::DiversifierIndex::from(0u32), orchard::keys::Scope::External); + let change_recipient = fvk.address_at(zip32::DiversifierIndex::from(0u32), orchard::keys::Scope::Internal); + let rho = orchard::note::Rho::from_bytes(&[9u8; 32]) + .into_option() + .ok_or_else(|| LedgerError::Protocol("bad rho".into()))?; + let rseed = orchard::note::RandomSeed::from_bytes([7u8; 32], &rho) + .into_option() + .ok_or_else(|| LedgerError::Protocol("bad rseed".into()))?; + let note = orchard::note::Note::from_parts( + spend_recipient, + orchard::value::NoteValue::from_raw(100_000), + AssetBase::zatoshi(), + rho, + rseed, + orchard::note::NoteVersion::V3, + ) + .into_option() + .ok_or_else(|| LedgerError::Protocol("bad note".into()))?; + let cmx = orchard::note::ExtractedNoteCommitment::from(note.commitment()); + let mut auth_path = [MerkleHashOrchard::empty_leaf(); 32]; + let mut state = MerkleHashOrchard::empty_leaf(); + for (l, sibling) in auth_path.iter_mut().enumerate() { + *sibling = state; + state = MerkleHashOrchard::combine( + incrementalmerkletree::Level::from(l as u8), + &state, + &state, + ); + } + let merkle_path = orchard::tree::MerklePath::from_parts(0, auth_path); + let anchor = merkle_path.root(cmx); + + let config = BuildConfig::Standard { + sapling_anchor: None, + orchard_anchor: None, + ironwood_anchor: Some(anchor), + orchard_padding: BundlePadding::DEFAULT, + ironwood_padding: BundlePadding::DEFAULT, + }; + let mut builder = Builder::new(&network, height, config); + builder + .add_ironwood_spend::<std::convert::Infallible>(fvk.clone(), note, merkle_path) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("add spend: {e:?}")))?; + builder + .add_ironwood_output::<std::convert::Infallible>( + Some(fvk.to_ovk(orchard::keys::Scope::External)), + spend_recipient, + Zatoshis::const_from_u64(40_000), + MemoBytes::empty(), + ) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("add output: {e:?}")))?; + builder + .add_ironwood_output::<std::convert::Infallible>( + Some(fvk.to_ovk(orchard::keys::Scope::External)), + change_recipient, + Zatoshis::const_from_u64(50_000), + MemoBytes::empty(), + ) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("add change: {e:?}")))?; + + let r = builder + .build_for_pczt(OsRng, &FeeRule::standard(), |_: &AssetBase| false) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("build_for_pczt: {e:?}")))?; + let pczt = Creator::build_from_parts(r.pczt_parts) + .ok_or_else(|| LedgerError::Protocol("creator returned no pczt".into()))?; + + let (pczt, _) = IoFinalizer::new(pczt) + .finalize_io() + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("io finalizer: {e:?}")))?; + + let ironwood_index = r.ironwood_meta.spend_action_index(0).unwrap(); + let package = crate::api::pay::PcztPackage { + pczt: pczt + .serialize() + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("serialize: {e:?}")))?, + n_spends: [0, 0, 0, 1], + sapling_indices: vec![], + orchard_indices: vec![], + ironwood_indices: vec![ironwood_index], + can_sign: true, + can_broadcast: false, + price: None, + category: None, + is_issuance: false, + }; + + // ── sign on the emulator ────────────────────────────────────────────── + let mut db = std::env::temp_dir(); + db.push(format!("zkool_ol_sign_{}.db", std::process::id())); + let mut connection = sqlx::sqlite::SqliteConnection::connect_with( + &sqlx::sqlite::SqliteConnectOptions::new() + .filename(&db) + .create_if_missing(true), + ) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::create_schema(&mut connection) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + + // Seed the OL account directly in the DB instead of importing it from the + // device: after a GET_VK review the emulator wedges in its home menu and + // stops answering APDUs, so the device interaction must come last. + let account = crate::db::store_account_metadata( + &mut connection, + "ol-sign", + &None, + &None, + u32::from(height), + false, + false, + ) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::store_account_hw(&mut connection, account, HwKind::Official as u8, 0) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::init_account_transparent(&mut connection, account, u32::from(height)) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::store_account_transparent_vk(&mut connection, account, &tvk) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::store_account_transparent_addr( + &mut connection, + account, + 0, + 0, + None, + &tpk, + &address_string, + false, + ) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::init_account_orchard(&network, &mut connection, account, u32::from(height)) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::store_account_orchard_vk( + &mut connection, + account, + &orchard::keys::FullViewingKey::from(usk.orchard()), + ) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + crate::db::update_dindex(&mut connection, account, 0, true) + .await + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; + + // The device review runs on the last ironwood packet; the driver approves it. + spawn_approval_driver(); + + let signed = tokio::time::timeout( + std::time::Duration::from_secs(120), + crate::ledger::official_sign::sign_transaction( + &network, + &mut connection, + account, + &package, + None, + &ledger, + ), + ) + .await + .map_err(|_| LedgerError::Protocol("timeout signing on the device".into())) + .and_then(|r| r.map_err(LedgerError::Anyhow))?; + + // Reaching this point means the device-derived signature verified against + // zkool's ZIP-244 sighash for the declared derivation path. + let _signed = pczt::Pczt::parse(&signed.pczt) + .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("reparse: {e:?}")))?; + std::fs::remove_file(&db).ok(); + println!("official ledger signing OK"); + Ok(()) +} From cd79c02cfdde2407ddbd89b27495225aea6cf537 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 23:35:26 +0800 Subject: [PATCH 153/189] fix: force internal change for Official Ledger accounts The Ledger app requires an internal-scope BIP-44 path on the transparent change output to treat it as change; set use_internal at account creation (Rust side enforced) and lock the toggle in the new account page when Official is selected. --- lib/pages/new_account.dart | 21 +++++++++++++++++---- rust/src/account.rs | 13 +++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index 3aed8ba59..1746cdf83 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -238,7 +238,17 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { ), ), Gap(12), - if (!ledger && (isSeed || key.isEmpty)) + if (ledger && ledgerApp == 1 && key.isEmpty) + Tooltip( + message: + "Official Ledger accounts always use an internal address for the change", + child: SwitchListTile( + value: true, + onChanged: null, + title: const Text("Use Internal Change"), + ), + ) + else if (!ledger && (isSeed || key.isEmpty)) Tooltip( message: "Check if you want this account to use an internal address for the change like Zashi (ZIP 316)", child: FormBuilderSwitch( @@ -385,7 +395,10 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { final String? passphrase = formData?["passphrase"]; final String? aindex = formData?["aindex"]; final String? birth = formData?["birth"]; - final bool? useInternal = formData?["useInternal"]; + final bool useInternal = + (ledger && ledgerApp == 1 && key.isEmpty) + ? true + : formData?["useInternal"] ?? false; final int? pools = formData!["pools"]; final icon = iconBytes; @@ -417,7 +430,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { birth: bh, folder: "", pools: pools, - useInternal: useInternal ?? false, + useInternal: useInternal, internal: false, hw: hw, ), @@ -444,7 +457,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { name: name ?? "", seed: seed.mnemonic, aindex: int.parse(aindex ?? "0"), - useInternal: useInternal ?? false, + useInternal: useInternal, birthHeight: bh, ); } diff --git a/rust/src/account.rs b/rust/src/account.rs index 4096fa303..4f03bab94 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -78,19 +78,28 @@ pub async fn new_account( .into() }); + let ledger_kind = HwKind::from_hw(na.hw); + // Official Ledger accounts always use an internal change address, so the + // transparent change output can carry the derivation path the Ledger app + // requires to verify it as change. + let use_internal = if ledger_kind == HwKind::Official { + true + } else { + na.use_internal + }; + let account = store_account_metadata( &mut db_tx, &na.name, &na.icon, &na.fingerprint, birth, - na.use_internal, + use_internal, na.internal, ) .await?; let mut key = na.key.clone(); - let ledger_kind = HwKind::from_hw(na.hw); if key.is_empty() && !ledger_kind.is_ledger() { key = generate_seed()?; } From 1e03b2f328f6eacce4c83626412a1a00c6b981dc Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 23:35:26 +0800 Subject: [PATCH 154/189] fix: derive shielded output addresses in the transaction plan TxPlan read the PCZT user_address field, which zkool never sets, so orchard/sapling/ironwood outputs showed no address. Fall back to encoding the raw recipient from the PCZT output itself. --- rust/src/pay/mod.rs | 67 +++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/rust/src/pay/mod.rs b/rust/src/pay/mod.rs index b6e5d4d0f..d1cf4ca92 100644 --- a/rust/src/pay/mod.rs +++ b/rust/src/pay/mod.rs @@ -10,7 +10,10 @@ use pool::PoolMask; use serde::{Deserialize, Serialize}; use sqlx::SqliteConnection; use tracing::{info, span, Level}; -use zcash_keys::encoding::AddressCodec as _; +use zcash_keys::{ + address::UnifiedAddress, + encoding::AddressCodec as _, +}; use zcash_note_encryption::Domain; use zcash_primitives::transaction::{OrchardBundle, Transaction}; use zcash_protocol::consensus::BranchId; @@ -143,7 +146,24 @@ fn orchard_asset_name(proprietary: &BTreeMap<String, Vec<u8>>, asset: Option<Ass }) } +/// The user-facing address of a shielded PCZT output: the user address set by +/// the planner when present, otherwise the raw recipient encoded on its own +/// (an orchard-only unified address, or the sapling payment address). +fn shielded_output_address( + network: &Network, + user_address: Option<&String>, + recipient: Option<UnifiedAddress>, +) -> Result<String> { + if let Some(address) = user_address.filter(|address| !address.is_empty()) { + return Ok(address.clone()); + } + recipient + .map(|address| address.encode(network)) + .ok_or_else(|| anyhow::anyhow!("shielded PCZT output has no recipient")) +} + fn append_orchard_plan<D: Domain>( + network: &Network, bundle: &orchard::pczt::Bundle<D>, inputs: &mut Vec<TxPlanIn>, outputs: &mut Vec<TxPlanOut>, @@ -172,12 +192,17 @@ fn append_orchard_plan<D: Domain>( .value() .ok_or_else(|| anyhow::anyhow!("Orchard PCZT output is missing its value"))? .inner(), - address: action - .output() - .user_address() - .as_ref() - .cloned() - .unwrap_or_default(), + address: shielded_output_address( + network, + action.output().user_address().as_ref(), + action + .output() + .recipient() + .as_ref() + .and_then(|recipient| { + UnifiedAddress::from_receivers(Some(*recipient), None, None) + }), + )?, asset_name: output_asset_name, }); } @@ -240,7 +265,13 @@ impl TxPlan { outputs.push(TxPlanOut { pool: 1, amount: o.value().unwrap().inner(), - address: o.user_address().as_ref().cloned().unwrap_or_default(), + address: match o.user_address().as_ref() { + Some(address) if !address.is_empty() => address.clone(), + _ => o + .recipient() + .map(|recipient| recipient.encode(network)) + .unwrap_or_default(), + }, asset_name: "ZEC".to_string(), }); } @@ -251,12 +282,12 @@ impl TxPlan { let verifier = if is_zsa { verifier.with_orchard_zsa(|bundle| { - append_orchard_plan(bundle, &mut inputs, &mut outputs, &mut fee) + append_orchard_plan(network, bundle, &mut inputs, &mut outputs, &mut fee) .map_err(pczt::roles::verifier::OrchardError::Custom) }) } else { verifier.with_orchard(|bundle| { - append_orchard_plan(bundle, &mut inputs, &mut outputs, &mut fee) + append_orchard_plan(network, bundle, &mut inputs, &mut outputs, &mut fee) .map_err(pczt::roles::verifier::OrchardError::Custom) }) } @@ -274,18 +305,20 @@ impl TxPlan { outputs.push(TxPlanOut { pool: 3, amount: a.output().value().expect("value").inner(), - address: a - .output() - .user_address() - .as_ref() - .cloned() - .unwrap_or_default(), + address: shielded_output_address( + network, + a.output().user_address().as_ref(), + a.output().recipient().as_ref().and_then(|recipient| { + UnifiedAddress::from_receivers(Some(*recipient), None, None) + }), + ) + .map_err(pczt::roles::verifier::OrchardError::Custom)?, asset_name: "ZEC".to_string(), }); } let f: i64 = (*bundle.value_sum()).try_into().unwrap(); fee += f; - Ok::<_, pczt::roles::verifier::OrchardError<()>>(()) + Ok::<_, pczt::roles::verifier::OrchardError<anyhow::Error>>(()) }) .unwrap(); From 599c223e84b8100b38576e99cf52d687c0853e5f Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Fri, 4 Sep 2026 23:35:26 +0800 Subject: [PATCH 155/189] fix: make app error messages selectable --- lib/widgets/error_display.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/widgets/error_display.dart b/lib/widgets/error_display.dart index 0b958d839..dea246ef3 100644 --- a/lib/widgets/error_display.dart +++ b/lib/widgets/error_display.dart @@ -116,13 +116,13 @@ class _ErrorDisplayState extends State<ErrorDisplay> { ), ), const Gap(4), - Text( + SelectableText( _errorMessage, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onErrorContainer, ), maxLines: _isExpanded ? null : 2, - overflow: _isExpanded ? null : TextOverflow.ellipsis, + textAlign: TextAlign.center, ), ], ), @@ -289,7 +289,7 @@ class ErrorDialog extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( + child: SelectableText( errorMessage, style: textTheme.bodyMedium?.copyWith( color: colorScheme.onSurface, @@ -333,7 +333,7 @@ class ErrorDialog extends StatelessWidget { onTap: () { Clipboard.setData(ClipboardData( text: '$error\n\n$stackTrace', - )); + ),); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Error details copied to clipboard'), From f37e1b62a8641220d6798290071703743fe50298 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 00:14:37 +0800 Subject: [PATCH 156/189] fix: lock Use Internal Change per Ledger app and avoid empty pools selection --- lib/pages/new_account.dart | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index 1746cdf83..3b1c57ba8 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -238,17 +238,19 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { ), ), Gap(12), - if (ledger && ledgerApp == 1 && key.isEmpty) + if (ledger) Tooltip( - message: - "Official Ledger accounts always use an internal address for the change", + message: ledgerApp == 1 + ? "Official Ledger accounts always use an internal address for the change" + : "Zondax Ledger accounts never use an internal address for the change", child: SwitchListTile( - value: true, + value: ledgerApp == 1, onChanged: null, + contentPadding: EdgeInsets.zero, title: const Text("Use Internal Change"), ), ) - else if (!ledger && (isSeed || key.isEmpty)) + else if (isSeed || key.isEmpty) Tooltip( message: "Check if you want this account to use an internal address for the change like Zashi (ZIP 316)", child: FormBuilderSwitch( @@ -320,7 +322,10 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { setState(() { ledger = v ?? false; }); - formKey.currentState?.fields["pools"]?.didChange(getPools()); + final pools = getPools(); + if (pools != 0) { + formKey.currentState?.fields["pools"]?.didChange(pools); + } }, ), if (ledger) ...[ @@ -395,10 +400,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { final String? passphrase = formData?["passphrase"]; final String? aindex = formData?["aindex"]; final String? birth = formData?["birth"]; - final bool useInternal = - (ledger && ledgerApp == 1 && key.isEmpty) - ? true - : formData?["useInternal"] ?? false; + final bool useInternal = ledger ? ledgerApp == 1 : formData?["useInternal"] ?? false; final int? pools = formData!["pools"]; final icon = iconBytes; From f7922853aeec099a4331416ebfa7e37401e07aee Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 12:02:04 +0800 Subject: [PATCH 157/189] feat: create Ledger accounts and sign via zkool_graphql Accept an optional hw field in the createAccount input and route signTx and pay through the Ledger device for hw accounts. The ledger signing code no longer depends on FRB: sinks are generic over crate::Sink, the signed package is returned instead of streamed, and the graphql server builds without the flutter feature. --- rust/src/api/account.rs | 72 +++++++++++++++++-- rust/src/api/init.rs | 1 - rust/src/api/migrate.rs | 17 +++-- rust/src/api/pay.rs | 3 +- rust/src/api/vault.rs | 6 ++ rust/src/api/voting.rs | 13 +++- rust/src/graphql/mutation.rs | 11 ++- rust/src/graphql/query.rs | 8 ++- rust/src/ledger/builder.rs | 120 ++++++++++++++++--------------- rust/src/ledger/mock.rs | 10 +-- rust/src/ledger/mod.rs | 13 +--- rust/src/ledger/nano.rs | 19 +---- rust/src/ledger/official.rs | 23 +----- rust/src/ledger/official_sign.rs | 69 +++++++----------- rust/src/ledger/tests.rs | 2 +- rust/src/vault/mod.rs | 2 + 16 files changed, 202 insertions(+), 187 deletions(-) diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index 954414c84..c74675a5c 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -20,12 +20,15 @@ use zcash_protocol::consensus::Parameters as ZkParams; use zcash_transparent::address::TransparentAddress; use zip32::AccountId; -use crate::{api::pay::PcztPackage, frb_generated::StreamSink}; +use crate::api::pay::PcztPackage; +#[cfg(feature = "flutter")] +use crate::frb_generated::StreamSink; use crate::{ api::{coin::Coin, pay::SigningEvent}, db::{get_account_dindex, get_account_hw}, io::{decrypt, encrypt}, ledger::{HwKind, LedgerApp}, + Sink, }; #[cfg_attr(feature = "flutter", frb)] @@ -850,18 +853,78 @@ pub async fn show_ledger_transparent_address(c: &Coin) -> Result<String> { Ok(r) } +#[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] pub async fn sign_ledger_transaction( sink: StreamSink<SigningEvent>, package: PcztPackage, c: &Coin, ) -> Result<()> { - let mut connection = c.get_connection().await?; - let ledger = get_ledger(&mut connection, c.account).await?; - ledger.sign_pczt(sink, package, c).await?; + let c = c.clone(); + tokio::spawn(async move { + match sign_ledger_pczt(&sink, package, &c).await { + Ok(pkg) => sink.send(SigningEvent::Result(pkg)).await, + Err(e) => sink.send_error(e).await, + } + }); Ok(()) } +#[cfg(feature = "ledger")] +pub(crate) async fn sign_ledger_pczt<S>( + sink: &S, + package: PcztPackage, + c: &Coin, +) -> Result<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ + let mut connection = c.get_connection().await?; + let hw = get_account_hw(&mut connection, c.account).await?; + match HwKind::from_hw(hw) { + HwKind::Zondax => { + crate::ledger::builder::sign_ledger_transaction( + c.network(), + sink, + connection, + c.account, + package, + ) + .await + } + HwKind::Official => { + crate::ledger::official_sign::sign_official_transaction( + c.network(), + sink, + &mut connection, + c.account, + package, + ) + .await + } + HwKind::Software => anyhow::bail!("account is not a hardware wallet"), + } +} + +#[cfg(not(feature = "ledger"))] +pub(crate) async fn sign_ledger_pczt<S>( + sink: &S, + package: PcztPackage, + c: &Coin, +) -> Result<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ + let _ = (sink, package); + let mut connection = c.get_connection().await?; + let hw = get_account_hw(&mut connection, c.account).await?; + if HwKind::from_hw(hw).is_ledger() { + anyhow::bail!("this build has no Ledger support") + } else { + anyhow::bail!("account is not a hardware wallet") + } +} + #[derive(Default, Debug)] pub struct TxAccount { pub id: u32, @@ -953,5 +1016,6 @@ pub(crate) async fn get_ledger( }) } +#[cfg(feature = "flutter")] #[frb] pub fn dummy_export(_a: SigningEvent) {} diff --git a/rust/src/api/init.rs b/rust/src/api/init.rs index e555fe9d2..664cd2eba 100644 --- a/rust/src/api/init.rs +++ b/rust/src/api/init.rs @@ -23,7 +23,6 @@ use flutter_rust_bridge::frb; /// (after `default_layer` but before `frb_layer`). type FilterSub = Layered<BoxedLayer<Registry>, Registry>; -#[cfg(feature = "flutter")] static FILTER_HANDLE: OnceLock<reload::Handle<EnvFilter, FilterSub>> = OnceLock::new(); #[cfg(feature = "flutter")] diff --git a/rust/src/api/migrate.rs b/rust/src/api/migrate.rs index c8c1b59eb..e08a0e232 100644 --- a/rust/src/api/migrate.rs +++ b/rust/src/api/migrate.rs @@ -5,15 +5,14 @@ use tokio_util::sync::CancellationToken; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; -use crate::{ - api::coin::Coin, - frb_generated::StreamSink, - migrate::{ - plan::next_task, - state::MigrationState, - step::StepOutcome, - task::{MigrationTask, Pacing, TaskKind}, - }, +use crate::api::coin::Coin; +#[cfg(feature = "flutter")] +use crate::frb_generated::StreamSink; +use crate::migrate::{ + plan::next_task, + state::MigrationState, + step::StepOutcome, + task::{MigrationTask, Pacing, TaskKind}, }; /// Current migration status — streamed to Flutter by run_migration(). diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index f23f8a620..13a6a9ad0 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -94,6 +94,7 @@ pub async fn sign_transaction(pczt: &PcztPackage, c: &Coin) -> Result<PcztPackag } #[cfg_attr(feature = "flutter", frb)] +#[derive(Debug, Clone)] pub enum SigningEvent { Progress(String), Result(PcztPackage), @@ -105,7 +106,7 @@ pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { } #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] -#[derive(Encode, Decode)] +#[derive(Debug, Clone, Encode, Decode)] pub struct PcztPackage { pub pczt: Vec<u8>, pub n_spends: [usize; 4], diff --git a/rust/src/api/vault.rs b/rust/src/api/vault.rs index ddc7e1d19..1bb2e93cf 100644 --- a/rust/src/api/vault.rs +++ b/rust/src/api/vault.rs @@ -1,9 +1,13 @@ +#[cfg(feature = "flutter")] use anyhow::Result; +#[cfg(feature = "flutter")] use flutter_rust_bridge::{frb, DartFnFuture}; +#[cfg(feature = "flutter")] use crate::vault::{DartVaultIO, Vault}; +#[cfg(feature = "flutter")] #[frb] pub fn init_vault( append: impl Fn(Vec<u8>) -> DartFnFuture<Result<()>> + Send + Sync + 'static, @@ -13,9 +17,11 @@ pub fn init_vault( Ok(DartVault(vault)) } +#[cfg(feature = "flutter")] #[frb(opaque)] pub struct DartVault(Vault<DartVaultIO>); +#[cfg(feature = "flutter")] #[frb] impl DartVault { #[frb] diff --git a/rust/src/api/voting.rs b/rust/src/api/voting.rs index 463c46d6f..fcc1e328e 100644 --- a/rust/src/api/voting.rs +++ b/rust/src/api/voting.rs @@ -5,15 +5,17 @@ //! transitions follow the plan: prepare → setup → sign/prove/submit → confirm, //! then van witness → commit → payloads → record execution → confirm. +#[cfg(feature = "flutter")] use std::sync::Arc; use anyhow::{anyhow, Result}; use rand_core::{OsRng, RngCore}; use serde::{Deserialize, Serialize}; use zcash_voting::prelude::{ - BundlePolicy, DelegationProgress, DelegationProgressBridge, DraftVote, NoopProgressReporter, - ShareTimingPolicy, TxEvent, VoteCommitStageBridge, + BundlePolicy, DelegationProgress, NoopProgressReporter, ShareTimingPolicy, TxEvent, }; +#[cfg(feature = "flutter")] +use zcash_voting::prelude::{DelegationProgressBridge, DraftVote, VoteCommitStageBridge}; use zcash_voting::recovery::{ DelegationRecovery as ForkDelegationRecovery, RoundRecoverySnapshot as ForkRoundRecovery, ShareWorkflow as ForkShareWorkflow, VoteRecovery as ForkVoteRecovery, @@ -25,7 +27,10 @@ use zcash_voting::{Network as VotingNetwork, VotingRoundParams}; #[cfg(feature = "flutter")] use flutter_rust_bridge::frb; -use crate::{api::coin::Coin, frb_generated::StreamSink, voting}; +use crate::api::coin::Coin; +#[cfg(feature = "flutter")] +use crate::frb_generated::StreamSink; +use crate::voting; // --------------------------------------------------------------------------- // Mirror types @@ -580,6 +585,7 @@ pub async fn delegation_confirm( /// `pir_layout` is persisted on first use; pass `None` after a restart to /// resume with the saved layout. Returns the submission together with its /// vote-chain wire JSON body (ready for `votechain_submit_delegation`). +#[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] #[allow(clippy::too_many_arguments)] pub async fn delegation_build_submission( @@ -820,6 +826,7 @@ pub async fn voting_drafts_load(round_id: &str, c: &Coin) -> Result<Option<Strin /// Commits one bundle's votes with live stage events. Draft votes are /// JSON-serialized fork `DraftVote`s; the VAN witness is derived internally /// after syncing the vote tree. +#[cfg(feature = "flutter")] #[cfg_attr(feature = "flutter", frb)] pub async fn voting_commit_with_progress( sink: StreamSink<VotingVoteCommitStage>, diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index 4aaf89538..b8d0fa07b 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -29,6 +29,7 @@ pub struct NewAccount { pub birth: Option<i32>, pub pools: Option<i32>, pub use_internal: bool, + pub hw: Option<i32>, } #[derive(GraphQLInputObject)] @@ -90,7 +91,7 @@ impl Mutation { use_internal: new_account.use_internal, folder: String::new(), internal: false, - hw: 0, + hw: new_account.hw.unwrap_or(0) as u8, }; let id_account = crate::api::account::new_account(&na, &context.coin).await?; Ok(id_account as i32) @@ -189,8 +190,12 @@ impl Mutation { let mut client = coin.client().await?; let height = client.latest_height().await?; let network = coin.network(); - let signed_pczt = - sign_transaction(&mut connection, id_account as u32, &network, &pczt).await?; + let hw = crate::db::get_account_hw(&mut connection, id_account as u32).await?; + let signed_pczt = if crate::ledger::HwKind::from_hw(hw).is_ledger() { + crate::api::account::sign_ledger_pczt(&(), pczt, coin).await? + } else { + sign_transaction(&mut connection, id_account as u32, &network, &pczt).await? + }; let tx_bytes = extract_transaction(&signed_pczt).await?; let txid = crate::pay::send(&mut client, height, &tx_bytes).await?; Ok(txid) diff --git a/rust/src/graphql/query.rs b/rust/src/graphql/query.rs index 04de606b6..777671524 100644 --- a/rust/src/graphql/query.rs +++ b/rust/src/graphql/query.rs @@ -286,9 +286,13 @@ impl Query { let (pczt, _) = bincode::decode_from_slice::<PcztPackage, _>(&pczt, bincode::config::standard())?; let network = context.coin.network(); - let signed = + let hw = crate::db::get_account_hw(&mut connection, id_account as u32).await?; + let signed = if crate::ledger::HwKind::from_hw(hw).is_ledger() { + crate::api::account::sign_ledger_pczt(&(), pczt, &context.coin).await? + } else { crate::pay::plan::sign_transaction(&mut connection, id_account as u32, &network, &pczt) - .await?; + .await? + }; let tx_bin = crate::pay::plan::extract_transaction(&signed).await?; let tx = hex::encode(&tx_bin); Ok(tx) diff --git a/rust/src/ledger/builder.rs b/rust/src/ledger/builder.rs index e6071a0eb..9c7b1e8ce 100644 --- a/rust/src/ledger/builder.rs +++ b/rust/src/ledger/builder.rs @@ -1,6 +1,5 @@ use std::io::Write; -use anyhow::Result; use byteorder::{WriteBytesExt, LE}; use jubjub::Fr; use pczt::{ @@ -44,25 +43,25 @@ use crate::{ LedgerError, LedgerResult, }, pay::plan::get_sapling_prover, - tiu, IntoAnyhow, + tiu, IntoAnyhow, Sink, }; -#[cfg(feature = "flutter")] -use crate::{frb_generated::StreamSink, ledger::transport::Device}; +use crate::ledger::transport::Device; #[allow(clippy::too_many_arguments)] -#[cfg(feature = "flutter")] -pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( +pub async fn sign_transaction<D: Device + Sync, S, R: RngCore + CryptoRng>( network: &Network, connection: &mut SqliteConnection, account: u32, package: &PcztPackage, prover: &LocalTxProver, - sink: &StreamSink<SigningEvent>, + sink: &S, ledger: &D, mut rng: R, -) -> LedgerResult<()> { - let s = sink; +) -> LedgerResult<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ let run = async move { use crate::ledger::transport::APDUCommand; @@ -107,7 +106,7 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( // Signing a tx with the Ledger involves several steps // Step 1. Send a InitTx instruction with inputs/outputs - let _ = sink.add(SigningEvent::Progress("Init Tx".to_string())); + sink.send(SigningEvent::Progress("Init Tx".to_string())).await; data.write_u8(ctin as u8)?; data.write_u8(ctout as u8)?; data.write_u8(stin as u8)?; @@ -235,7 +234,9 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( // This will make the Ledger show "Please Review..." info!("Confirm Tx on Ledger"); - let _ = sink.add(SigningEvent::Progress("Confirm Tx on Ledger".to_string())); + sink + .send(SigningEvent::Progress("Confirm Tx on Ledger".to_string())) + .await; let init_tx = APDUCommand { cla: 0x85, ins: 0xA0, @@ -281,9 +282,11 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( data: vec![], }; for sp in pczt.sapling().spends().iter() { - let _ = sink.add(SigningEvent::Progress( - "Extracting spend randomness".to_string(), - )); + sink + .send(SigningEvent::Progress( + "Extracting spend randomness".to_string(), + )) + .await; let res = ledger.execute(xtract_sp.clone()).await?; assert_eq!(res.retcode, 0x9000); let data = &res.data; @@ -334,9 +337,11 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( for (out, memo) in pczt.sapling().outputs().iter().zip(memos.iter()) { let fvk = fvk.as_ref().expect("fvk present for Sapling outputs"); let ovk = fvk.ovk; - let _ = sink.add(SigningEvent::Progress( - "Extracting output randomness".to_string(), - )); + sink + .send(SigningEvent::Progress( + "Extracting output randomness".to_string(), + )) + .await; let res = ledger.execute(xtract_out.clone()).await?; assert_eq!(res.retcode, 0x9000); let data = &res.data; @@ -459,7 +464,7 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( }; info!("Adding proofs to PCZT"); - let _ = sink.add(SigningEvent::Progress("Computing ZKPs".to_string())); + sink.send(SigningEvent::Progress("Computing ZKPs".to_string())).await; let pczt = Prover::new(pczt) .create_sapling_proofs(prover, prover) .unwrap() @@ -570,9 +575,11 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( assert_eq!(sighashes.len(), 220); buffers.push(sighashes); - let _ = sink.add(SigningEvent::Progress( - "Checking Tx and Signing on Ledger".to_string(), - )); + sink + .send(SigningEvent::Progress( + "Checking Tx and Signing on Ledger".to_string(), + )) + .await; let check_sign = APDUCommand { cla: 0x85, ins: 0xA3, @@ -588,9 +595,11 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( // Starting from the transparent inputs let mut tsigs = vec![]; for _ in pczt.transparent().inputs() { - let _ = sink.add(SigningEvent::Progress( - "Getting transparent signature".to_string(), - )); + sink + .send(SigningEvent::Progress( + "Getting transparent signature".to_string(), + )) + .await; let get_tsig = APDUCommand { cla: 0x85, ins: 0xA5, @@ -608,9 +617,11 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( // And then the shielded spends let mut ssigs = vec![]; for _ in pczt.sapling().spends() { - let _ = sink.add(SigningEvent::Progress( - "Getting shielded signature".to_string(), - )); + sink + .send(SigningEvent::Progress( + "Getting shielded signature".to_string(), + )) + .await; let get_ssig = APDUCommand { cla: 0x85, ins: 0xA4, @@ -684,42 +695,33 @@ pub async fn sign_transaction<D: Device + Sync, R: RngCore + CryptoRng>( }; Ok(new_package) }; - match run.await { - Ok(new_package) => { - let _ = sink.add(SigningEvent::Result(new_package)); - } - Err(error) => { - let _ = s.add_error(anyhow::Error::new(error)); - } - } - Ok(()) + run.await } -#[cfg(feature = "flutter")] -pub async fn sign_ledger_transaction( +pub async fn sign_ledger_transaction<S>( network: Network, - sink: StreamSink<SigningEvent>, + sink: &S, mut connection: PoolConnection<Sqlite>, account: u32, package: PcztPackage, -) -> Result<()> { - tokio::spawn(async move { - use crate::ledger::transport::connect_ledger; - - let ledger = connect_ledger().await?; - let sapling_prover = get_sapling_prover().await?; - sign_transaction( - &network, - &mut connection, - account, - &package, - sapling_prover, - &sink, - &ledger, - OsRng, - ) - .await?; - Ok::<_, LedgerError>(()) - }); - Ok(()) +) -> anyhow::Result<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ + use crate::ledger::transport::connect_ledger; + + let ledger = connect_ledger().await?; + let sapling_prover = get_sapling_prover().await?; + let signed = sign_transaction( + &network, + &mut connection, + account, + &package, + sapling_prover, + sink, + &ledger, + OsRng, + ) + .await?; + Ok(signed) } diff --git a/rust/src/ledger/mock.rs b/rust/src/ledger/mock.rs index 524c1fa7d..87a05d68d 100644 --- a/rust/src/ledger/mock.rs +++ b/rust/src/ledger/mock.rs @@ -4,11 +4,7 @@ use tonic::async_trait; use zcash_transparent::address::TransparentAddress; use crate::{ - api::{ - coin::{Coin, Network}, - pay::{PcztPackage, SigningEvent}, - }, - frb_generated::StreamSink, + api::coin::Network, ledger::{HwKind, LedgerApp}, }; @@ -85,8 +81,4 @@ impl LedgerApp for StubLedger { ) -> Result<String> { anyhow::bail!("{}", self.error) } - - async fn sign_pczt(&self, _sink: StreamSink<SigningEvent>, _package: PcztPackage, _c: &Coin) -> Result<()> { - anyhow::bail!("{}", self.error) - } } diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index 1c63275c1..f1ef22876 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -5,9 +5,7 @@ use zcash_transparent::address::TransparentAddress; use tonic::async_trait; -use crate::api::coin::{Coin, Network}; -use crate::api::pay::{PcztPackage, SigningEvent}; -use crate::frb_generated::StreamSink; +use crate::api::coin::Network; pub mod error; pub type LedgerError = error::Error; @@ -107,13 +105,4 @@ pub trait LedgerApp: Send + Sync { ) -> Result<String> { anyhow::bail!("not supported by this Ledger app") } - - async fn sign_pczt( - &self, - _sink: StreamSink<SigningEvent>, - _package: PcztPackage, - _c: &Coin, - ) -> Result<()> { - anyhow::bail!("not supported by this Ledger app") - } } diff --git a/rust/src/ledger/nano.rs b/rust/src/ledger/nano.rs index 8aff78ef8..31c37a950 100644 --- a/rust/src/ledger/nano.rs +++ b/rust/src/ledger/nano.rs @@ -5,11 +5,7 @@ use tonic::async_trait; use zcash_transparent::address::TransparentAddress; use crate::{ - api::{ - coin::{Coin, Network}, - pay::{PcztPackage, SigningEvent}, - }, - frb_generated::StreamSink, + api::coin::Network, ledger::{HwKind, LedgerApp}, }; @@ -81,17 +77,4 @@ impl LedgerApp for ZondaxApp { crate::ledger::fvk::show_transparent_address(network, connection, account).await?; Ok(address) } - - async fn sign_pczt(&self, sink: StreamSink<SigningEvent>, package: PcztPackage, c: &Coin) -> Result<()> { - let connection = c.get_connection().await?; - crate::ledger::builder::sign_ledger_transaction( - c.network(), - sink, - connection, - c.account, - package, - ) - .await?; - Ok(()) - } } diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs index 590ed8a5c..1d42cdb66 100644 --- a/rust/src/ledger/official.rs +++ b/rust/src/ledger/official.rs @@ -7,11 +7,7 @@ use zcash_keys::keys::UnifiedFullViewingKey; use zcash_protocol::consensus::NetworkConstants as _; use crate::{ - api::{ - coin::{Coin, Network}, - pay::{PcztPackage, SigningEvent}, - }, - frb_generated::StreamSink, + api::coin::Network, ledger::{ transport::{connect_ledger, APDUCommand, Device}, HwKind, LedgerApp, LedgerError, LedgerResult, @@ -116,21 +112,4 @@ impl LedgerApp for OfficialApp { let ledger = connect_ledger().await?; Ok(get_ufvk(&ledger, network, aindex).await?) } - - async fn sign_pczt( - &self, - sink: StreamSink<SigningEvent>, - package: PcztPackage, - c: &Coin, - ) -> Result<()> { - let connection = c.get_connection().await?; - crate::ledger::official_sign::sign_official_transaction( - c.network(), - sink, - connection, - c.account, - package, - )?; - Ok(()) - } } diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index 678a4f89f..36c789949 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -14,7 +14,7 @@ use ff::PrimeField as _; use orchard::pczt::Action; use orchard::primitives::redpallas; use pczt::roles::{prover::Prover, signer::Signer, spend_finalizer::SpendFinalizer}; -use sqlx::{pool::PoolConnection, Row, Sqlite, SqliteConnection}; +use sqlx::{Row, SqliteConnection}; use zcash_note_encryption::Domain; use zcash_protocol::consensus::NetworkConstants as _; @@ -25,12 +25,12 @@ use crate::{ pay::{PcztPackage, SigningEvent}, }, db::{get_account_aindex, get_account_dindex}, - frb_generated::StreamSink, ledger::{ transport::{APDUCommand, Device}, LedgerError, }, pay::plan::{get_orchard_pk, IRONWOOD_PK}, + Sink, }; const CLA: u8 = 0xE0; @@ -350,24 +350,27 @@ fn frame_shielded_bundle<D: Domain>( Ok((packets, displayed)) } -pub async fn sign_transaction<D: Device + Sync>( +pub async fn sign_transaction<D: Device + Sync, S>( network: &Network, connection: &mut SqliteConnection, account: u32, package: &PcztPackage, - sink: Option<&StreamSink<SigningEvent>>, + sink: Option<&S>, ledger: &D, -) -> Result<PcztPackage> { +) -> Result<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ use pczt::Pczt; use pczt::roles::updater::Updater; - let progress = |msg: String| { + let progress = |msg: String| async move { if let Some(sink) = sink { - let _ = sink.add(SigningEvent::Progress(msg)); + sink.send(SigningEvent::Progress(msg)).await; } }; - progress("Preparing transaction".to_string()); + progress("Preparing transaction".to_string()).await; if package.is_issuance { anyhow::bail!("ZSA issuance is not supported on Official Ledger accounts"); @@ -530,7 +533,7 @@ pub async fn sign_transaction<D: Device + Sync>( } // ── Send to the device ──────────────────────────────────────────────── - progress("Confirm on your Ledger".to_string()); + progress("Confirm on your Ledger".to_string()).await; let header = { let g = pczt.global(); @@ -556,7 +559,7 @@ pub async fn sign_transaction<D: Device + Sync>( send_command(ledger, INS_PCZT_IRONWOOD_ACTION, ironwood_packets, true).await?; // ── Collect signatures ──────────────────────────────────────────────── - progress("Signing on Ledger".to_string()); + progress("Signing on Ledger".to_string()).await; let ctin = pczt.transparent().inputs().len(); @@ -566,24 +569,24 @@ pub async fn sign_transaction<D: Device + Sync>( "Signing transparent input {}/{}", index + 1, ctin - )); + )).await; tsigs.push(sign_transparent_input(ledger, index as u32).await?); } let mut orchard_sigs = Vec::with_capacity(package.orchard_indices.len()); for index in &package.orchard_indices { - progress("Signing orchard spend".to_string()); + progress("Signing orchard spend".to_string()).await; orchard_sigs.push(sign_one(ledger, INS_PCZT_SIGN_ORCHARD, *index as u32).await?); } let mut ironwood_sigs = Vec::with_capacity(package.ironwood_indices.len()); for index in &package.ironwood_indices { - progress("Signing ironwood spend".to_string()); + progress("Signing ironwood spend".to_string()).await; ironwood_sigs.push(sign_one(ledger, INS_PCZT_SIGN_IRONWOOD, *index as u32).await?); } // ── Apply signatures, proofs, binding signature ─────────────────────── - progress("Finalizing transaction".to_string()); + progress("Finalizing transaction".to_string()).await; let mut signer = Signer::new(pczt).map_err(|error| anyhow!("signer: {error:?}"))?; for (index, sig) in tsigs.iter().enumerate() { @@ -646,36 +649,16 @@ pub async fn sign_transaction<D: Device + Sync>( }) } -pub fn sign_official_transaction( +pub async fn sign_official_transaction<S>( network: Network, - sink: StreamSink<SigningEvent>, - mut connection: PoolConnection<Sqlite>, + sink: &S, + connection: &mut SqliteConnection, account: u32, package: PcztPackage, -) -> Result<()> { - tokio::spawn(async move { - let run = async { - let ledger = crate::ledger::transport::connect_ledger().await?; - sign_transaction( - &network, - &mut connection, - account, - &package, - Some(&sink), - &ledger, - ) - .await - } - .await; - match run { - Ok(new_package) => { - let _ = sink.add(SigningEvent::Result(new_package)); - } - Err(error) => { - let _ = sink.add_error(error); - } - } - Ok::<_, anyhow::Error>(()) - }); - Ok(()) +) -> Result<PcztPackage> +where + S: Sink<SigningEvent> + Sync, +{ + let ledger = crate::ledger::transport::connect_ledger().await?; + sign_transaction(&network, connection, account, &package, Some(sink), &ledger).await } diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index ac198684a..99beeec09 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -494,7 +494,7 @@ pub async fn ledger_official_sign() -> LedgerResult<()> { &mut connection, account, &package, - None, + None::<&()>, &ledger, ), ) diff --git a/rust/src/vault/mod.rs b/rust/src/vault/mod.rs index c6f959794..d2a1e5381 100644 --- a/rust/src/vault/mod.rs +++ b/rust/src/vault/mod.rs @@ -2,6 +2,7 @@ use anyhow::Result; // #[cfg(flutter)] pub mod crypto; +#[cfg(feature = "flutter")] mod dart; #[async_trait] @@ -85,5 +86,6 @@ impl<IO: VaultIO> Vault<IO> { } } +#[cfg(feature = "flutter")] pub use dart::DartVaultIO; use tonic::async_trait; From 883dd62dec2a444fc24eaa29967e780df66d70bd Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 12:02:05 +0800 Subject: [PATCH 158/189] ci: run the Official Ledger emulator tests Exercise official signing, UFVK export, and account import against speculos in the manual test-ledger workflow, in that order since the GET_VK review wedges the emulator. --- .github/workflows/test-ledger.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-ledger.yml b/.github/workflows/test-ledger.yml index e0e678dd7..3dc735d47 100644 --- a/.github/workflows/test-ledger.yml +++ b/.github/workflows/test-ledger.yml @@ -6,6 +6,8 @@ on: jobs: emulator: runs-on: ubuntu-latest + env: + SEED: ${{ secrets.SEED }} steps: - name: Install RUST uses: dtolnay/rust-toolchain@stable @@ -20,8 +22,6 @@ jobs: with: workspaces: rust - name: Setup emulator - env: - SEED: ${{ secrets.SEED }} run: | misc/ledger/setup.sh misc/ledger/build.sh @@ -32,7 +32,12 @@ jobs: -H 'Content-Type: application/json' -d '{"apduHex": "e0c4000000"}') echo "$response" echo "$response" | grep -qE '"data": "3830[0-9a-f]*9000", "error": null' + # Signing runs before the GET_VK tests: its review wedges the emulator + # (see ledger/tests.rs), so the device interaction must come last. - name: Run ledger tests run: | cd rust cargo test --features zemu -- --ignored --nocapture ledger_app_version + cargo test --features zemu -- --ignored --nocapture ledger_official_sign + cargo test --features zemu -- --ignored --nocapture ledger_get_ufvk + cargo test --features zemu -- --ignored --nocapture ledger_account_import From 6e757f85580c5ae24371aab137604b7ecd7b726d Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 12:34:09 +0800 Subject: [PATCH 159/189] fix: pass the account id explicitly when signing on the server sign_ledger_pczt took the account from Coin.account, which the graphql server leaves unset, so every hw signTx failed with RowNotFound. --- rust/src/api/account.rs | 13 ++++++++----- rust/src/graphql/mutation.rs | 2 +- rust/src/graphql/query.rs | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index c74675a5c..57c464fdf 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -861,8 +861,9 @@ pub async fn sign_ledger_transaction( c: &Coin, ) -> Result<()> { let c = c.clone(); + let account = c.account; tokio::spawn(async move { - match sign_ledger_pczt(&sink, package, &c).await { + match sign_ledger_pczt(&sink, package, account, &c).await { Ok(pkg) => sink.send(SigningEvent::Result(pkg)).await, Err(e) => sink.send_error(e).await, } @@ -874,20 +875,21 @@ pub async fn sign_ledger_transaction( pub(crate) async fn sign_ledger_pczt<S>( sink: &S, package: PcztPackage, + account: u32, c: &Coin, ) -> Result<PcztPackage> where S: Sink<SigningEvent> + Sync, { let mut connection = c.get_connection().await?; - let hw = get_account_hw(&mut connection, c.account).await?; + let hw = get_account_hw(&mut connection, account).await?; match HwKind::from_hw(hw) { HwKind::Zondax => { crate::ledger::builder::sign_ledger_transaction( c.network(), sink, connection, - c.account, + account, package, ) .await @@ -897,7 +899,7 @@ where c.network(), sink, &mut connection, - c.account, + account, package, ) .await @@ -910,6 +912,7 @@ where pub(crate) async fn sign_ledger_pczt<S>( sink: &S, package: PcztPackage, + account: u32, c: &Coin, ) -> Result<PcztPackage> where @@ -917,7 +920,7 @@ where { let _ = (sink, package); let mut connection = c.get_connection().await?; - let hw = get_account_hw(&mut connection, c.account).await?; + let hw = get_account_hw(&mut connection, account).await?; if HwKind::from_hw(hw).is_ledger() { anyhow::bail!("this build has no Ledger support") } else { diff --git a/rust/src/graphql/mutation.rs b/rust/src/graphql/mutation.rs index b8d0fa07b..64fcf67b7 100644 --- a/rust/src/graphql/mutation.rs +++ b/rust/src/graphql/mutation.rs @@ -192,7 +192,7 @@ impl Mutation { let network = coin.network(); let hw = crate::db::get_account_hw(&mut connection, id_account as u32).await?; let signed_pczt = if crate::ledger::HwKind::from_hw(hw).is_ledger() { - crate::api::account::sign_ledger_pczt(&(), pczt, coin).await? + crate::api::account::sign_ledger_pczt(&(), pczt, id_account as u32, coin).await? } else { sign_transaction(&mut connection, id_account as u32, &network, &pczt).await? }; diff --git a/rust/src/graphql/query.rs b/rust/src/graphql/query.rs index 777671524..870eb4127 100644 --- a/rust/src/graphql/query.rs +++ b/rust/src/graphql/query.rs @@ -288,7 +288,8 @@ impl Query { let network = context.coin.network(); let hw = crate::db::get_account_hw(&mut connection, id_account as u32).await?; let signed = if crate::ledger::HwKind::from_hw(hw).is_ledger() { - crate::api::account::sign_ledger_pczt(&(), pczt, &context.coin).await? + crate::api::account::sign_ledger_pczt(&(), pczt, id_account as u32, &context.coin) + .await? } else { crate::pay::plan::sign_transaction(&mut connection, id_account as u32, &network, &pczt) .await? From eb3d89d502a61422441c17b5c117a9d3ce2b9720 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 12:46:13 +0800 Subject: [PATCH 160/189] fix: tag the transparent change output with its derivation The Official app hides a transparent output as change only when it carries a bip32 derivation: an internal-scope path whose on-device derivation matches the declared pubkey. Identify the change output by script against the account's internal addresses and frame the path, otherwise the change is displayed as an external recipient. --- rust/src/ledger/official_sign.rs | 55 ++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index 36c789949..bc443944b 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -15,8 +15,11 @@ use orchard::pczt::Action; use orchard::primitives::redpallas; use pczt::roles::{prover::Prover, signer::Signer, spend_finalizer::SpendFinalizer}; use sqlx::{Row, SqliteConnection}; +use zcash_keys::encoding::AddressCodec as _; use zcash_note_encryption::Domain; use zcash_protocol::consensus::NetworkConstants as _; +use zcash_script::script::Evaluable as _; +use zcash_transparent::address::TransparentAddress; use crate::{ account::get_orchard_vk, @@ -391,15 +394,33 @@ where let dindex = get_account_dindex(connection, account).await?; // Compressed pubkeys by address, for the transparent input derivation packets. - let pks: HashMap<String, Vec<u8>> = sqlx::query( - "SELECT address, pk FROM transparent_address_accounts WHERE account = ?", + let taddrs: Vec<(String, Vec<u8>, u32, u32)> = sqlx::query( + "SELECT address, pk, scope, dindex FROM transparent_address_accounts WHERE account = ?", ) .bind(account) - .map(|row: sqlx::sqlite::SqliteRow| (row.get::<String, _>(0), row.get::<Vec<u8>, _>(1))) + .map(|row: sqlx::sqlite::SqliteRow| { + ( + row.get::<String, _>(0), + row.get::<Vec<u8>, _>(1), + row.get::<u32, _>(2), + row.get::<u32, _>(3), + ) + }) .fetch_all(&mut *connection) - .await? - .into_iter() - .collect(); + .await?; + + let pks: HashMap<String, Vec<u8>> = taddrs + .iter() + .map(|(address, pk, _, _)| (address.clone(), pk.clone())) + .collect(); + let mut change_scripts: HashMap<Vec<u8>, (Vec<u8>, u32)> = HashMap::new(); + for (address, pk, scope, dindex) in &taddrs { + if *scope == 1 { + if let Ok(taddr) = TransparentAddress::decode(network, address) { + change_scripts.insert(taddr.script().to_bytes(), (pk.clone(), *dindex)); + } + } + } // The internal change address is hidden from the device review; every other // positive shielded output counts against the device display budget. @@ -493,10 +514,24 @@ where script_packet.write_all(script)?; output_packets.push(script_packet); - // No derivation on transparent outputs: they are displayed rather - // than hidden as change (the app requires an internal-scope path - // whose on-device derivation matches the output key). - output_packets.push(vec![0x00]); + let mut derivation = vec![0x00]; + if let Some((pk, dindex)) = change_scripts.get(script) { + derivation.clear(); + write_compact_size(&mut derivation, 1)?; + derivation.write_all(pk)?; + derivation.write_all(&[0u8; 32])?; + write_bip32_path( + &mut derivation, + &[ + 44 | HARDENED, + coin_type | HARDENED, + aindex | HARDENED, + 1, + *dindex, + ], + )?; + } + output_packets.push(derivation); } } From 5ff1ec66e090d34822f8e2bb0a5cb6b375c48a9e Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 13:13:03 +0800 Subject: [PATCH 161/189] test: gate Ledger tests on the app home screen The driver pressed buttons until its deadline, so a stale driver from the previous test interfered with the next review and APDUs sent during the app's post-review recovery window were dropped. Each driver now waits for the review to start and retires once the app is home, and a test only completes after wait_until_ready, so no restarts are needed between tests. --- .github/workflows/test-ledger.yml | 4 +-- rust/src/ledger/tests.rs | 47 ++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-ledger.yml b/.github/workflows/test-ledger.yml index 3dc735d47..29ec09ac8 100644 --- a/.github/workflows/test-ledger.yml +++ b/.github/workflows/test-ledger.yml @@ -32,8 +32,8 @@ jobs: -H 'Content-Type: application/json' -d '{"apduHex": "e0c4000000"}') echo "$response" echo "$response" | grep -qE '"data": "3830[0-9a-f]*9000", "error": null' - # Signing runs before the GET_VK tests: its review wedges the emulator - # (see ledger/tests.rs), so the device interaction must come last. + # Each test returns only once the app is back on its home screen, so + # the emulator needs no restart between them. - name: Run ledger tests run: | cd rust diff --git a/rust/src/ledger/tests.rs b/rust/src/ledger/tests.rs index 99beeec09..6a9eeb7b9 100644 --- a/rust/src/ledger/tests.rs +++ b/rust/src/ledger/tests.rs @@ -69,16 +69,40 @@ fn screen_text() -> String { .unwrap_or_default() } +/// Block until the app is back on its home screen. A device operation is not +/// really finished when the host gets its answer: the app needs a moment to +/// return to ready, and APDUs sent in that window are dropped. +fn wait_until_ready(timeout: std::time::Duration) -> bool { + let deadline = std::time::Instant::now() + timeout; + while std::time::Instant::now() < deadline { + if screen_text().to_lowercase().contains("app is ready") { + return true; + } + std::thread::sleep(std::time::Duration::from_millis(200)); + } + false +} + /// Drive the NBGL review: advance pages with the right button. The post-review /// "Address verified" status and the "Sign transaction" approval page need a /// both-button press; "Reject transaction" means the approval page was -/// overshot, so step back with left. Loops until the deadline so stale reviews -/// from earlier failed runs are approved too. +/// overshot, so step back with left. The driver waits for the review to start, +/// and retires as soon as the app is back on the home screen, so it never +/// outlives the interaction it was spawned for. fn spawn_approval_driver() { std::thread::spawn(|| { let deadline = std::time::Instant::now() + std::time::Duration::from_secs(120); + while std::time::Instant::now() < deadline { + if !screen_text().to_lowercase().contains("app is ready") { + break; + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } while std::time::Instant::now() < deadline { let text = screen_text(); + if text.to_lowercase().contains("app is ready") { + return; + } if text.contains("Reject transaction") { eprintln!("driver: left (screen: {text:?})"); ui_post("/button/left", r#"{"action": "press-and-release"}"#); @@ -146,6 +170,11 @@ pub async fn ledger_get_ufvk() -> LedgerResult<()> { println!("device : {ufvk}"); println!("expected : {expected}"); assert_eq!(ufvk, expected, "device UFVK does not match the seed-derived key"); + if !wait_until_ready(std::time::Duration::from_secs(30)) { + return Err(LedgerError::Protocol( + "device did not return to the home screen".into(), + )); + } Ok(()) } @@ -238,6 +267,11 @@ pub async fn ledger_account_import() -> LedgerResult<()> { println!("db ufvk : {ufvk}"); println!("expected : {expected}"); assert_eq!(ufvk, expected, "stored keys do not match the device UFVK"); + if !wait_until_ready(std::time::Duration::from_secs(30)) { + return Err(LedgerError::Protocol( + "device did not return to the home screen".into(), + )); + } std::fs::remove_file(&db).ok(); Ok(()) } @@ -436,8 +470,8 @@ pub async fn ledger_official_sign() -> LedgerResult<()> { .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("{e}")))?; // Seed the OL account directly in the DB instead of importing it from the - // device: after a GET_VK review the emulator wedges in its home menu and - // stops answering APDUs, so the device interaction must come last. + // device: the import flow is covered by ledger_account_import, and this + // test only needs the signing protocol against the emulator. let account = crate::db::store_account_metadata( &mut connection, "ol-sign", @@ -506,6 +540,11 @@ pub async fn ledger_official_sign() -> LedgerResult<()> { // zkool's ZIP-244 sighash for the declared derivation path. let _signed = pczt::Pczt::parse(&signed.pczt) .map_err(|e| LedgerError::Anyhow(anyhow::anyhow!("reparse: {e:?}")))?; + if !wait_until_ready(std::time::Duration::from_secs(30)) { + return Err(LedgerError::Protocol( + "device did not return to the home screen".into(), + )); + } std::fs::remove_file(&db).ok(); println!("official ledger signing OK"); Ok(()) From cc51e2ffb7c766b3d0172e65ef5acac14f3a87d6 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 16:04:11 +0800 Subject: [PATCH 162/189] fix: keep transparent change addresses paired with external addresses Materialize the internal (scope 1) change counterpart for every external transparent address on accounts that use internal change, and stop allocating a fresh internal index on every prepare (which drifted from the account dindex and left orphaned rows). - new_account and generate_next_dindex store the internal counterpart alongside the external address. - plan_transaction resolves transparent change to the stored change-scope address at the current dindex and errors when the pair is missing, instead of deriving a new address via generate_next_change_address. - transparent_sweep pairs a used external address with its internal twin for use_internal accounts, and a used internal address with its external twin. - Coin::open_database runs an idempotent backfill materializing missing internal counterparts for existing accounts. --- rust/src/account.rs | 157 +++++++++++++++++++++++++++++++++++++++++++ rust/src/api/coin.rs | 1 + rust/src/pay/plan.rs | 17 ++--- rust/src/sync.rs | 77 +++++++++++++++++++-- 4 files changed, 235 insertions(+), 17 deletions(-) diff --git a/rust/src/account.rs b/rust/src/account.rs index 4f03bab94..9ca221729 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -460,6 +460,18 @@ pub async fn new_account( } else { anyhow::bail!("Unsupported key"); } + + let external_indexes: Vec<u32> = sqlx::query( + "SELECT dindex FROM transparent_address_accounts WHERE account = ? AND scope = 0", + ) + .bind(account) + .map(|row: SqliteRow| row.get(0)) + .fetch_all(&mut *db_tx) + .await?; + for di in external_indexes { + ensure_internal_change_address(network, &mut *db_tx, account, di).await?; + } + db_tx.commit().await?; Ok(account) } @@ -888,6 +900,7 @@ pub async fn generate_next_dindex( false, ) .await?; + ensure_internal_change_address(network, &mut db_tx, account, dindex).await?; } db_tx.commit().await?; @@ -961,6 +974,150 @@ async fn get_transparent_keys( Ok((xsk, xvk)) } +/// The stored transparent address that receives a transaction's transparent +/// change: the account's change-scope address at the current dindex. Pairs are +/// materialized together when addresses are derived, so a missing row is a +/// pairing-invariant violation and is surfaced as an error rather than derived. +pub async fn transparent_change_address( + connection: &mut SqliteConnection, + account: u32, + use_internal: bool, + dindex: u32, +) -> Result<String> { + let scope: u32 = if use_internal { 1 } else { 0 }; + let kind = if use_internal { "change" } else { "external" }; + let address: Option<String> = sqlx::query( + "SELECT address FROM transparent_address_accounts + WHERE account = ?1 AND scope = ?2 AND dindex = ?3", + ) + .bind(account) + .bind(scope) + .bind(dindex) + .map(|row: SqliteRow| row.get(0)) + .fetch_optional(&mut *connection) + .await?; + address.ok_or_else(|| { + anyhow!( + "no stored {kind} transparent address at dindex {dindex} for account {account}; \ + generate a new address set or resync to materialize the change-address pair" + ) + }) +} + +/// Derive and store the transparent address at (scope, dindex) when missing. +async fn derive_and_store_transparent( + network: &Network, + connection: &mut SqliteConnection, + account: u32, + scope: u32, + dindex: u32, +) -> Result<bool> { + let exists: (i64,) = sqlx::query_as( + "SELECT COUNT(*) FROM transparent_address_accounts + WHERE account = ?1 AND scope = ?2 AND dindex = ?3", + ) + .bind(account) + .bind(scope) + .bind(dindex) + .fetch_one(&mut *connection) + .await?; + if exists.0 > 0 { + return Ok(false); + } + + let hw = get_account_hw(connection, account).await?; + let (xsk, xvk) = get_transparent_keys(connection, account).await?; + let (sk, pk, address) = match xvk { + Some(xvk) => { + let sk = match xsk.as_ref() { + Some(xsk) => Some(derive_transparent_sk(xsk, scope, dindex)?), + None => None, + }; + let (pk, address) = derive_transparent_address(&xvk, scope, dindex, false)?; + (sk, pk, address) + } + None if hw != 0 => { + let (aindex,): (u32,) = + sqlx::query_as("SELECT aindex FROM accounts WHERE id_account = ?") + .bind(account) + .fetch_one(&mut *connection) + .await?; + let ledger = get_ledger(connection, account).await?; + let (pk, address) = ledger + .get_transparent_pubkey(network, aindex, scope, dindex) + .await?; + (None, pk, address) + } + _ => { + anyhow::bail!( + "cannot derive transparent address scope {scope} at dindex {dindex} \ + for account {account}: no account key" + ) + } + }; + let encoded = address.encode(network); + store_account_transparent_addr(connection, account, scope, dindex, sk, &pk, &encoded, false) + .await +} + +/// Ensure the internal (scope 1) change counterpart of external index `dindex` +/// exists for accounts that use internal change. Returns whether a new row was +/// inserted. +pub async fn ensure_internal_change_address( + network: &Network, + connection: &mut SqliteConnection, + account: u32, + dindex: u32, +) -> Result<bool> { + let (use_internal,): (bool,) = + sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") + .bind(account) + .fetch_one(&mut *connection) + .await?; + if !use_internal { + return Ok(false); + } + derive_and_store_transparent(network, connection, account, 1, dindex).await +} + +/// Materialize the internal (change) counterpart of every stored external +/// transparent address for accounts that use internal change. Idempotent; run +/// at database open to reconcile databases that predate change-address pairing. +pub async fn backfill_transparent_change_addresses( + network: &Network, + connection: &mut SqliteConnection, +) -> Result<usize> { + let mut added = 0; + let accounts: Vec<u32> = sqlx::query( + "SELECT a.id_account FROM accounts a + WHERE a.use_internal = 1 AND EXISTS ( + SELECT 1 FROM transparent_address_accounts ta + WHERE ta.account = a.id_account AND ta.scope = 0)", + ) + .map(|row: SqliteRow| row.get(0)) + .fetch_all(&mut *connection) + .await?; + for account in accounts { + let (xsk, xvk) = get_transparent_keys(connection, account).await?; + if xvk.is_none() && xsk.is_none() { + continue; + } + let indexes: Vec<u32> = sqlx::query( + "SELECT dindex FROM transparent_address_accounts WHERE account = ? AND scope = 0", + ) + .bind(account) + .map(|row: SqliteRow| row.get(0)) + .fetch_all(&mut *connection) + .await?; + for dindex in indexes { + if derive_and_store_transparent(network, connection, account, 1, dindex).await? { + added += 1; + } + } + } + Ok(added) +} + pub async fn get_addresses( network: &Network, connection: &mut SqliteConnection, diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index c6a5192a5..9f0202afd 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -74,6 +74,7 @@ impl Coin { migrate_sapling_addresses(&network, &mut connection).await?; backfill_diversifier_index(&mut connection).await?; + crate::account::backfill_transparent_change_addresses(&network, &mut connection).await?; Ok(Coin { coin, diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index fcb17766e..8416af2d4 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -51,9 +51,9 @@ use zip321::{Payment, TransactionRequest}; use crate::{ account::{ - derive_transparent_sk, generate_next_change_address, get_account_full_address, - get_orchard_note, get_orchard_sk, get_orchard_vk, get_sapling_note, get_sapling_sk, - get_sapling_vk, + derive_transparent_sk, get_account_full_address, get_orchard_note, get_orchard_sk, + get_orchard_vk, get_sapling_note, get_sapling_sk, get_sapling_vk, + transparent_change_address, }, api::{coin::Network, issuance::IssuanceInfo, pay::PcztPackage}, db::{get_account_dindex, get_account_hw, select_account_transparent}, @@ -769,14 +769,9 @@ pub async fn plan_transaction( // ── Fetch change address ───────────────────────────────────────────── let change_scope = if use_internal { 1 } else { 0 }; - let mut change_address = + let change_address = get_account_full_address(network, connection, account, change_scope, hw).await?; let tkeys = select_account_transparent(connection, account, dindex).await?; - if change_pool == 0 && tkeys.xvk.is_some() { - change_address = generate_next_change_address(network, connection, account) - .await? - .unwrap(); - } // Fill in ZSA change output addresses for rs in &mut recipient_states { @@ -1052,9 +1047,7 @@ pub async fn plan_transaction( // ── Add change output ──────────────────────────────────────────────── if change > 0 { let change_addr = if change_pool == 0 && tkeys.xvk.is_some() { - generate_next_change_address(network, connection, account) - .await? - .unwrap() + transparent_change_address(connection, account, use_internal, dindex).await? } else { change_address.clone() }; diff --git a/rust/src/sync.rs b/rust/src/sync.rs index 828b3a16f..b857c279c 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -1276,6 +1276,11 @@ pub async fn transparent_sweep( let hw = get_account_hw(&mut connection, account).await?; let aindex = get_account_aindex(&mut connection, account).await?; let dindex = get_account_dindex(&mut connection, account).await?; + let (use_internal,): (bool,) = + sqlx::query_as("SELECT use_internal FROM accounts WHERE id_account = ?") + .bind(account) + .fetch_one(&mut *connection) + .await?; tokio::spawn(async move { let ledger = get_ledger(&mut connection, account).await?; let mut n_added = 0; @@ -1309,18 +1314,80 @@ pub async fn transparent_sweep( let mut txids = txids?; if txids.next().await.is_some() { let sk = if let Some(tsk) = tk.xsk.as_ref() { - let sk = derive_transparent_sk(tsk, scope, dindex)?; - Some(sk) + Some(derive_transparent_sk(tsk, scope, dindex)?) } else { None }; - if store_account_transparent_addr( + let added = store_account_transparent_addr( &mut connection, account, scope, dindex, sk, &pk, &taddr, false, ) - .await? - { + .await?; + if added { n_added += 1; } + + let want_counterpart = if scope == 0 { + use_internal + } else { + true + }; + if want_counterpart { + let counterpart_scope = 1 - scope; + let existing: (i64,) = sqlx::query_as( + "SELECT COUNT(*) FROM transparent_address_accounts + WHERE account = ?1 AND scope = ?2 AND dindex = ?3", + ) + .bind(account) + .bind(counterpart_scope) + .bind(dindex) + .fetch_one(&mut *connection) + .await?; + if existing.0 == 0 { + let (csk, cpk, ctaddr) = match xvk.as_ref() { + Some(xvk) => { + let sk = if let Some(tsk) = tk.xsk.as_ref() { + Some(derive_transparent_sk( + tsk, + counterpart_scope, + dindex, + )?) + } else { + None + }; + let (pk, address) = derive_transparent_address( + xvk, + counterpart_scope, + dindex, + false, + )?; + (sk, pk, address) + } + None if hw != 0 => { + let (pk, address) = ledger + .get_transparent_pubkey( + &network, + aindex, + counterpart_scope, + dindex, + ) + .await?; + (None, pk, address) + } + _ => anyhow::bail!("Sweep needs an xpub key"), + }; + store_account_transparent_addr( + &mut connection, + account, + counterpart_scope, + dindex, + csk, + &cpk, + &ctaddr.encode(&network), + false, + ) + .await?; + } + } } else { gap += 1; } From ad51493d61f8f42834bdb7f93474c748e70f930a Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 16:37:32 +0800 Subject: [PATCH 163/189] feat: gate the Nym transport behind a cargo feature Add a "nym" cargo feature (on by default) covering the mixnet transport and nym:// nym-rpc endpoints, making the nym crates optional dependencies. CI graphql builds now pass --no-default-features so the server no longer compiles the Nym stack or the Flutter bridge. --- .github/workflows/build-graphql.yml | 2 +- .github/workflows/migration.yml | 2 +- .github/workflows/wallet.yml | 2 +- rust/Cargo.toml | 14 +++++++---- rust/src/api/coin.rs | 38 +++++++++++++++++++++-------- rust/src/api/network.rs | 1 + rust/src/net/mod.rs | 2 ++ rust/src/net/zebra.rs | 3 +++ 8 files changed, 46 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-graphql.yml b/.github/workflows/build-graphql.yml index 75918d997..3d6fa58ec 100644 --- a/.github/workflows/build-graphql.yml +++ b/.github/workflows/build-graphql.yml @@ -25,7 +25,7 @@ jobs: sudo apt-get update sudo apt-get install -y pkg-config libudev-dev cd rust - cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params + cargo build --release --bin zkool_graphql --no-default-features --features=graphql,bundled-sapling-params - name: Create Release if: startsWith(github.ref_name, 'zkool-v') uses: softprops/action-gh-release@v3 diff --git a/.github/workflows/migration.yml b/.github/workflows/migration.yml index 891107ac7..5cabeebc8 100644 --- a/.github/workflows/migration.yml +++ b/.github/workflows/migration.yml @@ -49,7 +49,7 @@ jobs: sudo apt-get update sudo apt-get install -y pkg-config libudev-dev cd rust - cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params + cargo build --release --bin zkool_graphql --no-default-features --features=graphql,bundled-sapling-params # target/release first, so the chain is brought up with the binary built # from this PR rather than the released one cached in tools/bin. diff --git a/.github/workflows/wallet.yml b/.github/workflows/wallet.yml index ef3d89d5f..4024de7cf 100644 --- a/.github/workflows/wallet.yml +++ b/.github/workflows/wallet.yml @@ -29,7 +29,7 @@ jobs: sudo apt-get update sudo apt-get install -y pkg-config libudev-dev cd rust - cargo build --release --bin zkool_graphql --features=graphql,bundled-sapling-params + cargo build --release --bin zkool_graphql --no-default-features --features=graphql,bundled-sapling-params - name: Run pytest tests run: | cd tests diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5fde611c0..d70689173 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -47,12 +47,15 @@ tokio-util = "0.7" webpki-roots = "1.0.2" arti-client = {version = "0.31", features = ["tokio", "native-tls", "onion-service-client"]} -nym-smolmix = "=1.21.5-rc.3" -nym-sdk = "=1.21.5-rc.3" -nym-network-defaults = "=1.21.5-rc.3" +# Nym mixnet transport (feature = "nym"): nym-smolmix provides the TCP +# tunnel, nym-sdk the nym-rpc endpoint client, nym-network-defaults the +# network env. Only pulled in when the feature is enabled. +nym-smolmix = {version = "=1.21.5-rc.3", optional = true} +nym-sdk = {version = "=1.21.5-rc.3", optional = true} +nym-network-defaults = {version = "=1.21.5-rc.3", optional = true} # bincode 1.x for nym-rpc wire compatibility (ProxiedMessage framing); # the crate also uses bincode 2.x elsewhere, hence the rename. -bincode1 = {package = "bincode", version = "1.3"} +bincode1 = {package = "bincode", version = "1.3", optional = true} uuid = {version = "1", features = ["v4"]} httparse = "1.10.1" hyper-util = {version = "0.1", features = ["tokio"]} @@ -158,10 +161,11 @@ rand = "0.6" vote-commitment-tree = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "049504162f11a09c89d33414d35e747851891d04" } [features] -default = ["flutter"] +default = ["flutter", "nym"] flutter = ["flutter_rust_bridge"] bundled-sapling-params = ["zcash_proofs/bundled-prover"] graphql = ["juniper", "juniper_warp", "juniper_graphql_ws", "dataloader", "warp", "jsonwebtoken", "bigdecimal", "chrono", "figment", "clap"] ledger = ["hidapi", "ledger-transport"] +nym = ["dep:nym-smolmix", "dep:nym-sdk", "dep:nym-network-defaults", "dep:bincode1"] zemu = ["ledger", "ledger-transport-zemu"] flutter_rust_bridge = ["dep:flutter_rust_bridge"] diff --git a/rust/src/api/coin.rs b/rust/src/api/coin.rs index 9f0202afd..179a336d4 100644 --- a/rust/src/api/coin.rs +++ b/rust/src/api/coin.rs @@ -183,21 +183,35 @@ impl Coin { } /// True when traffic to the server goes through the Nym mixnet, either - /// via a mixnet-native nym:// endpoint or the Nym transport. + /// via a mixnet-native nym:// endpoint or the Nym transport. Always + /// false when this build has no `nym` feature. pub(crate) fn is_mixnet(&self) -> bool { - crate::net::nym_service::parse_nym_url(&self.url).is_some() || self.transport == 2 + cfg_if::cfg_if! { + if #[cfg(feature = "nym")] { + crate::net::nym_service::parse_nym_url(&self.url).is_some() || self.transport == 2 + } else { + false + } + } } pub(crate) async fn client(&self) -> Result<Client> { - // Mixnet-native endpoint (nym:// URL, a nym-rpc service): bypasses - // the transport enum entirely — the mixnet IS the transport. - if let Some(recipient) = crate::net::nym_service::parse_nym_url(&self.url) { - if self.server_type != 0 { - anyhow::bail!("Nym service addresses only support lightwalletd (gRPC) servers"); + #[cfg(feature = "nym")] + { + // Mixnet-native endpoint (nym:// URL, a nym-rpc service): bypasses + // the transport enum entirely — the mixnet IS the transport. + if let Some(recipient) = crate::net::nym_service::parse_nym_url(&self.url) { + if self.server_type != 0 { + anyhow::bail!("Nym service addresses only support lightwalletd (gRPC) servers"); + } + let channel = crate::net::nym_service::grpc_channel(recipient).await?; + let client = CompactTxStreamerClient::new(channel); + return Ok(Box::new(client) as Client); } - let channel = crate::net::nym_service::grpc_channel(recipient).await?; - let client = CompactTxStreamerClient::new(channel); - return Ok(Box::new(client) as Client); + } + #[cfg(not(feature = "nym"))] + if self.url.starts_with("nym://") { + anyhow::bail!("Nym mixnet support is not enabled in this build"); } match self.server_type { @@ -205,7 +219,10 @@ impl Coin { 0 => { let channel = match self.transport { 1 => connect_over_tor(&self.url).await?, + #[cfg(feature = "nym")] 2 => connect_over_nym(&self.url).await?, + #[cfg(not(feature = "nym"))] + 2 => anyhow::bail!("Nym transport is not enabled in this build"), 3 if !self.proxy.is_empty() => { connect_over_proxy(&self.url, &self.proxy).await? } @@ -327,6 +344,7 @@ async fn connect_over_tor(url: &str) -> anyhow::Result<Channel> { Ok(endpoint.connect_with_connector(connector).await?) } +#[cfg(feature = "nym")] async fn connect_over_nym(url: &str) -> anyhow::Result<Channel> { let uri = url.parse::<Uri>()?; diff --git a/rust/src/api/network.rs b/rust/src/api/network.rs index 95cda452c..4b195a2ed 100644 --- a/rust/src/api/network.rs +++ b/rust/src/api/network.rs @@ -109,6 +109,7 @@ pub async fn query_lwd_list(coin: u8) -> Result<Vec<LWDInfo>> { /// True when `url` is a mixnet-native server address /// (`nym://<identity>.<encryption>@<gateway>`). +#[cfg(feature = "nym")] #[cfg_attr(feature = "flutter", frb(sync))] pub fn is_valid_nym_url(url: String) -> bool { crate::net::nym_service::parse_nym_url(&url).is_some() diff --git a/rust/src/net/mod.rs b/rust/src/net/mod.rs index e9fddf0e0..3a7fcf59f 100644 --- a/rust/src/net/mod.rs +++ b/rust/src/net/mod.rs @@ -7,7 +7,9 @@ use tonic::async_trait; use crate::{api::coin::Network, lwd::*}; pub mod lwd; +#[cfg(feature = "nym")] pub mod nym; +#[cfg(feature = "nym")] pub mod nym_service; pub mod votechain; pub mod zebra; diff --git a/rust/src/net/zebra.rs b/rust/src/net/zebra.rs index 8ff5be2f2..3e3e77679 100644 --- a/rust/src/net/zebra.rs +++ b/rust/src/net/zebra.rs @@ -123,10 +123,13 @@ impl ZebraClient { drop(tor_client); self.post_stream(Box::pin(stream), req).await? } + #[cfg(feature = "nym")] 2 => { let stream = crate::net::nym::nym_connect(&self.host, self.port).await?; self.post_stream(Box::pin(stream), req).await? } + #[cfg(not(feature = "nym"))] + 2 => anyhow::bail!("Nym transport is not enabled in this build"), _ => { let body: Value = self .client From 1749b86e67801ac239b1d1cb1a1b983a62e49e51 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 19:42:51 +0800 Subject: [PATCH 164/189] fix: advance account dindex after the transparent scan The transparent sweep stores every used external address but left accounts.dindex untouched, so addresses found above the current index were missing from the 0..=dindex address list and next-address generation could land on an already-used index. After the scan, bump accounts.dindex to the greatest stored external (scope 0) index, never backwards. --- rust/src/sync.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rust/src/sync.rs b/rust/src/sync.rs index b857c279c..4fe8715d4 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -1399,6 +1399,23 @@ pub async fn transparent_sweep( } } } + // Advance the account dindex to the greatest stored external (scope 0) + // used index, never backwards. The scan only stores used addresses and + // address generation keeps accounts.dindex at the newest row, so the + // table's max external dindex is the receiving frontier. + sqlx::query( + "UPDATE accounts + SET dindex = max( + dindex, + COALESCE( + (SELECT max(dindex) FROM transparent_address_accounts + WHERE account = accounts.id_account AND scope = 0), + 0)) + WHERE id_account = ?", + ) + .bind(account) + .execute(&mut *connection) + .await?; Ok(n_added) }); Ok(()) From b09842ee6eca09d8e4620882f4f0837cb59a88fe Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 19:52:48 +0800 Subject: [PATCH 165/189] fix: stop the transparent scan only after consecutive unused addresses The gap counter was cumulative: used addresses found between unused ones did not reset it, so a sparse used/unused pattern ended the scan early and never discovered later used addresses. Reset the gap on each used address. --- rust/src/sync.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust/src/sync.rs b/rust/src/sync.rs index 4fe8715d4..c3d4b29de 100644 --- a/rust/src/sync.rs +++ b/rust/src/sync.rs @@ -1313,6 +1313,9 @@ pub async fn transparent_sweep( => { let mut txids = txids?; if txids.next().await.is_some() { + // A used address resets the gap count: only + // consecutive unused addresses end the scan. + gap = 0; let sk = if let Some(tsk) = tk.xsk.as_ref() { Some(derive_transparent_sk(tsk, scope, dindex)?) } else { From c6572f365fefe55767b28994733bbd8d990b86f6 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 20:17:58 +0800 Subject: [PATCH 166/189] fix: include Ironwood in Unshield All Unshield All used sourcePools 6 (Sapling | Orchard) and silently left any Ironwood shielded balance untouched. Use 14 (Sapling | Orchard | Ironwood) so the whole shielded balance is swept to the transparent address. --- lib/pages/send.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/send.dart b/lib/pages/send.dart index 70aef512b..fb0b23c58 100644 --- a/lib/pages/send.dart +++ b/lib/pages/send.dart @@ -326,7 +326,7 @@ class SendPageState extends ConsumerState<SendPage> { try { final pczt = await transferAllBetweenPools( c: c, - sourcePools: 6, + sourcePools: 14, // Sapling | Orchard | Ironwood destinationAddress: addresses?.taddr ?? "", ); From 0fefa11a40d657cbcd4d73bb27c6b507738d9df3 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Sat, 5 Sep 2026 20:30:26 +0800 Subject: [PATCH 167/189] fix: restart autoSync immediately when the interval becomes positive autoSync() read the interval from appSettingsProvider, which only updates after the settings page is saved, so changing the interval from 0 to a positive value cancelled the subscription instead of starting it. Pass the new interval explicitly to autoSync(). --- lib/settings.dart | 6 ++++-- lib/store.dart | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/settings.dart b/lib/settings.dart index d7962b130..7a44533b0 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -1130,10 +1130,12 @@ class SettingsFormState extends ConsumerState<SettingsForm> { settings = settings.copyWith(syncInterval: value); widget.onChanged(settings); }); - // Restart autoSync if the interval was changed to a positive value + // Restart autoSync if the interval was changed to a positive value. Pass + // the new interval explicitly: the appSettingsProvider still holds the + // previously saved value until the page is left. final interval = int.tryParse(value) ?? 0; if (interval > 0) { - ref.read(synchronizerProvider.notifier).autoSync(); + ref.read(synchronizerProvider.notifier).autoSync(interval: interval); } } diff --git a/lib/store.dart b/lib/store.dart index 40d7a87db..b5d3851b5 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -916,11 +916,11 @@ class SynchronizerNotifier extends _$SynchronizerNotifier { } } - Future<void> autoSync({bool now = false}) async { + Future<void> autoSync({bool now = false, int? interval}) async { final settings = await ref.read(appSettingsProvider.future); - final interval = int.tryParse(settings.syncInterval) ?? 0; + final effectiveInterval = interval ?? (int.tryParse(settings.syncInterval) ?? 0); - if (settings.offline || interval <= 0) { + if (settings.offline || effectiveInterval <= 0) { await _autoSyncSubscription?.cancel(); _autoSyncSubscription = null; return; From f2005e91ba55496791050083edbe6ff3ce8dd873 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Tue, 8 Sep 2026 20:29:35 +0800 Subject: [PATCH 168/189] fix: select and sync a newly restored account After restoring an account from a seed phrase, the 'synchronize now' prompt did nothing: syncIfNeeded read a stale getAccountsProvider cache that lacked the new account. Refresh and await the account list before switching the selection, and set selectedAccountIdProvider so the restored account is the selected one (also fixing resume-after-restart and the null currentAccount crash when the offstage AccountViewPage rebuilt mid-restore). --- build_number.txt | 2 +- lib/pages/new_account.dart | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/build_number.txt b/build_number.txt index 8c0a18696..5b0cffbc0 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -363 +370 diff --git a/lib/pages/new_account.dart b/lib/pages/new_account.dart index 3b1c57ba8..11a8811b8 100644 --- a/lib/pages/new_account.dart +++ b/lib/pages/new_account.dart @@ -446,7 +446,13 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { if (!settings.offline) await cacheBlockTime(height: bh, c: c); } on AnyhowException catch (_) {} + // Refresh the account list before switching selection, so the provider + // graph never sees a selected id that the (stale) list can't resolve. + ref.invalidate(getAccountsProvider); + await ref.read(getAccountsProvider.future); + await coinContext.setAccount(account: account); + ref.read(selectedAccountIdProvider.notifier).set(account); c = coinContext.coin; if ((key.isNotEmpty && await hasTransparentPubKey(c: c)) || ledger) { @@ -466,6 +472,7 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { if (mounted && key.isEmpty && seed != null) { await showSeed(context, seed.mnemonic); } + ref.invalidate(getAccountsProvider); if (mounted && r && currentHeight != null) { final shouldSync = await confirmDialog( context, @@ -473,10 +480,10 @@ class NewAccountPageState extends ConsumerState<NewAccountPage> { message: "Account imported successfully. Would you like to synchronize it now?", ); if (shouldSync && mounted) { + await ref.read(getAccountsProvider.future); unawaited(ref.read(synchronizerProvider.notifier).syncIfNeeded(currentHeight, now: true)); } } - ref.invalidate(getAccountsProvider); if (mounted) GoRouter.of(context).pop(); } on AnyhowException catch (e) { await showException(context, e.message); From d7c455d258833594931b16670c0cc467ebede9d6 Mon Sep 17 00:00:00 2001 From: hhanh00 <hanh425@gmail.com> Date: Sat, 12 Sep 2026 18:42:11 +0800 Subject: [PATCH 169/189] chore(main): release zkool 6.30.0 (#1249) --- .release-please-manifest.json | 2 +- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ build_number.txt | 2 +- pubspec.yaml | 2 +- version.txt | 2 +- 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 515ac7d61..3ed996f7b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "6.29.0" + ".": "6.30.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d6d731b9..7a0adcb07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [6.30.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.29.0...zkool-v6.30.0) (2026-09-12) + + +### Features + +* **account:** collapse pool balances on tap, persisted in DB settings ([7639054](https://github.com/hhanh00/zkool2/commit/7639054bcc6f542e90a961d853ed610dfc786d22)) +* create Ledger accounts and sign via zkool_graphql ([f792285](https://github.com/hhanh00/zkool2/commit/f7922853aeec099a4331416ebfa7e37401e07aee)) +* gate the Nym transport behind a cargo feature ([ad51493](https://github.com/hhanh00/zkool2/commit/ad51493d61f8f42834bdb7f93474c748e70f930a)) +* import Official Ledger UFVK from the device ([ae6de55](https://github.com/hhanh00/zkool2/commit/ae6de55f60bbeac1d7b749b81e34f544efcbff91)) +* sign v6 transactions with the Official Ledger app ([e6e462c](https://github.com/hhanh00/zkool2/commit/e6e462c6a71b7c3add7f823a280da9a69f525b84)) +* support multiple Ledger app types (Official, Zondax) ([#1242](https://github.com/hhanh00/zkool2/issues/1242)) ([1588b96](https://github.com/hhanh00/zkool2/commit/1588b96b43df840e640d0c8c3ff3b612b58a5602)) + + +### Bug Fixes + +* advance account dindex after the transparent scan ([1749b86](https://github.com/hhanh00/zkool2/commit/1749b86e67801ac239b1d1cb1a1b983a62e49e51)) +* build v6 for Official Ledger accounts and open the APDU HID interface ([121b51d](https://github.com/hhanh00/zkool2/commit/121b51d9737e7c3a5be8d99144578713582b4177)) +* derive shielded output addresses in the transaction plan ([1e03b2f](https://github.com/hhanh00/zkool2/commit/1e03b2f328f6eacce4c83626412a1a00c6b981dc)) +* force internal change for Official Ledger accounts ([cd79c02](https://github.com/hhanh00/zkool2/commit/cd79c02cfdde2407ddbd89b27495225aea6cf537)) +* include Ironwood in Unshield All ([c6572f3](https://github.com/hhanh00/zkool2/commit/c6572f365fefe55767b28994733bbd8d990b86f6)) +* keep transparent change addresses paired with external addresses ([cc51e2f](https://github.com/hhanh00/zkool2/commit/cc51e2ffb7c766b3d0172e65ef5acac14f3a87d6)) +* lock Use Internal Change per Ledger app and avoid empty pools selection ([f37e1b6](https://github.com/hhanh00/zkool2/commit/f37e1b62a8641220d6798290071703743fe50298)) +* make app error messages selectable ([599c223](https://github.com/hhanh00/zkool2/commit/599c223e84b8100b38576e99cf52d687c0853e5f)) +* pass the account id explicitly when signing on the server ([6e757f8](https://github.com/hhanh00/zkool2/commit/6e757f85580c5ae24371aab137604b7ecd7b726d)) +* restart autoSync immediately when the interval becomes positive ([0fefa11](https://github.com/hhanh00/zkool2/commit/0fefa11a40d657cbcd4d73bb27c6b507738d9df3)) +* scope witness consistency check to synced accounts ([059e980](https://github.com/hhanh00/zkool2/commit/059e980588554626add21ebb5da79acf9fc66cd2)) +* select and sync a newly restored account ([f2005e9](https://github.com/hhanh00/zkool2/commit/f2005e91ba55496791050083edbe6ff3ce8dd873)) +* stop the transparent scan only after consecutive unused addresses ([b09842e](https://github.com/hhanh00/zkool2/commit/b09842ee6eca09d8e4620882f4f0837cb59a88fe)) +* tag the transparent change output with its derivation ([eb3d89d](https://github.com/hhanh00/zkool2/commit/eb3d89d502a61422441c17b5c117a9d3ce2b9720)) +* **vote:** show ballot proposals immediately instead of after the vote-tree pre-sync ([694a5c2](https://github.com/hhanh00/zkool2/commit/694a5c20de8ac0eec8b24f027885636d589f723d)) + ## [6.29.0](https://github.com/hhanh00/zkool2/compare/zkool-v6.28.1...zkool-v6.29.0) (2026-09-01) diff --git a/build_number.txt b/build_number.txt index 5b0cffbc0..67bf40fe1 100644 --- a/build_number.txt +++ b/build_number.txt @@ -1 +1 @@ -370 +371 diff --git a/pubspec.yaml b/pubspec.yaml index 2d83958fd..69873284c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "Zkool" # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.29.0 # x-release-please-version +version: 6.30.0 # x-release-please-version environment: sdk: ^3.6.1 diff --git a/version.txt b/version.txt index 94ae9e992..137f5acd5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -6.29.0 +6.30.0 From 625f3d2a0225bd7b3016b5a95bfdd566277aec03 Mon Sep 17 00:00:00 2001 From: Hanh Huynh Huu <hanh425@gmail.com> Date: Mon, 14 Sep 2026 16:14:26 +0800 Subject: [PATCH 170/189] chore: restore prerelease rc config for release-please --- release-please-config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release-please-config.json b/release-please-config.json index 64e021bb6..a056d2f03 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -4,6 +4,9 @@ "release-type": "simple", "component": "zkool", "include-component-in-tag": true, + "prerelease": true, + "versioning": "prerelease", + "prerelease-type": "rc", "changelog-path": "CHANGELOG.md", "extra-files": [ "version.txt", From 2a7c90c2914bb0fee0938444d514065a49bf9e28 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto <cyjan@mrcyjanek.net> Date: Sat, 16 May 2026 09:18:48 -0400 Subject: [PATCH 171/189] cake wallet patch (cherry picked from commit 36e72b530c274c4a54a6127aadb94886e84d67bf) --- ios/Podfile.lock | 2 - lib/pages/raptor.dart | 24 +--- lib/src/rust/api/account.dart | 6 +- lib/src/rust/api/account.freezed.dart | 30 ++++- lib/src/rust/api/coin.dart | 2 +- lib/src/rust/api/contacts.dart | 2 +- lib/src/rust/api/db.dart | 2 +- lib/src/rust/api/frost.dart | 2 +- lib/src/rust/api/init.dart | 2 +- lib/src/rust/api/issuance.dart | 2 +- lib/src/rust/api/key.dart | 2 +- lib/src/rust/api/mempool.dart | 2 +- lib/src/rust/api/migrate.dart | 2 +- lib/src/rust/api/network.dart | 2 +- lib/src/rust/api/openalias.dart | 2 +- lib/src/rust/api/pay.dart | 2 +- lib/src/rust/api/plugin.dart | 2 +- lib/src/rust/api/raptor.dart | 2 +- lib/src/rust/api/sapling.dart | 2 +- lib/src/rust/api/sweep.dart | 2 +- lib/src/rust/api/sync.dart | 2 +- lib/src/rust/api/transaction.dart | 2 +- lib/src/rust/api/vault.dart | 2 +- lib/src/rust/api/zsa.dart | 2 +- lib/src/rust/frb_generated.io.dart | 2 +- lib/src/rust/frb_generated.web.dart | 2 +- lib/src/rust/io.dart | 2 +- lib/src/rust/lib.dart | 2 +- lib/src/rust/pay.dart | 2 +- lib/widgets/scanner.dart | 19 --- linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 6 - .../xcshareddata/swiftpm/Package.resolved | 68 ---------- pubspec.yaml | 23 ++-- rust/src/account.rs | 118 +++++++++++++++--- rust/src/api/account.rs | 7 ++ rust/src/db.rs | 24 ++-- rust_builder/cargokit/build_pod.sh | 3 +- .../lib/src/android_environment.dart | 2 +- .../cargokit/build_tool/lib/src/builder.dart | 6 +- rust_builder/cargokit/cmake/cargokit.cmake | 2 +- rust_builder/cargokit/gradle/plugin.gradle | 2 +- windows/flutter/generated_plugins.cmake | 1 + 43 files changed, 203 insertions(+), 191 deletions(-) delete mode 100644 macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 72fcaa47e..2383d5c9f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -99,7 +99,6 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - PromisesObjC (2.4.0) - rive_common (0.0.1): - Flutter - rlz (0.0.1): @@ -143,7 +142,6 @@ SPEC REPOS: - GTMAppAuth - GTMSessionFetcher - OrderedSet - - PromisesObjC - SDWebImage - SwiftyGif diff --git a/lib/pages/raptor.dart b/lib/pages/raptor.dart index 3ed4788d0..aa82ccbc0 100644 --- a/lib/pages/raptor.dart +++ b/lib/pages/raptor.dart @@ -7,7 +7,6 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:zkool/src/rust/api/raptor.dart'; import 'package:zkool/store.dart'; @@ -120,7 +119,6 @@ class ScanAnimatedQRPage extends StatefulWidget { class ScanAnimatedQRPageState extends State<ScanAnimatedQRPage> { Widget? scanner; - final controller = MobileScannerController(); Map<int, Uint8List> packets = {}; @override @@ -129,25 +127,8 @@ class ScanAnimatedQRPageState extends State<ScanAnimatedQRPage> { Future(() async { final completed = Completer<Uint8List>(); - final sub = controller.barcodes.listen((qr) async { - final barcode = qr.barcodes.first; - var data = barcode.rawBytes!; - if (Platform.isMacOS) data = getQrBytes(data: data); - if (data.length < 16) return; - final id = ByteData.sublistView(data).getUint32(12, Endian.big); - - if (!packets.containsKey(id)) { - packets[id] = data; - setState(() {}); - final result = await decode(packet: data); - if (result != null) { - completed.complete(result); - } - } - }); - final data = await completed.future; - sub.cancel(); - GoRouter.of(context).pop(data.toList()); + + GoRouter.of(context).pop([].toList()); }); } @@ -156,7 +137,6 @@ class ScanAnimatedQRPageState extends State<ScanAnimatedQRPage> { return Scaffold( body: Stack( children: [ - MobileScanner(controller: controller), Positioned( bottom: 10, left: 10, diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index cabe13ddb..1d978f230 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -85,6 +85,9 @@ Future<Addresses> getAccountAddresses( RustLib.instance.api.crateApiAccountGetAccountAddresses( account: account, uaPools: uaPools, c: c); +Future<List<String>> listOwnedAddresses({required Coin c}) => + RustLib.instance.api.crateApiAccountListOwnedAddresses(c: c); + Future<TxAccount> getTxDetails({required int idTx, required Coin c}) => RustLib.instance.api.crateApiAccountGetTxDetails(idTx: idTx, c: c); @@ -403,6 +406,7 @@ sealed class Tx with _$Tx { required int height, required int time, required PlatformInt64 value, + required PlatformInt64 fee, int? tpe, String? category, required PlatformInt64 zsaValue, diff --git a/lib/src/rust/api/account.freezed.dart b/lib/src/rust/api/account.freezed.dart index bea274294..594d3a823 100644 --- a/lib/src/rust/api/account.freezed.dart +++ b/lib/src/rust/api/account.freezed.dart @@ -3648,6 +3648,7 @@ mixin _$Tx { int get height; int get time; PlatformInt64 get value; + PlatformInt64 get fee; int? get tpe; String? get category; PlatformInt64 get zsaValue; @@ -3674,6 +3675,7 @@ mixin _$Tx { (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && + (identical(other.fee, fee) || other.fee == fee) && (identical(other.tpe, tpe) || other.tpe == tpe) && (identical(other.category, category) || other.category == category) && @@ -3698,6 +3700,7 @@ mixin _$Tx { height, time, value, + fee, tpe, category, zsaValue, @@ -3710,7 +3713,7 @@ mixin _$Tx { @override String toString() { - return 'Tx(id: $id, txid: $txid, height: $height, time: $time, value: $value, tpe: $tpe, category: $category, zsaValue: $zsaValue, assetId: $assetId, assetDisplay: $assetDisplay, price: $price, memo: $memo, isUserMemo: $isUserMemo, contactName: $contactName)'; + return 'Tx(id: $id, txid: $txid, height: $height, time: $time, value: $value, fee: $fee, tpe: $tpe, category: $category, zsaValue: $zsaValue, assetId: $assetId, assetDisplay: $assetDisplay, price: $price, memo: $memo, isUserMemo: $isUserMemo, contactName: $contactName)'; } } @@ -3724,6 +3727,7 @@ abstract mixin class $TxCopyWith<$Res> { int height, int time, PlatformInt64 value, + PlatformInt64 fee, int? tpe, String? category, PlatformInt64 zsaValue, @@ -3752,6 +3756,7 @@ class _$TxCopyWithImpl<$Res> implements $TxCopyWith<$Res> { Object? height = null, Object? time = null, Object? value = null, + Object? fee = null, Object? tpe = freezed, Object? category = freezed, Object? zsaValue = null, @@ -3783,6 +3788,10 @@ class _$TxCopyWithImpl<$Res> implements $TxCopyWith<$Res> { ? _self.value : value // ignore: cast_nullable_to_non_nullable as PlatformInt64, + fee: null == fee + ? _self.fee + : fee // ignore: cast_nullable_to_non_nullable + as PlatformInt64, tpe: freezed == tpe ? _self.tpe : tpe // ignore: cast_nullable_to_non_nullable @@ -3920,6 +3929,7 @@ extension TxPatterns on Tx { int height, int time, PlatformInt64 value, + PlatformInt64 fee, int? tpe, String? category, PlatformInt64 zsaValue, @@ -3941,6 +3951,7 @@ extension TxPatterns on Tx { _that.height, _that.time, _that.value, + _that.fee, _that.tpe, _that.category, _that.zsaValue, @@ -3976,6 +3987,7 @@ extension TxPatterns on Tx { int height, int time, PlatformInt64 value, + PlatformInt64 fee, int? tpe, String? category, PlatformInt64 zsaValue, @@ -3996,6 +4008,7 @@ extension TxPatterns on Tx { _that.height, _that.time, _that.value, + _that.fee, _that.tpe, _that.category, _that.zsaValue, @@ -4028,6 +4041,7 @@ extension TxPatterns on Tx { int height, int time, PlatformInt64 value, + PlatformInt64 fee, int? tpe, String? category, PlatformInt64 zsaValue, @@ -4048,6 +4062,7 @@ extension TxPatterns on Tx { _that.height, _that.time, _that.value, + _that.fee, _that.tpe, _that.category, _that.zsaValue, @@ -4072,6 +4087,7 @@ class _Tx implements Tx { required this.height, required this.time, required this.value, + required this.fee, this.tpe, this.category, required this.zsaValue, @@ -4093,6 +4109,8 @@ class _Tx implements Tx { @override final PlatformInt64 value; @override + final PlatformInt64 fee; + @override final int? tpe; @override final String? category; @@ -4128,6 +4146,7 @@ class _Tx implements Tx { (identical(other.height, height) || other.height == height) && (identical(other.time, time) || other.time == time) && (identical(other.value, value) || other.value == value) && + (identical(other.fee, fee) || other.fee == fee) && (identical(other.tpe, tpe) || other.tpe == tpe) && (identical(other.category, category) || other.category == category) && @@ -4152,6 +4171,7 @@ class _Tx implements Tx { height, time, value, + fee, tpe, category, zsaValue, @@ -4164,7 +4184,7 @@ class _Tx implements Tx { @override String toString() { - return 'Tx(id: $id, txid: $txid, height: $height, time: $time, value: $value, tpe: $tpe, category: $category, zsaValue: $zsaValue, assetId: $assetId, assetDisplay: $assetDisplay, price: $price, memo: $memo, isUserMemo: $isUserMemo, contactName: $contactName)'; + return 'Tx(id: $id, txid: $txid, height: $height, time: $time, value: $value, fee: $fee, tpe: $tpe, category: $category, zsaValue: $zsaValue, assetId: $assetId, assetDisplay: $assetDisplay, price: $price, memo: $memo, isUserMemo: $isUserMemo, contactName: $contactName)'; } } @@ -4179,6 +4199,7 @@ abstract mixin class _$TxCopyWith<$Res> implements $TxCopyWith<$Res> { int height, int time, PlatformInt64 value, + PlatformInt64 fee, int? tpe, String? category, PlatformInt64 zsaValue, @@ -4207,6 +4228,7 @@ class __$TxCopyWithImpl<$Res> implements _$TxCopyWith<$Res> { Object? height = null, Object? time = null, Object? value = null, + Object? fee = null, Object? tpe = freezed, Object? category = freezed, Object? zsaValue = null, @@ -4238,6 +4260,10 @@ class __$TxCopyWithImpl<$Res> implements _$TxCopyWith<$Res> { ? _self.value : value // ignore: cast_nullable_to_non_nullable as PlatformInt64, + fee: null == fee + ? _self.fee + : fee // ignore: cast_nullable_to_non_nullable + as PlatformInt64, tpe: freezed == tpe ? _self.tpe : tpe // ignore: cast_nullable_to_non_nullable diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index 87f2082ab..ebeab917d 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/contacts.dart b/lib/src/rust/api/contacts.dart index 97c03c9dc..7f5ff0da9 100644 --- a/lib/src/rust/api/contacts.dart +++ b/lib/src/rust/api/contacts.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/db.dart b/lib/src/rust/api/db.dart index 77746c5fd..bd56ce4ad 100644 --- a/lib/src/rust/api/db.dart +++ b/lib/src/rust/api/db.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index 1325efab6..e3ef36cc5 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/init.dart b/lib/src/rust/api/init.dart index 2502df761..e8b0a78aa 100644 --- a/lib/src/rust/api/init.dart +++ b/lib/src/rust/api/init.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/issuance.dart b/lib/src/rust/api/issuance.dart index baa7321b7..a6b0cf466 100644 --- a/lib/src/rust/api/issuance.dart +++ b/lib/src/rust/api/issuance.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/key.dart b/lib/src/rust/api/key.dart index 65992f57e..31a45b0cf 100644 --- a/lib/src/rust/api/key.dart +++ b/lib/src/rust/api/key.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/mempool.dart b/lib/src/rust/api/mempool.dart index 847ca3ee0..603137f1b 100644 --- a/lib/src/rust/api/mempool.dart +++ b/lib/src/rust/api/mempool.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index b38200c11..2e22c9ad5 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/network.dart b/lib/src/rust/api/network.dart index 3c056c3a7..d476a9921 100644 --- a/lib/src/rust/api/network.dart +++ b/lib/src/rust/api/network.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/openalias.dart b/lib/src/rust/api/openalias.dart index 7e0e0fb46..417a3f8cd 100644 --- a/lib/src/rust/api/openalias.dart +++ b/lib/src/rust/api/openalias.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index ca8eccb63..4de71a5dd 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/plugin.dart b/lib/src/rust/api/plugin.dart index 773ec276d..cc3501b1d 100644 --- a/lib/src/rust/api/plugin.dart +++ b/lib/src/rust/api/plugin.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/raptor.dart b/lib/src/rust/api/raptor.dart index 584e6f953..d56383f0f 100644 --- a/lib/src/rust/api/raptor.dart +++ b/lib/src/rust/api/raptor.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/sapling.dart b/lib/src/rust/api/sapling.dart index 72388e983..0a9b7ba5c 100644 --- a/lib/src/rust/api/sapling.dart +++ b/lib/src/rust/api/sapling.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/sweep.dart b/lib/src/rust/api/sweep.dart index 3b11052b8..5dd6ab3ba 100644 --- a/lib/src/rust/api/sweep.dart +++ b/lib/src/rust/api/sweep.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/sync.dart b/lib/src/rust/api/sync.dart index d07d48c5e..8ef4d3d88 100644 --- a/lib/src/rust/api/sync.dart +++ b/lib/src/rust/api/sync.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/transaction.dart b/lib/src/rust/api/transaction.dart index a3eb4e2ce..4702254f7 100644 --- a/lib/src/rust/api/transaction.dart +++ b/lib/src/rust/api/transaction.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/vault.dart b/lib/src/rust/api/vault.dart index 749ed9dab..5b8532f0a 100644 --- a/lib/src/rust/api/vault.dart +++ b/lib/src/rust/api/vault.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/zsa.dart b/lib/src/rust/api/zsa.dart index a8ade42f8..5268a566c 100644 --- a/lib/src/rust/api/zsa.dart +++ b/lib/src/rust/api/zsa.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index fd5cdffb6..124af5f41 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index fbeaa8738..02a68e7c4 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field diff --git a/lib/src/rust/io.dart b/lib/src/rust/io.dart index 0d15c9d3e..55bbab0c3 100644 --- a/lib/src/rust/io.dart +++ b/lib/src/rust/io.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/lib.dart b/lib/src/rust/lib.dart index 5372cd8a9..49f31a45f 100644 --- a/lib/src/rust/lib.dart +++ b/lib/src/rust/lib.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/pay.dart b/lib/src/rust/pay.dart index 4c52e5bf3..84d3d8e93 100644 --- a/lib/src/rust/pay.dart +++ b/lib/src/rust/pay.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. +// @generated by `flutter_rust_bridge`@ 2.11.1. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index d5b73148b..8377ab4e6 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:qr_flutter/qr_flutter.dart'; class ScannerPage extends StatefulWidget { @@ -21,28 +20,10 @@ class _ScannerPageState extends State<ScannerPage> { title: const Text("QR Scanner"), ), body: Center( - child: MobileScanner( - onDetect: onDetect, - fit: BoxFit.cover, - ), ), ); } - void onDetect(BarcodeCapture? capture) { - if (scanned || capture == null) return; - final List<Barcode> barcodes = capture.barcodes; - for (final barcode in barcodes) { - final text = barcode.rawValue; - if (text != null) { - final error = widget.validator.call(text); - if (error == null) { - scanned = true; - GoRouter.of(context).pop(text); - } - } - } - } } Future<String?> showScanner( diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index b77b820f9..8a66dfded 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni rlz ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4795fec64..4d3e84224 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,12 +10,9 @@ import file_picker import file_selector_macos import flutter_contacts import flutter_inappwebview_macos -import flutter_passkey_service import google_sign_in_ios import local_auth_darwin -import mobile_scanner import package_info_plus -import path_provider_foundation import rive_common import shared_preferences_foundation import url_launcher_macos @@ -26,12 +23,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterContactsPlugin.register(with: registry.registrar(forPlugin: "FlutterContactsPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) - FlutterPasskeyServicePlugin.register(with: registry.registrar(forPlugin: "FlutterPasskeyServicePlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) - MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 100cf7b26..000000000 --- a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,68 +0,0 @@ -{ - "pins" : [ - { - "identity" : "app-check", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/app-check.git", - "state" : { - "revision" : "61b85103a1aeed8218f17c794687781505fbbef5", - "version" : "11.2.0" - } - }, - { - "identity" : "appauth-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/openid/AppAuth-iOS.git", - "state" : { - "revision" : "2781038865a80e2c425a1da12cc1327bcd56501f", - "version" : "1.7.6" - } - }, - { - "identity" : "googlesignin-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleSignIn-iOS.git", - "state" : { - "revision" : "65fb3f1aa6ffbfdc79c4e22178a55cd91561f5e9", - "version" : "8.0.0" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "60da361632d0de02786f709bdc0c4df340f7613e", - "version" : "8.1.0" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b", - "version" : "3.5.0" - } - }, - { - "identity" : "gtmappauth", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GTMAppAuth.git", - "state" : { - "revision" : "5d7d66f647400952b1758b230e019b07c0b4b22a", - "version" : "4.1.1" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", - "version" : "2.4.0" - } - } - ], - "version" : 2 -} diff --git a/pubspec.yaml b/pubspec.yaml index 69873284c..9abf38a39 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: cupertino_icons: ^1.0.8 rlz: path: rust_builder - flutter_rust_bridge: 2.12.0 + flutter_rust_bridge: 2.11.1 logger: ^2.0.2+1 go_router: ^14.8.1 @@ -33,7 +33,7 @@ dependencies: path_provider: ^2.1.5 file_picker: ^10.3.8 - flutter_contacts: ^2.2.1 + # flutter_contacts: ^2.0.0 collection: ^1.19.1 image_picker: ^1.1.2 @@ -48,7 +48,6 @@ dependencies: decimal: ^3.2.1 intl: ^0.20.2 - mobile_scanner: ^7.0.1 qr_flutter: ^4.1.0 local_auth: ^2.3.0 @@ -64,18 +63,18 @@ dependencies: bubble: ^1.2.1 memoize: ^3.0.0 async: ^2.13.0 - flutter_passkey_service: - git: https://github.com/hhanh00/flutter_passkey_service.git + #flutter_passkey_service: + # git: https://github.com/hhanh00/flutter_passkey_service.git - googleapis: ^13.0.0 - google_sign_in: ^6.0.0 - googleapis_auth: ^1.6.0 - extension_google_sign_in_as_googleapis_auth: ^2.0.0 - device_info_plus: ^10.1.0 + # googleapis: ^13.0.0 + # google_sign_in: ^6.0.0 + # googleapis_auth: ^1.6.0 + # extension_google_sign_in_as_googleapis_auth: ^2.0.0 + device_info_plus: ^9.1.0 - password_strength_checker: ^1.3.2 + # password_strength_checker: ^1.3.2 crypto: ^3.0.3 - flex_color_scheme: ^8.4.0 + flex_color_scheme: ^8.1.1 dev_dependencies: flutter_test: diff --git a/rust/src/account.rs b/rust/src/account.rs index 9ca221729..7c04af1a2 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -257,23 +257,44 @@ pub async fn new_account( store_account_transparent_sk(&mut db_tx, account, tsk).await?; let tvk = &tsk.to_account_pubkey(); store_account_transparent_vk(&mut db_tx, account, tvk).await?; - for di in &[0, dindex] { - let sk = derive_transparent_sk(tsk, 0, *di)?; - let (pk, taddr) = derive_transparent_address(tvk, 0, *di, false)?; - store_account_transparent_addr( - &mut db_tx, - account, - 0, - *di, - Some(sk), - &pk, - &taddr.encode(&network), - false, - ) - .await?; - // do not create two taddrs if dindex == 0 - if dindex == 0 { - break; + // Transparent-only accounts need every receive slot 0..=dindex registered: + // transparent_sync only scans rows in transparent_address_accounts. + // The unified default diversifier can be >0, so &[0, dindex] leaves gaps. + if pools == 1 { + for di in 0..=dindex { + let sk = derive_transparent_sk(tsk, 0, di)?; + let (pk, taddr) = derive_transparent_address(tvk, 0, di, false)?; + store_account_transparent_addr( + &mut db_tx, + account, + 0, + di, + Some(sk), + &pk, + &taddr.encode(&network), + false, + ) + .await?; + } + } else { + for di in &[0, dindex] { + let sk = derive_transparent_sk(tsk, 0, *di)?; + let (pk, taddr) = derive_transparent_address(tvk, 0, *di, false)?; + store_account_transparent_addr( + &mut db_tx, + account, + 0, + *di, + Some(sk), + &pk, + &taddr.encode(&network), + false, + ) + .await?; + // do not create two taddrs if dindex == 0 + if dindex == 0 { + break; + } } } } @@ -837,6 +858,28 @@ pub async fn generate_next_dindex( .fetch_one(&mut *db_tx) .await?; let hw = get_account_hw(&mut db_tx, account).await?; + // Backfill any skipped transparent receive slots (transparent-only rotation wallets). + let tkeys_fill = select_account_transparent(&mut db_tx, account, dindex).await?; + if let Some(xvk) = tkeys_fill.xvk.as_ref() { + for di in 0..=dindex { + let sk = tkeys_fill + .xsk + .as_ref() + .and_then(|tsk| derive_transparent_sk(tsk, 0, di).ok()); + let (pk, taddr) = derive_transparent_address(xvk, 0, di, false)?; + store_account_transparent_addr( + &mut db_tx, + account, + 0, + di, + sk, + &pk, + &taddr.encode(network), + false, + ) + .await?; + } + } // Next Sapling address. Some dindex must be skipped because they do not // correspond to a valid sapling address let svk = get_sapling_vk(&mut db_tx, account).await?; @@ -1165,6 +1208,47 @@ pub async fn get_addresses( Ok(addresses) } +pub async fn list_owned_addresses( + network: &Network, + connection: &mut SqliteConnection, + account: u32, +) -> Result<Vec<String>> { + let mut addresses = Vec::new(); + let hw = get_account_hw(connection, account).await?; + + let transparent = sqlx::query( + "SELECT address FROM transparent_address_accounts WHERE account = ?", + ) + .bind(account) + .map(|row: SqliteRow| row.get::<String, _>(0)) + .fetch_all(&mut *connection) + .await?; + addresses.extend(transparent); + + for scope in [0u8, 1u8] { + let addr = get_account_full_address(network, connection, account, scope, hw).await?; + if !addr.is_empty() { + addresses.push(addr); + } + } + + let addrs = get_addresses(network, connection, account, ALL_POOLS).await?; + if let Some(t) = addrs.taddr { + addresses.push(t); + } + if let Some(s) = addrs.saddr { + addresses.push(s); + } + if let Some(o) = addrs.oaddr { + addresses.push(o); + } + if let Some(u) = addrs.ua { + addresses.push(u); + } + + Ok(addresses) +} + pub async fn reset_sync( network: &Network, connection: &mut SqliteConnection, diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index 57c464fdf..b8aa48e95 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -324,6 +324,7 @@ pub struct Tx { pub height: u32, pub time: u32, pub value: i64, + pub fee: i64, pub tpe: Option<u8>, pub category: Option<String>, pub zsa_value: i64, @@ -392,6 +393,12 @@ pub async fn get_account_addresses(account: u32, ua_pools: u8, c: &Coin) -> Resu crate::account::get_addresses(&c.network(), &mut connection, account, ua_pools).await } +#[cfg_attr(feature = "flutter", frb)] +pub async fn list_owned_addresses(c: &Coin) -> Result<Vec<String>> { + let mut connection = c.get_connection().await?; + crate::account::list_owned_addresses(&c.network(), &mut connection, c.account).await +} + pub struct Addresses { pub taddr: Option<String>, pub saddr: Option<String>, diff --git a/rust/src/db.rs b/rust/src/db.rs index 7baac7212..9a0ca8f06 100644 --- a/rust/src/db.rs +++ b/rust/src/db.rs @@ -1451,7 +1451,7 @@ pub async fn fetch_txs(connection: &mut SqliteConnection, account: u32) -> Resul // order by height desc to get latest transactions first tracing::debug!("fetch_txs: starting for account {}", account); let transactions = sqlx::query( - "SELECT t.id_tx, t.txid, t.height, t.time, t.value, t.tpe, c.name, t.zsa_value, t.price, t.asset_id, + "SELECT t.id_tx, t.txid, t.height, t.time, t.value, t.fee, t.tpe, c.name, t.zsa_value, t.price, t.asset_id, a.asset_name, a.asset_desc_hash, um.user_memo as memo, (um.user_memo IS NOT NULL AND um.user_memo != '') as is_user_memo, @@ -1476,18 +1476,20 @@ pub async fn fetch_txs(connection: &mut SqliteConnection, account: u32) -> Resul let height: u32 = row.get(2); let time: u32 = row.get(3); let value: i64 = row.get(4); - let tpe: Option<u8> = row.get(5); - let category: Option<String> = row.get(6); - let zsa_value: i64 = row.get(7); - let price: Option<f64> = row.get(8); - let asset_id: Option<i32> = row.get(9); - let asset_name: Option<String> = row.get(10); - let asset_desc_hash: Option<Vec<u8>> = row.get(11); - let memo: Option<String> = row.get(12); - let is_user_memo: bool = row.get(13); - let contact_name: Option<String> = row.get(14); + let fee: i64 = row.get(5); + let tpe: Option<u8> = row.get(6); + let category: Option<String> = row.get(7); + let zsa_value: i64 = row.get(8); + let price: Option<f64> = row.get(9); + let asset_id: Option<i32> = row.get(10); + let asset_name: Option<String> = row.get(11); + let asset_desc_hash: Option<Vec<u8>> = row.get(12); + let memo: Option<String> = row.get(13); + let is_user_memo: bool = row.get(14); + let contact_name: Option<String> = row.get(15); Tx { id, + fee, txid, height, time, diff --git a/rust_builder/cargokit/build_pod.sh b/rust_builder/cargokit/build_pod.sh index 88df765d7..c382e0664 100755 --- a/rust_builder/cargokit/build_pod.sh +++ b/rust_builder/cargokit/build_pod.sh @@ -20,7 +20,8 @@ export CARGOKIT_DARWIN_PLATFORM_NAME=$PLATFORM_NAME export CARGOKIT_DARWIN_ARCHS=$ARCHS # Current build configuration (Debug, Release) -export CARGOKIT_CONFIGURATION=$CONFIGURATION +# export CARGOKIT_CONFIGURATION=$CONFIGURATION +export CARGOKIT_CONFIGURATION=release # Path to directory containing Cargo.toml. export CARGOKIT_MANIFEST_DIR=$PODS_TARGET_SRCROOT/$1 diff --git a/rust_builder/cargokit/build_tool/lib/src/android_environment.dart b/rust_builder/cargokit/build_tool/lib/src/android_environment.dart index 15fc9eeda..264359c1f 100644 --- a/rust_builder/cargokit/build_tool/lib/src/android_environment.dart +++ b/rust_builder/cargokit/build_tool/lib/src/android_environment.dart @@ -185,7 +185,7 @@ class AndroidEnvironment { .writeAsStringSync('INPUT(-lgcc)'); } - var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? ''; + var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? "--cfg\u001fzcash_unstable=\"nu7\""; if (rustFlags.isNotEmpty) { rustFlags = '$rustFlags\x1f'; } diff --git a/rust_builder/cargokit/build_tool/lib/src/builder.dart b/rust_builder/cargokit/build_tool/lib/src/builder.dart index 0f5ee997c..a5c63a45f 100644 --- a/rust_builder/cargokit/build_tool/lib/src/builder.dart +++ b/rust_builder/cargokit/build_tool/lib/src/builder.dart @@ -151,7 +151,7 @@ class RustBuilder { manifestPath, '-p', environment.crateInfo.packageName, - if (!environment.configuration.isDebug) '--release', + '--release', '--target', target.rust, '--target-dir', @@ -168,7 +168,9 @@ class RustBuilder { Future<Map<String, String>> _buildEnvironment() async { if (target.android == null) { - return {}; + return { + "RUSTFLAGS": '--cfg zcash_unstable="nu7"' + }; } else { final sdkPath = environment.androidSdkPath; final ndkVersion = environment.androidNdkVersion; diff --git a/rust_builder/cargokit/cmake/cargokit.cmake b/rust_builder/cargokit/cmake/cargokit.cmake index ddd05df9b..321ed36cd 100644 --- a/rust_builder/cargokit/cmake/cargokit.cmake +++ b/rust_builder/cargokit/cmake/cargokit.cmake @@ -35,7 +35,7 @@ function(apply_cargokit target manifest_dir lib_name any_symbol_name) set(CARGOKIT_ENV "CARGOKIT_CMAKE=${CMAKE_COMMAND}" - "CARGOKIT_CONFIGURATION=$<CONFIG>" + "CARGOKIT_CONFIGURATION=release" "CARGOKIT_MANIFEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/${manifest_dir}" "CARGOKIT_TARGET_TEMP_DIR=${CARGOKIT_TEMP_DIR}" "CARGOKIT_OUTPUT_DIR=${CARGOKIT_OUTPUT_DIR}" diff --git a/rust_builder/cargokit/gradle/plugin.gradle b/rust_builder/cargokit/gradle/plugin.gradle index 4af35ee05..33215effa 100644 --- a/rust_builder/cargokit/gradle/plugin.gradle +++ b/rust_builder/cargokit/gradle/plugin.gradle @@ -71,7 +71,7 @@ abstract class CargoKitBuildTask extends DefaultTask { environment "CARGOKIT_ROOT_PROJECT_DIR", rootProjectDir environment "CARGOKIT_TOOL_TEMP_DIR", "${buildDir}/build_tool" environment "CARGOKIT_MANIFEST_DIR", manifestDir - environment "CARGOKIT_CONFIGURATION", buildMode + environment "CARGOKIT_CONFIGURATION", "release" environment "CARGOKIT_TARGET_TEMP_DIR", buildDir environment "CARGOKIT_OUTPUT_DIR", outputDir environment "CARGOKIT_NDK_VERSION", ndkVersion diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index e3f6ba78d..c5b91f362 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni rlz ) From c8f1282ce7d4d293da8d3f2663feb6ce59ee77aa Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 5 Aug 2026 19:52:43 -0400 Subject: [PATCH 172/189] pay: add prove_and_finalize for externally signed PCZTs sign_transaction fuses signing, proving and spend finalization, so a PCZT signed off-device (Keystone, Cupcake) had no way to be completed: proving is hot-side work but was only reachable through the code path that needs spending keys. prove_and_finalize takes an already-signed PCZT and runs just the Prover (sapling/orchard/ironwood) and SpendFinalizer, so the result can go to extract_transaction and broadcast. It touches no spending keys, making it usable on watch-only accounts, and is exposed through api::pay for FRB. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 2a52d2efc408ef50294520ba319f533f86821205) --- rust/src/api/pay.rs | 12 ++++++++ rust/src/pay/plan.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 13a6a9ad0..38b8e0c74 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -100,6 +100,18 @@ pub enum SigningEvent { Result(PcztPackage), } +/// Proves and finalizes a PCZT signed by an external airgapped signer +/// (Keystone, Cupcake). Uses no spending keys, so it works on watch-only +/// accounts; pass the result to [`extract_transaction`] to broadcast. +#[cfg_attr(feature = "flutter", frb)] +pub async fn prove_and_finalize(pczt: &PcztPackage, c: &Coin) -> Result<PcztPackage> { + let network = c.network(); + + let tx = crate::pay::plan::prove_and_finalize(&network, pczt).await?; + + Ok(tx) +} + #[cfg_attr(feature = "flutter", frb)] pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { crate::pay::plan::extract_transaction(package).await diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 8416af2d4..d6053a98d 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1485,6 +1485,74 @@ pub async fn sign_transaction( }) } +/// Proves and finalizes a PCZT whose signatures were produced elsewhere (an +/// airgapped signer such as Keystone or Cupcake, which never proves). +/// +/// This is the second half of [`sign_transaction`]: the caller supplies a PCZT +/// that already carries spend authorization signatures, and this runs the +/// Prover and Spend Finalizer so the result can be extracted and broadcast. +/// No spending keys are touched, so it is safe for watch-only accounts. +pub async fn prove_and_finalize( + network: &crate::api::coin::Network, + package: &PcztPackage, +) -> Result<PcztPackage> { + let span = span!(Level::INFO, "transaction"); + + let PcztPackage { + pczt, + n_spends, + sapling_indices, + orchard_indices, + ironwood_indices, + price, + category, + is_issuance, + .. + } = package; + let pczt = Pczt::parse(pczt).map_err(|e| anyhow!("failed to parse PCZT: {e:?}"))?; + + let ironwood_active = network.is_nu_active( + NetworkUpgrade::Nu6_3, + BlockHeight::from_u32(*pczt.global().expiry_height()), + ); + + span.in_scope(|| { + info!("Adding Proofs to externally signed PCZT"); + }); + + let sapling_prover = get_sapling_prover().await?; + let orchard_pk = get_orchard_pk(network, ironwood_active); + let pczt = Prover::new(pczt) + .create_sapling_proofs(sapling_prover, sapling_prover) + .map_err(|e| anyhow!("sapling proving failed: {e:?}"))? + .create_orchard_proof(orchard_pk) + .map_err(|e| anyhow!("orchard proving failed: {e:?}"))? + .create_ironwood_proof(&IRONWOOD_PK) + .map_err(|e| anyhow!("ironwood proving failed: {e:?}"))? + .finish(); + info!("Proved"); + + let pczt = SpendFinalizer::new(pczt) + .finalize_spends() + .map_err(|e| anyhow!("spend finalization failed: {e:?}"))?; + info!("Spend Finalized"); + + Ok(PcztPackage { + pczt: pczt + .serialize() + .map_err(|e| anyhow!("failed to serialize PCZT: {e:?}"))?, + n_spends: *n_spends, + sapling_indices: sapling_indices.clone(), + orchard_indices: orchard_indices.clone(), + ironwood_indices: ironwood_indices.clone(), + can_sign: false, + can_broadcast: true, + price: *price, + category: *category, + is_issuance: *is_issuance, + }) +} + pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { let span = span!(Level::INFO, "transaction"); span.in_scope(|| { From b17dcd5ae47ec75db944a1f91f4bf6f0b932f791 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Thu, 6 Aug 2026 22:01:12 -0400 Subject: [PATCH 173/189] pay: identify transparent inputs the way an external signer expects The PCZT's transparent bip32_derivation entries carried a zeroed seed fingerprint and a two-element path. Nothing checked either while signing happened in-process, so both were effectively placeholders. A hardware wallet does check: it matches the fingerprint against its own seed and parses the path as BIP 44, and rejects anything that fails as belonging to a different wallet. Write the account's stored fingerprint and the full m/44'/coin'/account'/scope/index path instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 972c702f2e2605caf77c74a9260cd9c9c476770b) --- rust/src/pay/plan.rs | 26 +++++++++++++++++++-- rust/tests/cross_version_pczt.rs | 32 +++++++++++++++++++++++++ rust/tests/v1_encoding_probe.rs | 40 ++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 rust/tests/cross_version_pczt.rs create mode 100644 rust/tests/v1_encoding_probe.rs diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index d6053a98d..a565c3f86 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1160,6 +1160,22 @@ pub async fn plan_transaction( } } + // An external signer identifies its own inputs by the ZIP-32 seed + // fingerprint and the full BIP-44 path. Both were previously placeholders + // — a zeroed fingerprint and a two-element path — which nothing checked, + // because signing happened locally. A hardware wallet does check, and + // rejects the transaction as belonging to a different wallet. + let seed_fingerprint: [u8; 32] = crate::db::get_account_fingerprint(&mut *connection, account) + .await? + .and_then(|fp| <[u8; 32]>::try_from(fp).ok()) + .unwrap_or([0u8; 32]); + let aindex = crate::db::get_account_aindex(&mut *connection, account).await?; + const HARDENED: u32 = 0x8000_0000; + let coin_type: u32 = match network { + Network::Main => 133, + _ => 1, + }; + let updater = Updater::new(pczt); let updater = updater .update_transparent_with(|mut u| { @@ -1167,8 +1183,14 @@ pub async fn plan_transaction( tsk_dindex.into_iter().enumerate() { u.update_input_with(i, |mut u| { - let derivation_path = vec![scope, dindex_t]; - let path = Bip32Derivation::parse([0u8; 32], derivation_path).unwrap(); + let derivation_path = vec![ + 44 | HARDENED, + coin_type | HARDENED, + aindex | HARDENED, + scope, + dindex_t, + ]; + let path = Bip32Derivation::parse(seed_fingerprint, derivation_path).unwrap(); u.set_bip32_derivation(pubkey.serialize(), path); u.set_proprietary("scope".to_string(), scope.to_le_bytes().to_vec()); u.set_proprietary("dindex".to_string(), dindex_t.to_le_bytes().to_vec()); diff --git a/rust/tests/cross_version_pczt.rs b/rust/tests/cross_version_pczt.rs new file mode 100644 index 000000000..e5ad3c7b2 --- /dev/null +++ b/rust/tests/cross_version_pczt.rs @@ -0,0 +1,32 @@ +//! Wire-compatibility check between PCZT implementations. +//! +//! This crate pins `pczt 0.7` (MrCyjaneK fork); the Cupcake airgapped signer +//! uses crates.io `pczt 0.9`. Both must read each other's bytes or the +//! airgapped flow cannot work: the signer's output has to parse here for +//! proving and broadcast. +//! +//! The fixture is a real Ironwood (NU6.3, v6) PCZT produced by the signer. + +use pczt::Pczt; + +#[test] +fn parses_a_pczt_serialized_by_the_airgapped_signer() { + let hex_text = include_str!("cupcake_ironwood_pczt.hex"); + let bytes = hex::decode(hex_text.trim()).expect("fixture is valid hex"); + + assert_eq!(&bytes[..4], b"PCZT", "fixture carries the PCZT magic"); + let version = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); + println!("fixture PCZT version: {version}"); + + match Pczt::parse(&bytes) { + Ok(pczt) => { + println!( + "parsed OK: expiry={} orchard_actions={} ironwood_actions={}", + pczt.global().expiry_height(), + pczt.orchard().actions().len(), + pczt.ironwood().actions().len(), + ); + } + Err(e) => panic!("INCOMPATIBLE: pczt 0.7 cannot parse 0.9 output: {e:?}"), + } +} diff --git a/rust/tests/v1_encoding_probe.rs b/rust/tests/v1_encoding_probe.rs new file mode 100644 index 000000000..ab8904830 --- /dev/null +++ b/rust/tests/v1_encoding_probe.rs @@ -0,0 +1,40 @@ +//! Scratch probe: dump v1 and v2 PCZT encodings of an Orchard-anchored PCZT +//! produced by this crate's pinned `pczt` (lrz 0.7), so they can be fed to +//! another pczt version's parser. + +use pczt::roles::creator::Creator; +use zcash_protocol::consensus::BranchId; + +#[test] +fn dump_v1_and_v2_encodings() { + let branch: u32 = BranchId::Nu6.into(); + let mut out = String::new(); + + for (tag, orchard_anchor) in [("ANCHORED", [7u8; 32]), ("EMPTYPOOLS", [0u8; 32])] { + let pczt = Creator::new(branch, 10_000_000, 133, [0u8; 32], orchard_anchor) + .unwrap() + .build(); + + let v2 = pczt.clone().serialize().expect("v2 serialize"); + out.push_str(&format!("{tag}-V2 {}\n", hex::encode(&v2))); + + match pczt::v1::Pczt::try_from(pczt) { + Ok(v1) => out.push_str(&format!("{tag}-V1 {}\n", hex::encode(v1.serialize()))), + Err(e) => out.push_str(&format!("V1_ERR {tag} {:?}\n", e)), + } + } + + // A v6 (NU6.3 / Ironwood) PCZT: can it use the v1 escape hatch at all? + let branch63: u32 = BranchId::Nu6_3.into(); + let p6 = Creator::new(branch63, 10_000_000, 133, [0u8; 32], [7u8; 32]) + .unwrap() + .build(); + match pczt::v1::Pczt::try_from(p6) { + Ok(v1) => out.push_str(&format!("V6-V1 {}\n", hex::encode(v1.serialize()))), + Err(e) => out.push_str(&format!("V1_ERR V6 {:?}\n", e)), + } + + let path = std::env::var("PROBE_OUT").unwrap_or_else(|_| "/tmp/pczt_probe.txt".into()); + std::fs::write(&path, &out).unwrap(); + println!("{out}"); +} From be2d46bb2d5bbd1db64b3feac3a7dad55851cac8 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Thu, 6 Aug 2026 23:26:22 -0400 Subject: [PATCH 174/189] pay: claim shielded spends for an external signer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Orchard and Ironwood spends were built with no ZIP-32 derivation, because the Orchard updater was never run at all — only the transparent and sapling ones were. A shielded spend therefore reached an external signer with nothing identifying the account that owns it, and was refused as belonging to a different wallet. zip32_derivation is the only ownership marker the Updater role can place on an Orchard spend, so set it on every real spend in both bundles. The path is m/32'/coin_type'/account', fully hardened and exactly three elements — the five-element BIP 44 path transparent inputs use is rejected here. Dummy spends are builder padding and stay unclaimed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 2fbdb988019936d74191c03b92c80d583a1c635d) --- rust/src/pay/plan.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index a565c3f86..874b1bcf5 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1230,6 +1230,57 @@ pub async fn plan_transaction( } .map_err(|error| anyhow!("Failed to attach Orchard asset names: {error:?}"))?; + // Shielded spends carry no key material of their own, so an external + // signer identifies them by the ZIP-32 path of the account that can spend + // them. Without this the spend reaches the device with no derivation at + // all and is refused as belonging to another wallet. + // + // Orchard requires every element hardened, and the path is exactly the + // three-element m/32'/coin_type'/account' — not the five-element BIP 44 + // path used for transparent inputs, which this rejects. + let orchard_zip32 = || { + orchard::pczt::Zip32Derivation::parse( + seed_fingerprint, + vec![32 | HARDENED, coin_type | HARDENED, aindex | HARDENED], + ) + .expect("orchard ZIP-32 path is fully hardened") + }; + + // Dummy spends are the builder's padding and belong to nobody, so leave + // them unclaimed. + fn real_spend_indices(bundle: &orchard::pczt::Bundle) -> Vec<usize> { + bundle + .actions() + .iter() + .enumerate() + .filter_map(|(i, a)| a.spend().dummy_sk().is_none().then_some(i)) + .collect() + } + + let updater = updater + .update_orchard_with(|mut u| { + for i in real_spend_indices(u.bundle()) { + u.update_action_with(i, |mut a| { + a.set_spend_zip32_derivation(orchard_zip32()); + Ok(()) + })?; + } + Ok(()) + }) + .map_err(|e| anyhow!("orchard updater failed: {e:?}"))?; + + let updater = updater + .update_ironwood_with(|mut u| { + for i in real_spend_indices(u.bundle()) { + u.update_action_with(i, |mut a| { + a.set_spend_zip32_derivation(orchard_zip32()); + Ok(()) + })?; + } + Ok(()) + }) + .map_err(|e| anyhow!("ironwood updater failed: {e:?}"))?; + let pczt = updater.finish(); // Issuer phase 1: build the AwaitingSighash issue bundle From 586e5f1aa8273cafdce4e2206cf64d07a37e6473 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Fri, 7 Aug 2026 10:48:53 -0400 Subject: [PATCH 175/189] Translate PCZTs across the Keystone wire dialect Cake pins the lrz fork of pczt 0.7; a Keystone running Cypherpunk firmware speaks 0.8.0-rc.1. Both call their encoding "v2", but six fields differ: anchor, cv_net, nullifier, rk and cmx each gained an Option, and enc_ciphertext became an enum. postcard is positional and not self-describing, so an Option's tag byte shifts everything after it. The result is a silent misread rather than an error. A Keystone parses a PCZT Cake built without complaint and finds zero actions in every pool, so it reports that none of the inputs belong to the wallet -- which surfaces as "Incongruent Transaction" with nothing to suggest an encoding problem. Translate at the QR boundary rather than moving either side's pinned version: Cake's ZSA features and the device's firmware both stay put. The ZSA issue bundle has no counterpart on the device and is dropped; it is empty for any transaction the device could sign anyway. Verified against the firmware's own parser, which reads two Ironwood actions and one signable spend from the transcoded fixture where Cake's dialect yields none. The reverse direction reproduces the original bytes exactly, so the returned signature carries back losslessly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit e5fa0a04c59044415dec5c74ca91aae719e497ac) --- rust/Cargo.toml | 2 + rust/src/api/pay.rs | 16 + rust/src/keystone_wire.rs | 489 ++++++++++++++++++++ rust/src/lib.rs | 1 + rust/tests/data/cake_ironwood.keystone.pczt | Bin 0 -> 4731 bytes rust/tests/data/cake_ironwood.pczt | Bin 0 -> 4720 bytes 6 files changed, 508 insertions(+) create mode 100644 rust/src/keystone_wire.rs create mode 100644 rust/tests/data/cake_ironwood.keystone.pczt create mode 100644 rust/tests/data/cake_ironwood.pczt diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d70689173..065ff0f4a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -37,6 +37,7 @@ csv-async = "1.3.1" vcard4 = "0.4" futures = "0.3" serde = "1.0" +postcard = {version = "1", features = ["alloc"]} serde_json = "1.0" serde_with = {version = "3.17", features = ["hex"]} sqlx = {version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"]} @@ -153,6 +154,7 @@ unexpected_cfgs = {level = "warn", check-cfg = ['cfg(frb_expand)']} [dev-dependencies] + chrono = "0.4" rand = "0.6" # Recovery-reconciliation tests exercise the voting fork's public prelude and diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 38b8e0c74..521182d3c 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -112,6 +112,22 @@ pub async fn prove_and_finalize(pczt: &PcztPackage, c: &Coin) -> Result<PcztPack Ok(tx) } +/// Rewrites a PCZT into the encoding a Keystone reads. +/// +/// Cake pins an older `pczt` than the device's firmware, and the two disagree +/// on enough of the v2 layout that each silently misreads the other. Translate +/// on the way out, and [`pczt_from_keystone`] on the way back. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_to_keystone(pczt: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::to_keystone(&pczt).map_err(|e| anyhow::anyhow!(e)) +} + +/// Rewrites a PCZT signed by a Keystone back into the encoding Cake uses. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_from_keystone(pczt: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::from_keystone(&pczt).map_err(|e| anyhow::anyhow!(e)) +} + #[cfg_attr(feature = "flutter", frb)] pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { crate::pay::plan::extract_transaction(package).await diff --git a/rust/src/keystone_wire.rs b/rust/src/keystone_wire.rs new file mode 100644 index 000000000..6c95dc344 --- /dev/null +++ b/rust/src/keystone_wire.rs @@ -0,0 +1,489 @@ +//! Wire mirrors of the two PCZT v2 dialects. +//! +//! Cake speaks the `lrz` fork of `pczt` 0.7; a Keystone running Cypherpunk +//! firmware speaks 0.8.0-rc.1. Both call their encoding "v2", but six fields +//! differ, so a PCZT written by one is misread by the other -- silently, since +//! nothing is malformed, only misaligned. Translating at the QR boundary keeps +//! Cake on its own dialect while handing the device one it can read. +//! +//! postcard is not self-describing: fields are positional and typed by the +//! compiled-in schema, so an `Option<T>` writes a tag byte that a bare `T` +//! does not. Cake's `pczt` (lrz 0.7) and Keystone's (0.8.0-rc.1) disagree on +//! exactly six fields, which is enough to shift every following byte. These +//! mirrors exist so the two layouts can be read and written independently of +//! either crate's private types. + +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; +use std::collections::BTreeMap; + +// ---- shared between both dialects ------------------------------------- + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Zip32Derivation { + pub seed_fingerprint: [u8; 32], + pub derivation_path: Vec<u32>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Global { + pub tx_version: u32, + pub version_group_id: u32, + pub consensus_branch_id: u32, + pub fallback_lock_time: Option<u32>, + pub expiry_height: u32, + pub coin_type: u32, + pub tx_modifiable: u8, + pub proprietary: BTreeMap<String, Vec<u8>>, +} + +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TransparentInput { + pub prevout_txid: [u8; 32], + pub prevout_index: u32, + pub sequence: Option<u32>, + pub required_time_lock_time: Option<u32>, + pub required_height_lock_time: Option<u32>, + pub script_sig: Option<Vec<u8>>, + pub value: u64, + pub script_pubkey: Vec<u8>, + pub redeem_script: Option<Vec<u8>>, + #[serde_as(as = "BTreeMap<[_; 33], _>")] + pub partial_signatures: BTreeMap<[u8; 33], Vec<u8>>, + pub sighash_type: u8, + #[serde_as(as = "BTreeMap<[_; 33], _>")] + pub bip32_derivation: BTreeMap<[u8; 33], Zip32Derivation>, + pub ripemd160_preimages: BTreeMap<[u8; 20], Vec<u8>>, + pub sha256_preimages: BTreeMap<[u8; 32], Vec<u8>>, + pub hash160_preimages: BTreeMap<[u8; 20], Vec<u8>>, + pub hash256_preimages: BTreeMap<[u8; 32], Vec<u8>>, + pub proprietary: BTreeMap<String, Vec<u8>>, +} + +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TransparentOutput { + pub value: u64, + pub script_pubkey: Vec<u8>, + pub redeem_script: Option<Vec<u8>>, + #[serde_as(as = "BTreeMap<[_; 33], _>")] + pub bip32_derivation: BTreeMap<[u8; 33], Zip32Derivation>, + pub user_address: Option<String>, + pub proprietary: BTreeMap<String, Vec<u8>>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TransparentBundle { + pub inputs: Vec<TransparentInput>, + pub outputs: Vec<TransparentOutput>, +} + +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub enum NoteVersion { + V2, + V3, +} + +// ---- source dialect: lrz 0.7 ----------------------------------------- + +pub mod src_ { + use super::*; + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct OrchardBundle { + pub actions: Vec<Action>, + pub flags: u8, + pub value_sum: (u64, bool), + pub anchor: [u8; 32], + pub note_version: NoteVersion, + pub zkproof: Option<Vec<u8>>, + pub bsk: Option<[u8; 32]>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Action { + pub cv_net: [u8; 32], + pub spend: Spend, + pub output: Output, + pub rcv: Option<[u8; 32]>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Spend { + pub nullifier: [u8; 32], + pub rk: [u8; 32], + #[serde_as(as = "Option<[_; 64]>")] + pub spend_auth_sig: Option<[u8; 64]>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rho: Option<[u8; 32]>, + pub rseed: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 96]>")] + pub fvk: Option<[u8; 96]>, + pub witness: Option<(u32, [[u8; 32]; 32])>, + pub alpha: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub dummy_sk: Option<[u8; 32]>, + pub proprietary: BTreeMap<String, Vec<u8>>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Output { + pub cmx: [u8; 32], + pub ephemeral_key: [u8; 32], + pub enc_ciphertext: Vec<u8>, + pub out_ciphertext: Vec<u8>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rseed: Option<[u8; 32]>, + pub ock: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub user_address: Option<String>, + pub proprietary: BTreeMap<String, Vec<u8>>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct SaplingBundle { + pub spends: Vec<SaplingSpend>, + pub outputs: Vec<SaplingOutput>, + pub value_sum: i128, + pub anchor: [u8; 32], + pub bsk: Option<[u8; 32]>, + } + + // Cake never builds Sapling bundles; these exist so a non-empty one is a + // hard error rather than a silent misparse. + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct SaplingSpend {} + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct SaplingOutput {} + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Pczt { + pub global: Global, + pub transparent: Option<TransparentBundle>, + pub sapling: Option<SaplingBundle>, + pub orchard: Option<OrchardBundle>, + pub ironwood: Option<OrchardBundle>, + #[serde(default)] + pub issue: Option<IssueBundle>, + } + + // The ZSA issuance bundle has no counterpart in 0.8.0-rc.1 and is dropped. + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct IssueBundle {} +} + +// ---- target dialect: 0.8.0-rc.1 (what Keystone reads) ----------------- + +pub mod dst { + use super::*; + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub enum EncCiphertext { + Encrypted(Vec<u8>), + MemoPlaintext(Vec<u8>), + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct OrchardBundle { + pub actions: Vec<Action>, + pub flags: u8, + pub value_sum: (u64, bool), + pub anchor: Option<[u8; 32]>, + pub note_version: NoteVersion, + pub zkproof: Option<Vec<u8>>, + pub bsk: Option<[u8; 32]>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Action { + pub cv_net: Option<[u8; 32]>, + pub spend: Spend, + pub output: Output, + pub rcv: Option<[u8; 32]>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Spend { + #[serde_as(as = "Option<[_; 32]>")] + pub nullifier: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 32]>")] + pub rk: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 64]>")] + pub spend_auth_sig: Option<[u8; 64]>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rho: Option<[u8; 32]>, + pub rseed: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 96]>")] + pub fvk: Option<[u8; 96]>, + pub witness: Option<(u32, [[u8; 32]; 32])>, + pub alpha: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub dummy_sk: Option<[u8; 32]>, + pub proprietary: BTreeMap<String, Vec<u8>>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Output { + #[serde_as(as = "Option<[_; 32]>")] + pub cmx: Option<[u8; 32]>, + pub ephemeral_key: [u8; 32], + pub enc_ciphertext: EncCiphertext, + pub out_ciphertext: Vec<u8>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rseed: Option<[u8; 32]>, + pub ock: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub user_address: Option<String>, + pub proprietary: BTreeMap<String, Vec<u8>>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct SaplingBundle { + pub spends: Vec<super::src_::SaplingSpend>, + pub outputs: Vec<super::src_::SaplingOutput>, + pub value_sum: i128, + pub anchor: Option<[u8; 32]>, + pub bsk: Option<[u8; 32]>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Pczt { + pub global: Global, + pub transparent: Option<TransparentBundle>, + pub sapling: Option<SaplingBundle>, + pub orchard: Option<OrchardBundle>, + pub ironwood: Option<OrchardBundle>, + } +} + + +// ---- translation ------------------------------------------------------ + +const MAGIC: [u8; 4] = *b"PCZT"; +const V2: u32 = 2; + +fn to_dst_orchard(b: src_::OrchardBundle) -> dst::OrchardBundle { + dst::OrchardBundle { + actions: b + .actions + .into_iter() + .map(|a| dst::Action { + cv_net: Some(a.cv_net), + spend: dst::Spend { + nullifier: Some(a.spend.nullifier), + rk: Some(a.spend.rk), + spend_auth_sig: a.spend.spend_auth_sig, + recipient: a.spend.recipient, + value: a.spend.value, + rho: a.spend.rho, + rseed: a.spend.rseed, + fvk: a.spend.fvk, + witness: a.spend.witness, + alpha: a.spend.alpha, + zip32_derivation: a.spend.zip32_derivation, + dummy_sk: a.spend.dummy_sk, + proprietary: a.spend.proprietary, + }, + output: dst::Output { + cmx: Some(a.output.cmx), + ephemeral_key: a.output.ephemeral_key, + enc_ciphertext: dst::EncCiphertext::Encrypted(a.output.enc_ciphertext), + out_ciphertext: a.output.out_ciphertext, + recipient: a.output.recipient, + value: a.output.value, + rseed: a.output.rseed, + ock: a.output.ock, + zip32_derivation: a.output.zip32_derivation, + user_address: a.output.user_address, + proprietary: a.output.proprietary, + }, + rcv: a.rcv, + }) + .collect(), + flags: b.flags, + value_sum: b.value_sum, + anchor: Some(b.anchor), + note_version: b.note_version, + zkproof: b.zkproof, + bsk: b.bsk, + } +} + +fn to_src_orchard(b: dst::OrchardBundle) -> Result<src_::OrchardBundle, String> { + // The signer only ever fills fields in, so anything absent here means the + // returned PCZT is not one this side can carry back. + fn need(v: Option<[u8; 32]>, what: &str) -> Result<[u8; 32], String> { + v.ok_or_else(|| format!("signed PCZT is missing {what}")) + } + Ok(src_::OrchardBundle { + actions: b + .actions + .into_iter() + .map(|a| { + Ok(src_::Action { + cv_net: need(a.cv_net, "action cv_net")?, + spend: src_::Spend { + nullifier: need(a.spend.nullifier, "spend nullifier")?, + rk: need(a.spend.rk, "spend rk")?, + spend_auth_sig: a.spend.spend_auth_sig, + recipient: a.spend.recipient, + value: a.spend.value, + rho: a.spend.rho, + rseed: a.spend.rseed, + fvk: a.spend.fvk, + witness: a.spend.witness, + alpha: a.spend.alpha, + zip32_derivation: a.spend.zip32_derivation, + dummy_sk: a.spend.dummy_sk, + proprietary: a.spend.proprietary, + }, + output: src_::Output { + cmx: need(a.output.cmx, "output cmx")?, + ephemeral_key: a.output.ephemeral_key, + enc_ciphertext: match a.output.enc_ciphertext { + dst::EncCiphertext::Encrypted(c) => c, + dst::EncCiphertext::MemoPlaintext(_) => { + return Err("signed PCZT left a memo unresolved".into()) + } + }, + out_ciphertext: a.output.out_ciphertext, + recipient: a.output.recipient, + value: a.output.value, + rseed: a.output.rseed, + ock: a.output.ock, + zip32_derivation: a.output.zip32_derivation, + user_address: a.output.user_address, + proprietary: a.output.proprietary, + }, + rcv: a.rcv, + }) + }) + .collect::<Result<Vec<_>, String>>()?, + flags: b.flags, + value_sum: b.value_sum, + anchor: need(b.anchor, "bundle anchor")?, + note_version: b.note_version, + zkproof: b.zkproof, + bsk: b.bsk, + }) +} + +fn split_header(bytes: &[u8]) -> Result<&[u8], String> { + if bytes.len() < 8 || bytes[..4] != MAGIC { + return Err("not a PCZT".into()); + } + let version = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); + if version != V2 { + return Err(format!("expected the v2 PCZT encoding, got v{version}")); + } + Ok(&bytes[8..]) +} + +fn with_header<T: serde::Serialize>(body: &T, hint: usize) -> Result<Vec<u8>, String> { + let mut buf = Vec::with_capacity(hint + 64); + buf.extend_from_slice(&MAGIC); + buf.extend_from_slice(&V2.to_le_bytes()); + postcard::to_extend(body, buf).map_err(|e| format!("re-encode failed: {e:?}")) +} + +/// Rewrites a PCZT from Cake's dialect into the one a Keystone reads. +pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { + let src: src_::Pczt = postcard::from_bytes(split_header(bytes)?) + .map_err(|e| format!("could not read this PCZT: {e:?}"))?; + if src + .sapling + .as_ref() + .is_some_and(|s| !s.spends.is_empty() || !s.outputs.is_empty()) + { + return Err("Sapling bundles cannot be signed by this device".into()); + } + let out = dst::Pczt { + global: src.global, + transparent: src.transparent, + sapling: src.sapling.map(|s| dst::SaplingBundle { + spends: s.spends, + outputs: s.outputs, + value_sum: s.value_sum, + anchor: Some(s.anchor), + bsk: s.bsk, + }), + orchard: src.orchard.map(to_dst_orchard), + ironwood: src.ironwood.map(to_dst_orchard), + }; + with_header(&out, bytes.len()) +} + +/// Rewrites a signed PCZT from the Keystone's dialect back into Cake's. +pub fn from_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { + let signed: dst::Pczt = postcard::from_bytes(split_header(bytes)?) + .map_err(|e| format!("could not read the signed PCZT: {e:?}"))?; + let out = src_::Pczt { + global: signed.global, + transparent: signed.transparent, + sapling: signed + .sapling + .map(|s| { + Ok::<_, String>(src_::SaplingBundle { + spends: s.spends, + outputs: s.outputs, + value_sum: s.value_sum, + anchor: s.anchor.ok_or("signed PCZT is missing sapling anchor")?, + bsk: s.bsk, + }) + }) + .transpose()?, + orchard: signed.orchard.map(to_src_orchard).transpose()?, + ironwood: signed.ironwood.map(to_src_orchard).transpose()?, + issue: None, + }; + with_header(&out, bytes.len()) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// A real Ironwood PCZT built by Cake, captured off the wire. + const CAKE: &[u8] = include_bytes!("../tests/data/cake_ironwood.pczt"); + + /// The same transaction in the Keystone's dialect. + /// + /// Checked in as a golden file rather than re-derived: `pczt` 0.8.0-rc.1 + /// cannot be built alongside the lrz stack this crate pins, so the + /// device-side assertion cannot live here. These bytes were verified + /// against the firmware's own parser, which reports two Ironwood actions + /// and one signable spend; Cake's dialect yields zero of each, which is + /// the bug this module exists to fix. + const KEYSTONE: &[u8] = include_bytes!("../tests/data/cake_ironwood.keystone.pczt"); + + #[test] + fn matches_what_the_device_can_read() { + assert_eq!(to_keystone(CAKE).expect("transcode"), KEYSTONE); + } + + #[test] + fn round_trip_is_lossless() { + assert_eq!(from_keystone(KEYSTONE).expect("transcode back"), CAKE); + } + + #[test] + fn rejects_a_foreign_encoding() { + assert!(to_keystone(b"not a pczt at all").is_err()); + let mut v1 = CAKE.to_vec(); + v1[4] = 1; + assert!(to_keystone(&v1).is_err()); + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index f83617c7e..2bacdff1f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -20,6 +20,7 @@ pub mod frost; pub mod graphql; pub mod io; pub mod key; +pub mod keystone_wire; pub mod keys; pub mod ledger; pub mod lwd; diff --git a/rust/tests/data/cake_ironwood.keystone.pczt b/rust/tests/data/cake_ironwood.keystone.pczt new file mode 100644 index 0000000000000000000000000000000000000000..def88923f0daacad9a3231160a0dcc9c3d0cf180 GIT binary patch literal 4731 zcmaJ_XD}Q9x3zljR?lin^cHmqqJ&ryHOlIu*JzO-dW~LICy25{?}8AlURLzFdi1sk zAz!{X^M1Z}X6~Icch2u~&fHhZCi>V|SXlU(M=5<|OI2x|H~_4*>nT74;NSIs=O6vQ z@n6yZ4*)jcNB7pBVWmW$j@#+d4SiG9QUvX5KjBWS`{e9WccIYFfVnd*X&amO`msxT zwT>(-E{^2r{I_yetpo9WL0ROu%m9zoon7NmPJ8GHGG+VfPuA56CzH%pYgKF%qx2Ly zg$yvXFzs6o6e0wA!ZWoA-jNY6k#lI1j;?$zO1v)X?v@OnjqD25Hc$54jP45<i4eaJ zzILEGg{*fo^!nk23CIBud{3imT2Za`M#hlNKd_=7#$&b>Tq{ctf&3P&0|*=@*Vbn( zb#&&_yzu}mz_t@=DL;g<mLpqpl78UpoFY~UK}zzrUnfL%y%mur1JK1k*8zi_I3mbj zkgqMH2OF-i>0Y%nv!1<pG?$whu?x6U7u>Fp@R_xOb!ZBI^na@OtzS+@DSzbzk6~jk z5Co|_Y1pOLcagT&GxMxumcP^%Q&9q?gmIZQx*xQVB;yvO9|fShNO{w^b1m`}<-(28 z0+vhjGh{+02QRt%zA^w-R&S#5qT_YqeE`pl_d<U@Pzod9axFx9zik|kCh#gwVz3pZ z$Sc7TmOc)-bmF_rlc@p+l+H%-Px`nTis&T`O*lF!B>SCMmgIEuNKj{bEJIhn5(gC0 zv9#{&R6Y4w4vO}uQVIC1uw(Z$gTM?7r>hV%^#^Hv!r>bCgZY*6_$nI_M`p4HHC5^L z{Ef#;hit9_=VI?y^;b&rD|ND5-jeKMJqz7s@9er(#0bKW33({_+R2x99{M){6dX+i z)p`-4Q>K+4FWOks>pXsFKlhaO_;r#$eC#cdT<Vq1z&kh!K<#J@jW(*c*7)bkpHH0S zX{5l;V#4azKkcw>9Xa+A_`O0E3iG!_PtDSus_yP9&k>s1+S-eIon1-eESJghOt`Qy zM~*rhNd!91L9aq*w?b!g)s>$);M1BnS=?oa+H?LUHEr(k=Qll57uw#;)~a|D&hy%{ z2;W75_SRiT0gYfruGnmq?ZwO`rAWTEiUHn=qz5OE8s8mP!(px<czDyY>fLBC3ZZV+ zwEueqyB`Nf@Seb2n~v`5{ZT%fw>s%gB{1Pq3<^ZD-K6=|Z0Qu4KrJxo0c<jF8rkF- z-q;@FyYif3=QyOz9yyJDN`F`mn<AV_9g;{YGk8gD*+D;N2XV&PfvPjCx%LIvkL=?D z7&pMNAfE$5Q9H7@;3IiGtj|cohHj^+$6y4wm}M8J*Q_!*$8{|m2&V1T(f#fzEXbtK zPP(Zv;$(^)h?RYhJ&mh24#-I)dr79MkXs=*2(C+W3pwcg8r7;6?>zU3aog~igGkl| zYlNSus)l;N6~ADq*L0rgF7ExZKwSaE!F4}aH}5Ia;yJLcP)*)@sP!x0pcp1f@kjWy zmq?mW{0KxI$$jYtTE})ON{VFRrij-5{nr;XXKn#0P9QY+-F``!BDylX_JS)*GinXb zpJ^giYzr0CxCS}8v_QpaSZMLN1UN72AM*ySc!}fCTMS6N>zP-X-%nF5&N495mu$<< z^sNR{856142L)a^b&dLA^t#vhB?9WHhHVICm2<h9xZgau6k@S2a{sJuTp~x%8}@5w z9gcX0R0t0=UYjc<>h-iqev!!-fVWCCpb7V<t1?di5XMmz^B!@<?g6*Ke2Y)Gc&Igq z)kPCMUjKfiz1;9L^fie9o<?^Rkvk2r*>a?8uvZ~~@SA4e30m}nF4Jb7tO9MawB*OG zvel}XUjpao3MU#Wq8@m!EE?(pa|B6&f%7qF6Pho9<Ya+kV_;K0Q)!i)bS(z*C%iX~ zVy{r#(c#wbNZM0Qi>)dfH3a-*Xuz!{Y}dIP6YGRW^=9if((Gfx!2CraA?@;l+{Qv^ z013c{HrpNkCuA288qNqLP1l%{vsHXDj67mW92h}j?~DHPZUD|f?un{l<G_|RtBso< zHE~&a)sxoOx6qil>*Eb7Y3kOgGCm*GuGZ}IedVUl_6|1-nspr$e}bQr(}!}F4CZ3> z;Z7w1Bd~6ZG@0)h%ch?`o07qWBf{bf@aCl#To{L#R+scp%eVV4T}|wvW>U;gZ!~he zM=>Au-3z=Z`_)I<8Oq1-4M9&dVm8KZl&bCq2XOsZUT}2F{<WTOOgVVC{Pp-X!DC8t z2~qd$5*jXZBah>wg(V(A@YzY0wVR!-xr9lya?8DF+`QwvOs<pNd2ybx9!pT>0fw&H zUO|c%uXty83aQMuc@gBNn-WXkTH9%=ksmZ%rn9mlb<uYF3m)O$b;$V5=lRbtFtq3y z`-rJXFvYuqxF??;ZwEk_b)*^&=pTJYsK>m`YleNtbWFH;9}mqw2`hrn4HL=)PA3Jr z{3QuXU1};d1e@T?^&*g|O@r8J%l9&CyYui*=M>rP<{~VqzK{E^8T!upOEkMADP4^$ z48~6MFU+t5G$VQ|;woP3usE;aK02|BxbQs-F^m^PpLS&~!!M6vxsq%rG7O-F<)7={ zDvHL|9cz(k><fYWp6A|)Dx@*vbnel^(oO3sr`i32bBAvpcOu7uT3U<K#BoK@i`~DS zCAaT|ZqRib?_5Tp1m2u-7I%ZY1%{C<nv=pYarYKMx4<@`v9clLSQ1|rzrm?NP=&Z9 zn%<z@2rYDfuA-r}O;Z>eb6K4eNotVq#B-gWJwq#vjeSHmwl;RbNwkgR4i_FD!H`lV zoj%*m*Nw$_lpPCuJ%i=ZVKK7!nID9#5C6_PasHPuUoD}b(BiunMp$fb_B3?%rZ7*` z<O_pjJ5G=A$=IuBKfG_f&Cllu8*Af)baBzVrkfpZt{;Q-j2J;BD0Rp6;d<UlvfHS} zm}X0fH-p5)rh!-*P$vjoBL5RxG$PgaAdvSLNT3F<x^ujUQh*w;5`7yq`J-38K8C#W zuumHGnQ(-(#jW`<1jl&^X8$uth$#84U1^-Et*HtynZO6=1>x2EOQmz(M0@3@qg`~j zbJHyXW5tBcpOV6-kf(3{TXX=2EK%fQ*}<RaTGL2f7`G<S5dm?Ml(k&U@FbL`$G9K> zN)v0nqM4yK_|k6GtocJy+h=`XnugQi{>DXaiS=4O;C+)mGs!j!3|T%y|L3h6&&~oi zhfnsm4+u==8T%;*4S+SYmp{nveayu{j|fi5QGDl@bxS%2OQIdl?$8>Wm?SJfoOPs% zZBnXef9bF7`>a{Co~oFv<nAd>8%l_EhqMoI?)np=EGTrfm;wiU50?ilDGFpsehCg3 z3PZCn(&<t7C7t#1V1{QpAY#}}x8ov!Hon8qPp(mEM$<|&QQz)!lRD8Bk1*UYx*C?U z^5N|vKql<PN)-Qucr42yEl-r<u}WQfG?)nEQCb@xB`SWwT{DF9bKynmgR|qRU3{O+ z5A7{^8Wc$OTH&V+Yw9AHd!Uf+{lXy#&hFCP&>m%c<fG(SKgW1Hd}E)cw#n2%1-SYR zC>jbx@Dq_#?SP_)2<%#1Q94oft7|!G;9Rql9{jCGN^s55TX+EaidjIC%z@~K>Lpe* zV@_O$>bxc`!G#rd$g(AP2wOdC6TZnA8FJWk0dfNmOWJ!}*~pI}jBSYi@-pV0P+v#b zLs{Fs*~WkK%k?E3XAb_0M@JOKZcO6ie&hL6sZvR)z%A!cRlAe8Kx*RX&3O*S8UNNc zo0n6H<#}(?`IB(Xi95`l;p;ga%A`^Q8mQ#HS+M6bwiBKfDVvAErWfqtBmhFgv3Ee7 zSlj%4XlCOW({sZ`vL=~sOfXEv)0Ew_RC;Z}?Ulo*?5&;DtwI1Ui<DdY<~dzp=U2nN znpBnR^*%;mlbkc<Bh66LzTKnNg5pq<X)z|UV;1xd>=%jqbK>G~TbxB{nhc4Xyi&oD z$JTcO_(HPbv%KeIaH@o6yGzoy>{J&LjhL4?vp(4(H-dvF+#f^(Ha4STtfVZTi(Z!B zywtU}Ej<h^kJ_Y{<(VO!#z`QTg)L!T)d1hXB!8QGd(#%@?j?(cgay?DfW%S4l`T|J z!^^vM${sv)#jR}=g0!u8^$(umul5TQOzb921?)u~LkYXah87uAX8N=^RVWmKXcoVj z*$(&%NWY@4tN%tAHhRT5v@>-!)m|YF*-r=nF<*NI{GpW^x6m-T%xHtKhXS8gDOyFF zh)Oun#@}w+ZoR{I9odX2T&X*3!7M-N%=_-Z$WVOodkmD1k6@aO;aRk)>Vc#by^iCN zE}a$~7C1_Wd~7p^R78r)SM20Y8*s>_z(t8PUD&;mHt|9R5}FxJ?)j<+^g5B2=P_4& z<&^`K-@DEqJ-J`RnY5Wa;I&Y`Le;|6zr({y{Z%PDX=-oYVUqIScD$Pwr@Y47V|8Hv z8v^-B8Tnp;V{d!peZO(G6*1<A{(;P6KS?0~UErSK#{i9t*1r284e9&fPY^!Xi2qcn zw9!{Yw(C6C187`l%!;i?fLblR?{^%JF~gtzoddQ^uOqJqFF!L9P;w?OHGtdkT8s3S zQsl2xovxU+X_#7rxCwD}vn;Wo*&!W<?<}x5l_rBhuA{rF>?oapR-gC~e?S$f4>#c0 ztL9r^RfAOe9H+60j~dZ8(+tQhrpZDHuCR=m31h)C3agu*<CqLz2hPhc3}3?P=t7li z_TX5ji@u9$llT;LC>7|*ZZb66YL6Ewa(KXQ9sRHezG`UZO>}p5o)v<=E~PI-Q0~7E zLpVE=&qg#CFKoBo(_&nf8L*kD!3qjLlVOaVVNCvPT?Pw|^;Mh_`C#Kkzg14JQ<p;8 zcAlt7n=yi84HXW4KkIPvHmF0~p|?VL=d~v+aif3|$_L;vVFn#q{B@owFM)j`f<VYH z@?pN73Sj5Ok2^Wx8N7fa6b?soB4{q6E^}ijQN(JZcv14RQlsi#a71}ZXKX1>VQ_FT zVMNHk^^XJ-{_|^z($Il9g^*}&U~ww_DxdNb$4i^R0XRzz;$iOVc7p_u$;7Nsvo~jF zK-0|+eMWz9(@dBHP`BQ?;CZA03Y+a;yV?J>FYH#ix4x}X6T|jJL>m^As-Q`|{?w?i zslY*lwkn)*u&T54hQDWU;z0E&UbiAD13R@kL?Ei&L-kA*zZ%(pqk^<oEgfll+bx=B znL)`ieJPS*WW#BY6PFiBlf^`_knCj<!uYqVj?tJUis)7}aTw9^8DyQLIp!qD$sax* zB$_;FNa+{Y-K3Mbeqm4iPp;NP|L~cP@eQhJUx1d&Or5Sa?}xooV77&bS69(>vc$KC zdH%EdqUYKI(XUBwq9uPNU%hei<nS-uZ09b;=o@^onj^!1TVbeJNPL|<pnqdHXMCY} zA!Ykm?n1sk%rvGi)%b?aoKyk4i{Q21`nec$vzImj97FvQN4$_Dw#aTF5}+{Yh75rj z#*qy=#z`vYsFSufy@<;s{5}}%briNcxA^eps+1xRJ6o;3CZpR@{H;2WfxJX2S}O8p z!+_wV2O0C6gA4(x4&rO8@hYa+>v+T(mgM|NKb5VF*`&oO+&YzD5U+0$*9`m>*?ksn zVBuOk6sV%|6??u`A{&MKlZ>_HyDOQMUN&PMDXwHYQHN%FREeYG=I0&s%DBZI>zYP} zp=4?_IMLA^u-bjBkGD`ja0&7Id}?}o{C7!lbvS|5(EmFwHI-Y?)kwFv%o>Q~3pfvJ zw>1ujqPR|ojk&!B6HVM$3DYfFY(%BcZ12Zhk0^t-jud;27;&zUcoQIyr(iojOQME+ z<IJ4MGx9mEmeERRkJ|fB!MZwF@!?uDu&irxVCeY3D|2aOHz?G<i@x*YM7hlKD%xyG ztfd7?ogJ6Ecu3s`G6*V^>~_3?&Uc*(JeY&V4^Qwc$ee)Pu_50t9Ip#anBYbmLozab zLX*O`cDYvh0cyi(zKEy7Wa@-7oQF&I<rgky2vi$)-v|1;lvI!Y$^4M32%j9hSK0$O zfb}wJKtIPx^KbX1cyTBV#^8OV4C-XMu#>j>%t~wZoDp(D^gr!J)c?fK>epAXLIEj* zDPV28Wz01Lb;rWH$uR=2zz-Mf1WDRhfNuwS_kN6nWdVtbToDYD2T&pD*kF#uj-3~& tkOAL)ntu-xmJHv>x0$<Q^AIT`CAgNuGYan#^^uso1KUj1p@SZZ{{VeF>UIDC literal 0 HcmV?d00001 diff --git a/rust/tests/data/cake_ironwood.pczt b/rust/tests/data/cake_ironwood.pczt new file mode 100644 index 0000000000000000000000000000000000000000..ba1f65c637e9dd7963ccdf4313903eb3527555b6 GIT binary patch literal 4720 zcmai2_ct4W8cpoI#cr%nd({j@jZ&dCYs6N2)~Xh@XYIWeHA3yJC`IfMwP)<wD=4L} z@BIVsJLkLSo_p@k_q*qNrDUv!1pol>GLMq`NSCToJF$U)wd*NhIPjnP-~E5{|2;sg zAKhDjh7}XMJ8q{-H}p(YN)a@#eT6y!_et5MZh|47=gu^xtgYYc#VqO8IxsUkJCLFC z-^yCH4#f2ZW|84Axv%c*8jW(;!A_9L+gE?Gu2wi0rMFtEVj>x&rqIcxz@dd{pK_2O z0mvgGQw#qcDbW%cyB5jl%IBhl>$2`{iLlv-t`IG=B#+IgKL3$$vHPHFd&*PjdN+Nq zFK#HmED*u_G^(Z*)oN#G1nv9-FZy9LW>dkrvh)zZXWlx1z-Dx5eb!P(Yc|aj2Lu4O z9Z^g9!3?$R*&35{17GJ9044azN!z}iP?_~sM5;7U2k%@P0&!#yCwoD*wu~NZxWb}+ z)y~9n_Ttf8Zf5u{@J>x&yF%Q1))L;KA@tGjslvB@S#8Dql@nb0jlBRcwDP23mrl=F z%1+nRqmoJPQcF}>5u6;#Y1-&^&_bMqQ;>G#kM1JjN#)8l&sUHQGeYxQEX~i53K}20 z<m&rM4_sNjiNcMF(~k27J~P@2`T0O0gvgL>A=LeC?Qk@KTX7PNr65UG2@$vOw$G&% z+hv+e;Xj~oGL(DL$JtOsCt+aB-bpUe@5sC)tDQ%TI@4tyy84wcAfE=%yt7sD;A1{0 z+M`Ut=e5L&+0zJw(9@r;LQT~kr1S`eYupazSIXn6tc4wzNE=jDq}KB{9xolTy6~Ti zzF*Z_Dao(Y&T@WBybE|1vdh-lb*+FAfFtAcP;#}CFYny-Zv4sFoA9f3!$qb{DnDMd zv82_x|Im8wA?5z-B!BqWi$AH<GmV~Sa1@BzQ6Cy@RBNsA%a=Q!ILlK{hMz@;)~|os zVcj}%=*9Pag(?){Yl)hgr9D;I-B+3;FtM?*6Z1T~lEPjtli{9lW@U;PbuttWaF~N# zh0Jb+%;u^oJ+sH7F>5lvOBb=@_)TKc+~db*a;7G@y_v09@g|J>wMP-2vpCJIo3=a} z!Gv6~-YVORo=Z%Ycx@RCx)n|fiYGC;JFd=vyMQyonwC}WMuSiYHPfd3-y>N4*w_O1 z_-0zPv|sO!@>#vqNOmeg@t2}75R&yK)wgC#yT}-3j!E-pm44I6Do6ju<`~a~`xGn3 zK6UoUaqLst!*b{p!BonScw(9UODc;Fx;a~@6ZQ^FjegCg&);rj9|y>=0f_;79}tMx zlEwxd$>{<<BMBP19j6{c5RhW#U65|G^5h)nwM+nnrdM0%yN8efqaGW{ruvAZ3043g z`yOi=M|B*SlR)~CR7F0wLSPV5m+BgP(D^m8RW;6O?i0hd!7)3bj5A<_kFctSYQP1r zV5!$+p7AdB{W5=D0o2}QKS(F<DdXZfsIE{|&TFXkEAXHgE<*lC=(Lwmia_iLOcud) z=?Y%Qax6-WVCEu^()#_^2RvtH4lRx+(Er_jNsuhEGQ9SJGfN|K4cCuxB1Uuz71+22 zJ-ReU#j2ZY@;duFE$bcg1g?0BVbhrph`;NZSDxQbRVmKWH`SA9%g*$vhEN(2D%%AH zTsd})`eJmu*Z9Q!>nVq=31pOVxth4%JUABu*cQ2dRyQt@A?OVHwXzOJJc28P1{$x; z<P&sz+9bY6rw?SbiZ`GM_NS}TPyZ0aQWo<ZamMU{wjsQWPdK@$)QQwY65L<^ex$YB z@HFH#F+Z+)cO;=3HK^HQq-?NP-k;!`M&Aiq<bw|5W}b{ZO_G$v$F8!~s_0+*=jaMY zYD&VMj9wWu%o*+gmV|)jqtV9HUjoQT1IET6CcGw6$~kG8^kh$XZX85kp}3;Ltlkl~ zC!ZEuRyL~h`$|(oT1!~3b2lc|36APb*R7@4#)Lrmi-Lk$<psHog)o0&pf^pnTgIQ@ zU0_HU1BfI|eNNU!;mI)ah%sSc1c|jT@-N)64{}db3>pWvtXQmFeW{4b%B!BVzP^P; z$6g<AP)bp?PL=U`t8}$yr|l~>eYUf|S<tBKnD`U)oQy7nqhv6*4`(V76b`s8(qOt{ zD4TxzY)Tp@0}&cmfIBa>;LI?@xVof^TE5+X>0)dLGnHg|dZV7>HH!JD=T_iJ(XTer zPG3HTX8?Yp9=$PkqgZt}IDq5J{DQq(=C9R!WAeen<*&!D@gGx=iHo>xmr!$>8M+@I zEi7>hK+aCGtXyqv%*2hOlv?gZV&@&+WpbYE&Wmx6^;m#24=}XVcJh)uxWzleQ%EJ= z&5J-^o#Yt0*4j=J_58r$GVPTW$&0qzUm4+kU55<cyr2IJg}{oQv5lAr2a&%kh<)<u z@wPvdNn5hvfbP+Egj)35yk_`!Ovi+)*YVKolhC4!xnTn7fa$~l=fA|EDN9YI1`uOB z*<J)PrD+f=b@^U;ZFfH7(>Zx|yO}U^iqGS|Yx=&k{t}HY2?`fObN#Usy$e$;e~s|o zir9)5JIqciIFC+j!!LZ!f(_yX(5GFQ%Ndu)@LUPj6KQ(z!t&4cZxuyj>khTZRJMhH zeUEdm1Z9%waay;iVX3Bd<<snbfw{vsk2{g$AWhB1X`<MosKxHzP7>Sqf;Z^8jd#u? zFnli#S@XNW-2#IMW{pXq=-7Mnz*|t8;8@uZax9TIi%<VlKd?f~0!^piZip7VKUY@Q z+@>xJiN37Pi6GI>cjUg#&z_-?!ooTt9a|f_;2_*aa)k+vk6=hB6HlM*=Ig{@Kgy1Q zzn%fOcbJbXe&z!s>%+eDOq~BE$XAVTC^Y}>i4hXrn>`Jgy(!ESG5$g?(T?3CbTanp z*$=N<FSGMGg2vidK^+`4kI80-tINkAT|)+N2};djeYl=ylJqvRF}m48{LLT{kx2kR z9p(t7P2hWCgGQwI90c(E0`u44R(FmUQSeg%SE6nMCx7&+)kl+c9`;G0J`;?Pw751u zhGIJ{!R>wq3KAyWwJVNOwl!4&C*yg6y<psWKgl$Xn<&rxG_<qMc5a$^K#Zu6*;A5? zDdg#!|Mno@A#)^|Xm-#i+SXJOXNIi_bhv-41Vt?;Q$`|6!+l%;Mjd0dqLHpT_|kUO zwE06~+h;vcs=DLh{>DXaiPc*E`zAdm;%#O)vV4Z_&s$gSodqm*@9b|M5SYv}wo`U$ zmXKb)K->4x7Y9AU*d<4ConO{1XzeWscR0F3YOJFZ0l-+R2xXhZ6p{YYU)%RtvuIrv zQ5lKdQ|vaBAj=L(AL88QCsav5@M<wR1Nc2m4!ESipC$1n$bTpl&CEcnOYWO^*2|3< zp6P&!Vl~~43j^DD4?{k=M5Y=}E6zlIyU$JRM4LataKUM7n9ItCw}*h4@E0qQd=p|Z z%!f4GkqXDkb!kx$LX3N9ZCs>?*acV35cbc77by=;4y(3tebPU)w&bW$V3}+ApVllX zix94XLfZEWhu{o0=kA8~NTVZfMUVP9hU4KIyHwRp#tus0)o)<YPym9Dkhp3G97%|8 z+v0-Kj<j1{%Ta~onx6FFZ9P)V&=|eV@JC-U@k@}}6aG-S1Vl09#CE96YtZ0dSW*Qq zTR?`e)Uq}+HaQ}K51TH)u8?5~JNGMVxiN&1HQ`?#hTIdX>u@_5OS>2A_-{VhzWC$J z!GD+00fn(06aTp1cs^CCSW?P=%P~~d?kL8ek}!I6o`Z41yS2&Y;gDp0-kW&-Bur!C z4s&PldQO`nu~eTLCb4fC<nfI4gu6x3`eCr?1zQ*~kicN<9Y{OICVwB6**M1d++dNk zNxB;o1XuPjVe=@JT3c{^Wj`u&Yb$vx?~lVQ>Ds<|P8-nq)u68?MfrNYj{(#q>qPNL zBgCX{_o%g?IK+5bl#%q98NCDlMeO#Rs5s09dr^uyUHm4mRAA(>)g3>cpiI~-&pBxZ zWqh;kCCOVh$_w#E%*&iv?`+{4fx#254<h~>n~~9$k`~WJF3WFT>R8#79)^@hZqmtc z&yY-G$CJsxmoTqtKyTm@zs<b7Xo_?9l0<?-1M7hxqDZ027Rt!s<=r|ZcW&C^);4kh znpWKU2am8<`-Snwwv#6Ob|MZT1YKi8i}cDfeVQD~<nn>ki{DIb2K@M?UQyN6e<KJT zz2X?!nL3+luaJZ8$NPhsu08z!&`6G(s~caYw?WxLKu@a_ETfD?#O-O~Zntf=-r>27 zY(^KZ)E%~9mY;OyeYa<zFTVIa2F}MrFwRDEFIrdiK$DAJ$8t-RPKyllAEiM*wwXaI zBE;k>c5<in*=3V6L<lvU*}Ra}af15d8tF}L`6>wXI-#b=F=t%ml|7~JyUrgyxnIN> zwHVzqYGJ&EDut_mhldsWtCDw8Ro}eBB<8>EcsDIZagDpjV$b$B82XbU;=Mfk-uB4* zexqzlBFqoH1L?=U5`sY5fIWkc{_5$iefLA^QujfhpuF%Azo}9w!>@>JmwC<y@VNGv zC2J2qm1<hw?^tdl`ak<S2dtT%N1hL!zNW<Bq)Z+vAeY0nCdn;@@L$O~9Z@ZlP}K%8 zW1{M286pAGLs|^)SwL|LbvnIlM|W4*Q5rst9?>D*fC^GCL!W)Gns<Rk6<X<ioXR3L zYDm{iJs`W7Dg(p60vIt7#6V``S2sPzG3h?`9G73{zl7G&hA7qSWdKeWeHK+G@yKaW z%CM8&Bv`iP9uHFZ@PN%K>R}IZ)zHk7;O68sD+qgCN>_-W*nc02aB?D>4R0=9*lxY2 z!8k9|V=+-d<mG=R!5KP38U0wh^cNiJt2o5-Ax4Y7s~n!E&V@AX+>w*kWBAAF%Iti; zR$*jqF#Fg;FZuG$YY%wBMgawk7szeQ1U@wX>oikd0{=t^g_2_ALVY~sAx?`QcXGng zd4NYKZ1&~^@LYIZ=EhKhu;oPYqQqy#MwPvw@bcu&m{RP*pr9av@Zf*&j|33_0OF+~ z19S4hQCy(n6uMPjr6&%T)`J5X%sGgMxv$#|;@rj)vx3cD9G(76H$U_k{2)y;q4pr1 zdaHux5&9@B);^s5U;9F?m3!;k$~DofUxc;bfhqDDRO?R-`<e>u)oH52C<d!KOK<pk z1}6?wp5k^Zpwh8Ys)P9>+uc>pRPd^i{Wr=;JC)Lrwzu6Pc^2su%+r^`>4w%E`Z=+A z5!6|X<O@lj=D`eqyXqK>m?H^qMG}S)EuX<wi5g>$0vvo{<AEYclLi#N0o_g7nd=vJ zME~rnO>_^RX&K(2n)dl=I8D`PYx92CDF$Sl3ww4IT_=fudzj}tt1o)4#UJ&W<R(hu zSJKrRM-O(t(#>|RQjDJd7t1+Pytfqw3WY@1NdtN}26ILi3Kx<#k7Y09>O)PU`%;W< zXw69EA-f13tF51l(Kmak6QD8FFEPXmSt9f77D9e<<8J5>gnk^^ply_>e2zM4Yts$C zOvLMh(_BYlxp9dNZ>~xzaI>-2>S-{zF2&udf#}IfB%>rFZZ`DsPkNBi&)G>4;Oao$ zwi?f3^1Y5nETM@`pY&2#%b1K?9K)<q@CR}G7I91=Uy<EsVfyAS#X|wg%3rbOYsIrs zI6p~QTE4rGTIyyq<dNV=v=eq{q(zoEIBb62L9dLP@3E|@ryEG5L_rc9+<>dy$9lL6 z1^Aax-_NHex5s~%6jq1hSq%KX<4{q$240PHi%GA6iN8Sd0K2WR*yP1^f~-vKHJB)( z#!9$O(PASiZDxBv`g%kOymh3|bHspsg~XizgFOV=`Ir;b<r-(^grAYkakh+B!g^HS ze+tsk2E>JFQp2;Z$v`3F1Fy`alw4sjzb?AYj}zt6&#P#%B>+nc6xut^cX80V52R33 z2<h#31Fg?GC1fxMjTaX0QII(SzhgzdUpQVDoG`|TGJ>XOdWR&2ZS8Wd@&Q$cQ+*Im zg-F#1W;hO)?#nNnO%bRzuD%a+cgZR4{ge5@SK;0{xUaMZuz~AkRKR}rljh%UOL1Z_ zYK;E-2x-*GbYUk=^_ivS>Nx}Sgz$gGM#S&L*Yej_(L#Pn{V7mwyG8UhJyplTyU8(p z&wvjXZ1{;<fNux7_r45+W&Q~YoZ<A72QWdYm>~AWj-3}N&;g%)>VJ<B=5(Kkx0$=5 e^H51c#SBgRXXIWbY9rBk2R4~1LkB(Nfd2qJsOoG0 literal 0 HcmV?d00001 From cb978e34715a1ff428b37dcee2b1c97af44cacb7 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Fri, 7 Aug 2026 20:53:24 -0400 Subject: [PATCH 176/189] Take only the signatures out of a Keystone's reply A signer returns what it needed to produce, not the document it was given: the Keystone redacts prover-only fields, including the Orchard full viewing key. Adopting its reply wholesale therefore loses data proving requires, and the spend fails at the prover with MissingFullViewingKey after the user has already approved it on the device. Keep the PCZT this wallet built and merge in only the authorising signatures. A spend that already carries one keeps it, since the IO Finalizer signs dummy spends before the device ever sees them, and a reply whose shape does not match the transaction that was sent is rejected rather than partially applied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 35b53610e2c52ab9ecc543b2256534c2a29946d9) --- rust/src/api/pay.rs | 9 +++ rust/src/keystone_wire.rs | 126 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 521182d3c..b710f1208 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -128,6 +128,15 @@ pub fn pczt_from_keystone(pczt: Vec<u8>) -> Result<Vec<u8>> { crate::keystone_wire::from_keystone(&pczt).map_err(|e| anyhow::anyhow!(e)) } +/// Takes a Keystone's signatures into the PCZT this wallet built. +/// +/// The device redacts prover-only fields, so its reply cannot be proved on its +/// own; `original` supplies those, `signed` supplies only the signatures. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_apply_keystone_signatures(original: Vec<u8>, signed: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::apply_signatures(&original, &signed).map_err(|e| anyhow::anyhow!(e)) +} + #[cfg_attr(feature = "flutter", frb)] pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { crate::pay::plan::extract_transaction(package).await diff --git a/rust/src/keystone_wire.rs b/rust/src/keystone_wire.rs index 6c95dc344..342a110ba 100644 --- a/rust/src/keystone_wire.rs +++ b/rust/src/keystone_wire.rs @@ -452,6 +452,82 @@ pub fn from_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { with_header(&out, bytes.len()) } +/// Applies a Keystone's signatures to the PCZT this wallet built. +/// +/// A signer returns only what it needed to produce: it redacts prover-only +/// fields such as the full viewing key, so its reply cannot be proved on its +/// own. Rather than trusting the returned document, keep the original and take +/// just the signatures out of the reply. +pub fn apply_signatures(original: &[u8], signed: &[u8]) -> Result<Vec<u8>, String> { + let mut orig: src_::Pczt = postcard::from_bytes(split_header(original)?) + .map_err(|e| format!("could not read the original PCZT: {e:?}"))?; + let from_device: src_::Pczt = postcard::from_bytes(split_header(signed)?) + .map_err(|e| format!("could not read the signed PCZT: {e:?}"))?; + + fn merge_orchard( + into: &mut Option<src_::OrchardBundle>, + from: &Option<src_::OrchardBundle>, + pool: &str, + ) -> Result<usize, String> { + match (into.as_mut(), from.as_ref()) { + (Some(a), Some(b)) => { + if a.actions.len() != b.actions.len() { + return Err(format!( + "the signed PCZT is not the {pool} transaction that was sent: \ + {} actions returned, {} expected", + b.actions.len(), + a.actions.len() + )); + } + let mut applied = 0; + for (x, y) in a.actions.iter_mut().zip(b.actions.iter()) { + // A spend already carrying its own signature keeps it; the + // IO Finalizer signs dummy spends before the device sees them. + if x.spend.spend_auth_sig.is_none() { + if let Some(sig) = y.spend.spend_auth_sig { + x.spend.spend_auth_sig = Some(sig); + applied += 1; + } + } + } + Ok(applied) + } + (None, Some(b)) if !b.actions.is_empty() => { + Err(format!("the signed PCZT has {pool} actions the original does not")) + } + _ => Ok(0), + } + } + + let mut applied = merge_orchard(&mut orig.orchard, &from_device.orchard, "Orchard")?; + applied += merge_orchard(&mut orig.ironwood, &from_device.ironwood, "Ironwood")?; + + // Transparent inputs are authorised with script signatures rather than a + // spend auth signature. + if let (Some(a), Some(b)) = (orig.transparent.as_mut(), from_device.transparent.as_ref()) { + if a.inputs.len() != b.inputs.len() { + return Err(format!( + "the signed PCZT is not the transaction that was sent: {} transparent \ + inputs returned, {} expected", + b.inputs.len(), + a.inputs.len() + )); + } + for (x, y) in a.inputs.iter_mut().zip(b.inputs.iter()) { + for (k, v) in &y.partial_signatures { + if x.partial_signatures.insert(*k, v.clone()).is_none() { + applied += 1; + } + } + } + } + + if applied == 0 { + return Err("the device returned no signatures".into()); + } + with_header(&orig, original.len()) +} + #[cfg(test)] mod tests { use super::*; @@ -479,6 +555,56 @@ mod tests { assert_eq!(from_keystone(KEYSTONE).expect("transcode back"), CAKE); } + #[test] + fn takes_signatures_and_keeps_prover_fields() { + // Stand in for the device: strip the prover-only fields it redacts, + // and attach a spend authorising signature. + let mut device: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let iw = device.ironwood.as_mut().unwrap(); + for a in iw.actions.iter_mut() { + a.spend.fvk = None; + a.spend.witness = None; + a.spend.spend_auth_sig = Some([7u8; 64]); + } + let device_bytes = with_header(&device, CAKE.len()).unwrap(); + + let merged = apply_signatures(CAKE, &device_bytes).expect("apply"); + let out: src_::Pczt = postcard::from_bytes(&merged[8..]).unwrap(); + let actions = &out.ironwood.as_ref().unwrap().actions; + + let orig: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let orig_actions = &orig.ironwood.as_ref().unwrap().actions; + + // Every spend ends up authorised, and a spend the wallet had not + // already signed takes the device's signature. Dummy spends keep the + // one the IO Finalizer produced before the device ever saw them. + assert!(actions.iter().all(|a| a.spend.spend_auth_sig.is_some())); + let taken = actions + .iter() + .zip(orig_actions.iter()) + .filter(|(_, b)| b.spend.spend_auth_sig.is_none()) + .count(); + assert!(taken > 0, "the fixture must have a spend for the device to sign"); + for (a, b) in actions.iter().zip(orig_actions.iter()) { + let expected = b.spend.spend_auth_sig.or(Some([7u8; 64])); + assert_eq!(a.spend.spend_auth_sig, expected); + } + + for (a, b) in actions.iter().zip(orig_actions.iter()) { + assert_eq!(a.spend.fvk, b.spend.fvk); + assert!(a.spend.fvk.is_some()); + assert_eq!(a.spend.witness.is_some(), b.spend.witness.is_some()); + } + } + + #[test] + fn rejects_a_reply_for_a_different_transaction() { + let mut other: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + other.ironwood.as_mut().unwrap().actions.truncate(1); + let bytes = with_header(&other, CAKE.len()).unwrap(); + assert!(apply_signatures(CAKE, &bytes).is_err()); + } + #[test] fn rejects_a_foreign_encoding() { assert!(to_keystone(b"not a pczt at all").is_err()); From 0904fc48bf8124176887496a959351bdd188f62b Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Fri, 7 Aug 2026 21:45:33 -0400 Subject: [PATCH 177/189] Expose the fee already recorded for a transaction decrypt_memo computes each transaction's fee and writes it to transactions.fee, but fetch_txs never selected the column, so every consumer saw zero and had no way to recover the real value: outputs the wallet sent are stored separately from notes it received, making the fee derivable only by combining three lists. Select the column and carry it on Tx. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 5afa3969c27b40064bd7d756c528483dcc418520) --- lib/src/rust/frb_generated.dart | 26 +++++++++++++++----------- rust/src/api/account.rs | 2 ++ rust/src/frb_generated.rs | 4 ++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 2488dd698..7763dfcbc 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -9753,23 +9753,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { Tx dco_decode_tx(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; - if (arr.length != 14) - throw Exception('unexpected arr length: expect 14 but see ${arr.length}'); + if (arr.length != 15) + throw Exception('unexpected arr length: expect 15 but see ${arr.length}'); return Tx( id: dco_decode_u_32(arr[0]), txid: dco_decode_list_prim_u_8_strict(arr[1]), height: dco_decode_u_32(arr[2]), time: dco_decode_u_32(arr[3]), value: dco_decode_i_64(arr[4]), - tpe: dco_decode_opt_box_autoadd_u_8(arr[5]), - category: dco_decode_opt_String(arr[6]), - zsaValue: dco_decode_i_64(arr[7]), - assetId: dco_decode_opt_box_autoadd_i_32(arr[8]), - assetDisplay: dco_decode_String(arr[9]), - price: dco_decode_opt_box_autoadd_f_64(arr[10]), - memo: dco_decode_opt_String(arr[11]), - isUserMemo: dco_decode_bool(arr[12]), - contactName: dco_decode_opt_String(arr[13]), + fee: dco_decode_i_64(arr[5]), + tpe: dco_decode_opt_box_autoadd_u_8(arr[6]), + category: dco_decode_opt_String(arr[7]), + zsaValue: dco_decode_i_64(arr[8]), + assetId: dco_decode_opt_box_autoadd_i_32(arr[9]), + assetDisplay: dco_decode_String(arr[10]), + price: dco_decode_opt_box_autoadd_f_64(arr[11]), + memo: dco_decode_opt_String(arr[12]), + isUserMemo: dco_decode_bool(arr[13]), + contactName: dco_decode_opt_String(arr[14]), ); } @@ -12473,6 +12474,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_height = sse_decode_u_32(deserializer); var var_time = sse_decode_u_32(deserializer); var var_value = sse_decode_i_64(deserializer); + var var_fee = sse_decode_i_64(deserializer); var var_tpe = sse_decode_opt_box_autoadd_u_8(deserializer); var var_category = sse_decode_opt_String(deserializer); var var_zsaValue = sse_decode_i_64(deserializer); @@ -12488,6 +12490,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { height: var_height, time: var_time, value: var_value, + fee: var_fee, tpe: var_tpe, category: var_category, zsaValue: var_zsaValue, @@ -15042,6 +15045,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(self.height, serializer); sse_encode_u_32(self.time, serializer); sse_encode_i_64(self.value, serializer); + sse_encode_i_64(self.fee, serializer); sse_encode_opt_box_autoadd_u_8(self.tpe, serializer); sse_encode_opt_String(self.category, serializer); sse_encode_i_64(self.zsaValue, serializer); diff --git a/rust/src/api/account.rs b/rust/src/api/account.rs index b8aa48e95..3f98945e5 100644 --- a/rust/src/api/account.rs +++ b/rust/src/api/account.rs @@ -324,6 +324,8 @@ pub struct Tx { pub height: u32, pub time: u32, pub value: i64, + /// Fee paid, in zatoshis. Recorded when the transaction's memos are + /// decrypted; zero for transactions whose details have not been fetched. pub fee: i64, pub tpe: Option<u8>, pub category: Option<String>, diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 52ecbe661..f7f056adb 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -11412,6 +11412,7 @@ impl SseDecode for crate::api::account::Tx { let mut var_height = <u32>::sse_decode(deserializer); let mut var_time = <u32>::sse_decode(deserializer); let mut var_value = <i64>::sse_decode(deserializer); + let mut var_fee = <i64>::sse_decode(deserializer); let mut var_tpe = <Option<u8>>::sse_decode(deserializer); let mut var_category = <Option<String>>::sse_decode(deserializer); let mut var_zsaValue = <i64>::sse_decode(deserializer); @@ -11427,6 +11428,7 @@ impl SseDecode for crate::api::account::Tx { height: var_height, time: var_time, value: var_value, + fee: var_fee, tpe: var_tpe, category: var_category, zsa_value: var_zsaValue, @@ -14073,6 +14075,7 @@ impl flutter_rust_bridge::IntoDart for crate::api::account::Tx { self.height.into_into_dart().into_dart(), self.time.into_into_dart().into_dart(), self.value.into_into_dart().into_dart(), + self.fee.into_into_dart().into_dart(), self.tpe.into_into_dart().into_dart(), self.category.into_into_dart().into_dart(), self.zsa_value.into_into_dart().into_dart(), @@ -16749,6 +16752,7 @@ impl SseEncode for crate::api::account::Tx { <u32>::sse_encode(self.height, serializer); <u32>::sse_encode(self.time, serializer); <i64>::sse_encode(self.value, serializer); + <i64>::sse_encode(self.fee, serializer); <Option<u8>>::sse_encode(self.tpe, serializer); <Option<String>>::sse_encode(self.category, serializer); <i64>::sse_encode(self.zsa_value, serializer); From 6393cb9ece437da2bad5eae8fe792436a9a82d14 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Fri, 7 Aug 2026 22:19:35 -0400 Subject: [PATCH 178/189] Name the recipient of every transparent output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An external signer displays each transparent output's recipient for review and refuses one it cannot name: keystone3-firmware rejects a PCZT whose transparent output has no user_address, whether or not the output belongs to the wallet. The address is recoverable from the script, but the signer will not derive it, so any transaction creating a transparent output — deshielding, or paying a t-address — fails on the device. State the address alongside the script. Outputs whose script is not a recognised transparent address are left alone rather than guessed at. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 4b2a1640e474027718e772a99c915e9aa485d5d0) --- rust/src/pay/plan.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 874b1bcf5..0b8499c70 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1205,6 +1205,27 @@ pub async fn plan_transaction( Ok(()) })?; } + + // An external signer shows the recipient of every transparent + // output for review, and refuses one it cannot name. The address is + // recoverable from the script, but the signer will not derive it + // itself, so state it here. + let recipients = u + .bundle() + .outputs() + .iter() + .map(|o| { + TransparentAddress::from_script_pubkey(&o.script_pubkey().clone().into()) + .map(|addr| addr.encode(network)) + }) + .collect::<Vec<_>>(); + for (i, recipient) in recipients.into_iter().enumerate() { + let Some(recipient) = recipient else { continue }; + u.update_output_with(i, |mut u| { + u.set_user_address(recipient); + Ok(()) + })?; + } Ok(()) }) .unwrap(); From 1035f377186ea352bbe6304dc551eb41e5b75a53 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Sun, 9 Aug 2026 16:22:50 -0400 Subject: [PATCH 179/189] keystone: batch PCZT signing (zcash-sign-batch / zcash-batch-sig-result) Adds to_batch_request and apply_batch_sig_result in keystone_wire, exposed as pczt_to_batch_request / pczt_apply_batch_signatures. The request carries the device's v2 PCZT dialect headerless under one shared version ("PCZB" magic); the reply is only Orchard/Ironwood spend-auth signatures ("PCZS"), applied to the wallet-owned PCZT -- an order of magnitude fewer QR frames on the return leg. Shielded spends only; a transparent-input shield stays on zcash-pczt (firmware rejects transparent inputs in a batch). Byte-exactness of the batch inner PCZT is asserted against the device-verified golden fixture. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 880ff9cefb9e5a670b85330e40073e60428bb0f8) --- rust/src/api/pay.rs | 20 ++++ rust/src/keystone_wire.rs | 230 +++++++++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 5 deletions(-) diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index b710f1208..84785fd47 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -137,6 +137,26 @@ pub fn pczt_apply_keystone_signatures(original: Vec<u8>, signed: Vec<u8>) -> Res crate::keystone_wire::apply_signatures(&original, &signed).map_err(|e| anyhow::anyhow!(e)) } +/// Builds a `zcash-sign-batch` request for a Keystone from one or more PCZTs in +/// Cake's dialect. +/// +/// The batch path returns only signatures rather than a whole PCZT, so the reply +/// is far smaller over animated QR. It carries shielded spends only; a PCZT with +/// transparent inputs (a shield) must use the single [`pczt_to_keystone`] path. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_to_batch_request(pczts: Vec<Vec<u8>>) -> Result<Vec<u8>> { + crate::keystone_wire::to_batch_request(&pczts).map_err(|e| anyhow::anyhow!(e)) +} + +/// Takes a Keystone's `zcash-batch-sig-result` reply into the PCZT this wallet +/// built. `original` is the single PCZT sent in the batch; `response` carries +/// only its spend-auth signatures. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_apply_batch_signatures(original: Vec<u8>, response: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::apply_batch_sig_result(&original, &response) + .map_err(|e| anyhow::anyhow!(e)) +} + #[cfg_attr(feature = "flutter", frb)] pub async fn extract_transaction(package: &PcztPackage) -> Result<Vec<u8>> { crate::pay::plan::extract_transaction(package).await diff --git a/rust/src/keystone_wire.rs b/rust/src/keystone_wire.rs index 342a110ba..93121ab35 100644 --- a/rust/src/keystone_wire.rs +++ b/rust/src/keystone_wire.rs @@ -399,8 +399,10 @@ fn with_header<T: serde::Serialize>(body: &T, hint: usize) -> Result<Vec<u8>, St postcard::to_extend(body, buf).map_err(|e| format!("re-encode failed: {e:?}")) } -/// Rewrites a PCZT from Cake's dialect into the one a Keystone reads. -pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { +/// Parses a PCZT in Cake's dialect and transcodes it to the one a Keystone +/// reads, without the framing header. The batch request carries these +/// headerless; [`to_keystone`] wraps a single one for the legacy path. +fn to_dst_pczt(bytes: &[u8]) -> Result<dst::Pczt, String> { let src: src_::Pczt = postcard::from_bytes(split_header(bytes)?) .map_err(|e| format!("could not read this PCZT: {e:?}"))?; if src @@ -410,7 +412,7 @@ pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { { return Err("Sapling bundles cannot be signed by this device".into()); } - let out = dst::Pczt { + Ok(dst::Pczt { global: src.global, transparent: src.transparent, sapling: src.sapling.map(|s| dst::SaplingBundle { @@ -422,8 +424,12 @@ pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { }), orchard: src.orchard.map(to_dst_orchard), ironwood: src.ironwood.map(to_dst_orchard), - }; - with_header(&out, bytes.len()) + }) +} + +/// Rewrites a PCZT from Cake's dialect into the one a Keystone reads. +pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { + with_header(&to_dst_pczt(bytes)?, bytes.len()) } /// Rewrites a signed PCZT from the Keystone's dialect back into Cake's. @@ -528,6 +534,129 @@ pub fn apply_signatures(original: &[u8], signed: &[u8]) -> Result<Vec<u8>, Strin with_header(&orig, original.len()) } +// ---- batch signing (zcash-sign-batch / zcash-batch-sig-result) --------- +// +// The device's batch protocol shrinks the airgapped round trip. The request +// carries headerless v2 PCZTs under one shared version; the reply is only the +// Orchard/Ironwood spend-auth signatures, not a whole PCZT -- an order of +// magnitude fewer QR frames coming back. Firmware 3.0.2 (cypherpunk) speaks +// batch version 1; see keystone3-firmware docs/protocols/ur_registrys/zcash.md. +// +// Only shielded spends are signable this way: the device rejects a batch PCZT +// with transparent inputs or Sapling. The caller routes only shielded sends +// here and keeps the transparent shield on the single zcash-pczt path. + +const BATCH_REQUEST_MAGIC: [u8; 4] = *b"PCZB"; +const BATCH_RESPONSE_MAGIC: [u8; 4] = *b"PCZS"; +const BATCH_VERSION: u32 = 1; + +#[derive(Serialize, Deserialize)] +struct BatchSignRequest { + pczts: Vec<dst::Pczt>, +} + +#[derive(Serialize, Deserialize)] +struct BatchSignResponse { + signatures: Vec<Vec<SpendAuthSignature>>, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +enum ValuePool { + Orchard, + Ironwood, +} + +#[serde_as] +#[derive(Serialize, Deserialize)] +struct SpendAuthSignature { + value_pool: ValuePool, + action_index: u32, + #[serde_as(as = "[_; 64]")] + signature: [u8; 64], +} + +/// Builds a `zcash-sign-batch` request body from PCZTs in Cake's dialect. +/// +/// Each is transcoded to the device's v2 dialect and carried headerless; the +/// shared PCZT version rides in the batch header. The bytes returned are the +/// opaque `data` the UR layer wraps. +pub fn to_batch_request(pczts: &[Vec<u8>]) -> Result<Vec<u8>, String> { + if pczts.is_empty() { + return Err("a batch request needs at least one transaction".into()); + } + let body = BatchSignRequest { + pczts: pczts + .iter() + .map(|b| to_dst_pczt(b)) + .collect::<Result<_, _>>()?, + }; + let hint: usize = pczts.iter().map(|b| b.len()).sum(); + let mut buf = Vec::with_capacity(hint + 32); + buf.extend_from_slice(&BATCH_REQUEST_MAGIC); + buf.extend_from_slice(&BATCH_VERSION.to_le_bytes()); + buf.extend_from_slice(&V2.to_le_bytes()); // one shared PCZT version for the batch + postcard::to_extend(&body, buf).map_err(|e| format!("batch request encode failed: {e:?}")) +} + +/// Applies a `zcash-batch-sig-result` reply to the PCZT this wallet built. +/// +/// The reply carries only spend-auth signatures, keyed by value pool and action +/// index; everything the prover needs stays in `original`, which must be the +/// single PCZT that was sent in the batch. +pub fn apply_batch_sig_result(original: &[u8], response: &[u8]) -> Result<Vec<u8>, String> { + if response.len() < 8 || response[..4] != BATCH_RESPONSE_MAGIC { + return Err("not a batch signature response".into()); + } + let version = u32::from_le_bytes(response[4..8].try_into().unwrap()); + if version != BATCH_VERSION { + return Err(format!("expected batch version {BATCH_VERSION}, got {version}")); + } + let (parsed, rest): (BatchSignResponse, _) = postcard::take_from_bytes(&response[8..]) + .map_err(|e| format!("could not read the batch response: {e:?}"))?; + if !rest.is_empty() { + return Err("trailing data after the batch response".into()); + } + // One PCZT was sent, so its signatures are the first (and only) entry. + let sigs = parsed + .signatures + .into_iter() + .next() + .ok_or("the device returned no signatures")?; + + let mut orig: src_::Pczt = postcard::from_bytes(split_header(original)?) + .map_err(|e| format!("could not read the original PCZT: {e:?}"))?; + + let mut applied = 0usize; + for sig in sigs { + let (bundle, pool) = match sig.value_pool { + ValuePool::Orchard => (orig.orchard.as_mut(), "Orchard"), + ValuePool::Ironwood => (orig.ironwood.as_mut(), "Ironwood"), + }; + let bundle = bundle.ok_or_else(|| { + format!("the response signs a {pool} action but the transaction has no {pool} bundle") + })?; + let action_count = bundle.actions.len(); + let action = bundle + .actions + .get_mut(sig.action_index as usize) + .ok_or_else(|| { + format!( + "the response signs {pool} action {} but the transaction has {action_count}", + sig.action_index + ) + })?; + // A spend the IO Finalizer already signed (a dummy) keeps its signature. + if action.spend.spend_auth_sig.is_none() { + action.spend.spend_auth_sig = Some(sig.signature); + applied += 1; + } + } + if applied == 0 { + return Err("the device returned no signatures".into()); + } + with_header(&orig, original.len()) +} + #[cfg(test)] mod tests { use super::*; @@ -612,4 +741,95 @@ mod tests { v1[4] = 1; assert!(to_keystone(&v1).is_err()); } + + #[test] + fn batch_request_carries_the_device_pczt() { + let req = to_batch_request(&[CAKE.to_vec()]).expect("batch request"); + // Header: "PCZB" || batch version 1 || pczt version 2, all little-endian. + assert_eq!(&req[..4], b"PCZB"); + assert_eq!(u32::from_le_bytes(req[4..8].try_into().unwrap()), 1); + assert_eq!(u32::from_le_bytes(req[8..12].try_into().unwrap()), 2); + + // The body is one PCZT, and its bytes are byte-identical to the body of + // the device-verified golden -- i.e. the batch carries exactly what the + // legacy zcash-pczt path already proved the firmware parses. + let body: BatchSignRequest = postcard::from_bytes(&req[12..]).expect("decode body"); + assert_eq!(body.pczts.len(), 1); + let inner = postcard::to_extend(&body.pczts[0], Vec::new()).expect("re-encode inner"); + assert_eq!( + inner, + &KEYSTONE[8..], + "batch inner PCZT must match the device-dialect golden body" + ); + } + + #[test] + fn batch_request_rejects_an_empty_batch() { + assert!(to_batch_request(&[]).is_err()); + } + + #[test] + fn applies_batch_signatures() { + // The Ironwood actions the device would sign are those the IO Finalizer + // left unsigned. + let orig: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let to_sign: Vec<u32> = orig + .ironwood + .as_ref() + .unwrap() + .actions + .iter() + .enumerate() + .filter(|(_, a)| a.spend.spend_auth_sig.is_none()) + .map(|(i, _)| i as u32) + .collect(); + assert!(!to_sign.is_empty(), "fixture must have a spend to sign"); + + // Stand in for the device: a compact response signing just those. + let body = BatchSignResponse { + signatures: vec![to_sign + .iter() + .map(|&i| SpendAuthSignature { + value_pool: ValuePool::Ironwood, + action_index: i, + signature: [9u8; 64], + }) + .collect()], + }; + let mut resp = Vec::new(); + resp.extend_from_slice(b"PCZS"); + resp.extend_from_slice(&1u32.to_le_bytes()); + let resp = postcard::to_extend(&body, resp).unwrap(); + + let merged = apply_batch_sig_result(CAKE, &resp).expect("apply"); + let out: src_::Pczt = postcard::from_bytes(&merged[8..]).unwrap(); + let out_actions = &out.ironwood.as_ref().unwrap().actions; + let orig_actions = &orig.ironwood.as_ref().unwrap().actions; + + // Every spend is now authorised; the ones the device signed took [9; 64], + // and any the IO Finalizer had already signed kept theirs. + assert!(out_actions.iter().all(|a| a.spend.spend_auth_sig.is_some())); + for (a, b) in out_actions.iter().zip(orig_actions.iter()) { + let expected = b.spend.spend_auth_sig.or(Some([9u8; 64])); + assert_eq!(a.spend.spend_auth_sig, expected); + } + } + + #[test] + fn rejects_a_malformed_batch_response() { + // Wrong magic. + assert!(apply_batch_sig_result(CAKE, b"nope____").is_err()); + // Right magic, unsupported version. + let mut bad = Vec::new(); + bad.extend_from_slice(b"PCZS"); + bad.extend_from_slice(&2u32.to_le_bytes()); + assert!(apply_batch_sig_result(CAKE, &bad).is_err()); + // Valid header, no signatures. + let empty = BatchSignResponse { signatures: vec![vec![]] }; + let mut resp = Vec::new(); + resp.extend_from_slice(b"PCZS"); + resp.extend_from_slice(&1u32.to_le_bytes()); + let resp = postcard::to_extend(&empty, resp).unwrap(); + assert!(apply_batch_sig_result(CAKE, &resp).is_err()); + } } From f32739fd36794283d3cfd7e11bd477e72f6fee02 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Sun, 9 Aug 2026 18:33:43 -0400 Subject: [PATCH 180/189] keystone batch: strip spend-auth sigs from the request The device rejects a batch request carrying any Orchard/Ironwood spend-auth signature ("batch request must not contain Ironwood spend authorization signatures"), including the IO-Finalizer sigs on preauthorized padding spends. Clear them from the request; the wallet-owned base keeps them for extraction and apply_batch_sig_result adds the device's real-spend signatures on top. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit cd6982bc96ee35bbebbace424078db4ed6c4b3e9) --- rust/src/keystone_wire.rs | 66 +++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/rust/src/keystone_wire.rs b/rust/src/keystone_wire.rs index 93121ab35..b427abd75 100644 --- a/rust/src/keystone_wire.rs +++ b/rust/src/keystone_wire.rs @@ -584,12 +584,17 @@ pub fn to_batch_request(pczts: &[Vec<u8>]) -> Result<Vec<u8>, String> { if pczts.is_empty() { return Err("a batch request needs at least one transaction".into()); } - let body = BatchSignRequest { - pczts: pczts - .iter() - .map(|b| to_dst_pczt(b)) - .collect::<Result<_, _>>()?, - }; + let mut dst_pczts: Vec<dst::Pczt> = + pczts.iter().map(|b| to_dst_pczt(b)).collect::<Result<_, _>>()?; + // The device rejects a batch request carrying ANY spend-authorization + // signature -- including the ones the IO Finalizer puts on preauthorized + // padding (dummy) spends before this wallet ever saw the transaction. + // Strip them from the request; the wallet-owned base PCZT keeps them, and + // apply_batch_sig_result layers the device's real-spend signatures on top. + for p in dst_pczts.iter_mut() { + clear_batch_spend_auth_sigs(p); + } + let body = BatchSignRequest { pczts: dst_pczts }; let hint: usize = pczts.iter().map(|b| b.len()).sum(); let mut buf = Vec::with_capacity(hint + 32); buf.extend_from_slice(&BATCH_REQUEST_MAGIC); @@ -598,6 +603,18 @@ pub fn to_batch_request(pczts: &[Vec<u8>]) -> Result<Vec<u8>, String> { postcard::to_extend(&body, buf).map_err(|e| format!("batch request encode failed: {e:?}")) } +/// Removes every Orchard and Ironwood spend-auth signature from a PCZT bound +/// for a batch request. The device refuses a request that carries any. +fn clear_batch_spend_auth_sigs(pczt: &mut dst::Pczt) { + for bundle in [pczt.orchard.as_mut(), pczt.ironwood.as_mut()] { + if let Some(b) = bundle { + for a in b.actions.iter_mut() { + a.spend.spend_auth_sig = None; + } + } + } +} + /// Applies a `zcash-batch-sig-result` reply to the PCZT this wallet built. /// /// The reply carries only spend-auth signatures, keyed by value pool and action @@ -743,24 +760,41 @@ mod tests { } #[test] - fn batch_request_carries_the_device_pczt() { + fn batch_request_strips_spend_auth_sigs() { let req = to_batch_request(&[CAKE.to_vec()]).expect("batch request"); // Header: "PCZB" || batch version 1 || pczt version 2, all little-endian. assert_eq!(&req[..4], b"PCZB"); assert_eq!(u32::from_le_bytes(req[4..8].try_into().unwrap()), 1); assert_eq!(u32::from_le_bytes(req[8..12].try_into().unwrap()), 2); - // The body is one PCZT, and its bytes are byte-identical to the body of - // the device-verified golden -- i.e. the batch carries exactly what the - // legacy zcash-pczt path already proved the firmware parses. let body: BatchSignRequest = postcard::from_bytes(&req[12..]).expect("decode body"); assert_eq!(body.pczts.len(), 1); - let inner = postcard::to_extend(&body.pczts[0], Vec::new()).expect("re-encode inner"); - assert_eq!( - inner, - &KEYSTONE[8..], - "batch inner PCZT must match the device-dialect golden body" - ); + + // The device refuses a batch request with any spend-auth signature. + let inner = &body.pczts[0]; + for bundle in [inner.orchard.as_ref(), inner.ironwood.as_ref()] { + if let Some(b) = bundle { + assert!( + b.actions.iter().all(|a| a.spend.spend_auth_sig.is_none()), + "batch request must not carry any spend-auth signature" + ); + } + } + + // The device golden has an IO-Finalizer signature on its padding spend, + // so stripping proves both that the fixture exercises the case and that + // the batch inner is otherwise the device-dialect PCZT byte for byte. + let mut golden: dst::Pczt = postcard::from_bytes(&KEYSTONE[8..]).unwrap(); + let had_sig = [golden.orchard.as_ref(), golden.ironwood.as_ref()] + .iter() + .flatten() + .flat_map(|b| b.actions.iter()) + .any(|a| a.spend.spend_auth_sig.is_some()); + assert!(had_sig, "fixture must carry a spend-auth sig to strip"); + clear_batch_spend_auth_sigs(&mut golden); + let golden_inner = postcard::to_extend(&golden, Vec::new()).unwrap(); + let inner_bytes = postcard::to_extend(inner, Vec::new()).unwrap(); + assert_eq!(inner_bytes, golden_inner); } #[test] From b637fb0fd57a3b2c5c190d4c35df5f0b8c45afd6 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 12:18:44 -0400 Subject: [PATCH 181/189] ledger: drive the Official Zcash app from Flutter over any transport The Official Ledger app signer (Ironwood/v6 PCZT) only reached the device through the desktop USB HID transport, which does not exist on a phone: there the BLE or USB connection is owned by the Flutter side. Split the transport so the protocol code (Official app, APDU framing) builds on every target, keep hidapi and the Zondax app behind the `ledger` feature, and add a Device that hands each APDU to a Dart closure. Expose it through api::ledger: app version probe, UFVK export, and PCZT signing with progress events. Official accounts can now also be created from a UFVK the host already exported, since the mobile wallet cannot let Rust talk to the device while creating the account. Nym is no longer a default feature: the wallet builds that consume this crate do not ship the mixnet transport, and is_valid_nym_url stays exported so the generated bindings do not depend on the feature. Bindings regenerated with flutter_rust_bridge 2.12.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- Cargo.lock | 1 + lib/src/rust/api/account.dart | 184 +- lib/src/rust/api/coin.dart | 21 +- lib/src/rust/api/contacts.dart | 63 +- lib/src/rust/api/db.dart | 36 +- lib/src/rust/api/frost.dart | 75 +- lib/src/rust/api/init.dart | 2 +- lib/src/rust/api/issuance.dart | 35 +- lib/src/rust/api/key.dart | 8 +- lib/src/rust/api/ledger.dart | 52 + lib/src/rust/api/mempool.dart | 10 +- lib/src/rust/api/migrate.dart | 17 +- lib/src/rust/api/network.dart | 31 +- lib/src/rust/api/openalias.dart | 21 +- lib/src/rust/api/pay.dart | 145 +- lib/src/rust/api/plugin.dart | 36 +- lib/src/rust/api/raptor.dart | 9 +- lib/src/rust/api/sapling.dart | 6 +- lib/src/rust/api/sweep.dart | 9 +- lib/src/rust/api/sync.dart | 57 +- lib/src/rust/api/transaction.dart | 83 +- lib/src/rust/api/vault.dart | 58 +- lib/src/rust/api/voting.dart | 1028 ++-- lib/src/rust/api/zsa.dart | 17 +- lib/src/rust/frb_generated.dart | 8091 +++++++++++++++++---------- lib/src/rust/frb_generated.io.dart | 1081 ++-- lib/src/rust/frb_generated.web.dart | 1187 ++-- lib/src/rust/io.dart | 2 +- lib/src/rust/lib.dart | 6 +- lib/src/rust/pay.dart | 8 +- lib/src/rust/pay/error.dart | 12 +- pubspec.yaml | 2 +- rust/Cargo.toml | 2 +- rust/src/account.rs | 27 +- rust/src/api/ledger.rs | 122 +- rust/src/api/mod.rs | 1 + rust/src/api/network.rs | 14 +- rust/src/frb_generated.rs | 638 ++- rust/src/ledger/dart_device.rs | 116 + rust/src/ledger/mock.rs | 11 +- rust/src/ledger/mod.rs | 13 +- rust/src/ledger/official.rs | 137 +- rust/src/ledger/official_sign.rs | 1 + rust/src/ledger/transport.rs | 423 +- rust/src/pay/plan.rs | 11 +- 45 files changed, 9055 insertions(+), 4854 deletions(-) create mode 100644 lib/src/rust/api/ledger.dart create mode 100644 rust/src/ledger/dart_device.rs diff --git a/Cargo.lock b/Cargo.lock index 4823e9901..96ccbe274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9409,6 +9409,7 @@ dependencies = [ "orchard", "pasta_curves", "pczt", + "postcard", "prost 0.14.4", "qrcode", "rand 0.6.5", diff --git a/lib/src/rust/api/account.dart b/lib/src/rust/api/account.dart index 1d978f230..a7ac95b04 100644 --- a/lib/src/rust/api/account.dart +++ b/lib/src/rust/api/account.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -11,24 +11,32 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; import 'pay.dart'; part 'account.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `get_ledger` +// These functions are ignored because they are not marked as `pub`: `get_ledger`, `sign_ledger_pczt` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `fmt`, `fmt`, `fmt`, `fmt`, `fmt` Future<int> getAccountPools({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountPools(account: account, c: c); -Future<String> getAccountUfvk( - {required int account, required int pools, required Coin c}) => - RustLib.instance.api - .crateApiAccountGetAccountUfvk(account: account, pools: pools, c: c); +Future<String> getAccountUfvk({ + required int account, + required int pools, + required Coin c, +}) => RustLib.instance.api.crateApiAccountGetAccountUfvk( + account: account, + pools: pools, + c: c, +); Future<Seed?> getAccountSeed({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountGetAccountSeed(account: account, c: c); -Future<String?> getAccountFingerprint( - {required int account, required Coin c}) => - RustLib.instance.api - .crateApiAccountGetAccountFingerprint(account: account, c: c); +Future<String?> getAccountFingerprint({ + required int account, + required Coin c, +}) => RustLib.instance.api.crateApiAccountGetAccountFingerprint( + account: account, + c: c, +); String uaFromUfvk({required String ufvk, int? di, required Coin c}) => RustLib.instance.api.crateApiAccountUaFromUfvk(ufvk: ufvk, di: di, c: c); @@ -45,12 +53,15 @@ Future<void> updateAccount({required AccountUpdate update, required Coin c}) => Future<void> deleteAccount({required int account, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteAccount(account: account, c: c); -Future<void> reorderAccount( - {required int oldPosition, - required int newPosition, - required Coin c}) => - RustLib.instance.api.crateApiAccountReorderAccount( - oldPosition: oldPosition, newPosition: newPosition, c: c); +Future<void> reorderAccount({ + required int oldPosition, + required int newPosition, + required Coin c, +}) => RustLib.instance.api.crateApiAccountReorderAccount( + oldPosition: oldPosition, + newPosition: newPosition, + c: c, +); Future<int> newAccount({required NewAccount na, required Coin c}) => RustLib.instance.api.crateApiAccountNewAccount(na: na, c: c); @@ -67,9 +78,10 @@ Future<String?> generateNextChangeAddress({required Coin c}) => Future<void> resetSync({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountResetSync(id: id, c: c); -Future<void> removeAccount({required int accountId, required Coin c}) => - RustLib.instance.api - .crateApiAccountRemoveAccount(accountId: accountId, c: c); +Future<void> removeAccount({required int accountId, required Coin c}) => RustLib + .instance + .api + .crateApiAccountRemoveAccount(accountId: accountId, c: c); Future<List<Tx>> listTxHistory({required Coin c}) => RustLib.instance.api.crateApiAccountListTxHistory(c: c); @@ -80,10 +92,15 @@ Future<List<Memo>> listMemos({required Coin c}) => Future<Addresses> getAddresses({required int uaPools, required Coin c}) => RustLib.instance.api.crateApiAccountGetAddresses(uaPools: uaPools, c: c); -Future<Addresses> getAccountAddresses( - {required int account, required int uaPools, required Coin c}) => - RustLib.instance.api.crateApiAccountGetAccountAddresses( - account: account, uaPools: uaPools, c: c); +Future<Addresses> getAccountAddresses({ + required int account, + required int uaPools, + required Coin c, +}) => RustLib.instance.api.crateApiAccountGetAccountAddresses( + account: account, + uaPools: uaPools, + c: c, +); Future<List<String>> listOwnedAddresses({required Coin c}) => RustLib.instance.api.crateApiAccountListOwnedAddresses(c: c); @@ -94,30 +111,46 @@ Future<TxAccount> getTxDetails({required int idTx, required Coin c}) => Future<List<TxNote>> listNotes({required Coin c}) => RustLib.instance.api.crateApiAccountListNotes(c: c); -Future<void> lockNote( - {required int id, required bool locked, required Coin c}) => +Future<void> lockNote({ + required int id, + required bool locked, + required Coin c, +}) => RustLib.instance.api.crateApiAccountLockNote(id: id, locked: locked, c: c); -Future<List<TAddressTxCount>> fetchTransparentAddressTxCount( - {required Coin c}) => - RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); - -Future<List<TAddressTxCount>> fetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}) => - RustLib.instance.api.crateApiAccountFetchAddressTxCount( - c: c, aggregate: aggregate, poolFilter: poolFilter); - -Future<Uint8List> exportAccount( - {required int id, required String passphrase, required Coin c}) => - RustLib.instance.api - .crateApiAccountExportAccount(id: id, passphrase: passphrase, c: c); - -Future<void> importAccount( - {required String passphrase, - required List<int> data, - required Coin c}) => - RustLib.instance.api - .crateApiAccountImportAccount(passphrase: passphrase, data: data, c: c); +Future<List<TAddressTxCount>> fetchTransparentAddressTxCount({ + required Coin c, +}) => RustLib.instance.api.crateApiAccountFetchTransparentAddressTxCount(c: c); + +Future<List<TAddressTxCount>> fetchAddressTxCount({ + required Coin c, + required bool aggregate, + required int poolFilter, +}) => RustLib.instance.api.crateApiAccountFetchAddressTxCount( + c: c, + aggregate: aggregate, + poolFilter: poolFilter, +); + +Future<Uint8List> exportAccount({ + required int id, + required String passphrase, + required Coin c, +}) => RustLib.instance.api.crateApiAccountExportAccount( + id: id, + passphrase: passphrase, + c: c, +); + +Future<void> importAccount({ + required String passphrase, + required List<int> data, + required Coin c, +}) => RustLib.instance.api.crateApiAccountImportAccount( + passphrase: passphrase, + data: data, + c: c, +); Future<void> printKeys({required int id, required Coin c}) => RustLib.instance.api.crateApiAccountPrintKeys(id: id, c: c); @@ -131,8 +164,11 @@ Future<List<Folder>> listFolders({required Coin c}) => Future<Folder> createNewFolder({required String name, required Coin c}) => RustLib.instance.api.crateApiAccountCreateNewFolder(name: name, c: c); -Future<void> renameFolder( - {required int id, required String name, required Coin c}) => +Future<void> renameFolder({ + required int id, + required String name, + required Coin c, +}) => RustLib.instance.api.crateApiAccountRenameFolder(id: id, name: name, c: c); Future<void> deleteFolders({required List<int> ids, required Coin c}) => @@ -142,12 +178,16 @@ Future<List<Category>> listCategories({required Coin c}) => RustLib.instance.api.crateApiAccountListCategories(c: c); Future<int> createNewCategory({required Category category, required Coin c}) => - RustLib.instance.api - .crateApiAccountCreateNewCategory(category: category, c: c); + RustLib.instance.api.crateApiAccountCreateNewCategory( + category: category, + c: c, + ); Future<void> renameCategory({required Category category, required Coin c}) => - RustLib.instance.api - .crateApiAccountRenameCategory(category: category, c: c); + RustLib.instance.api.crateApiAccountRenameCategory( + category: category, + c: c, + ); Future<void> deleteCategories({required List<int> ids, required Coin c}) => RustLib.instance.api.crateApiAccountDeleteCategories(ids: ids, c: c); @@ -155,10 +195,15 @@ Future<void> deleteCategories({required List<int> ids, required Coin c}) => Future<String> getExportedData({required int type, required Coin c}) => RustLib.instance.api.crateApiAccountGetExportedData(type: type, c: c); -Future<void> lockRecentNotes( - {required int height, required int threshold, required Coin c}) => - RustLib.instance.api.crateApiAccountLockRecentNotes( - height: height, threshold: threshold, c: c); +Future<void> lockRecentNotes({ + required int height, + required int threshold, + required Coin c, +}) => RustLib.instance.api.crateApiAccountLockRecentNotes( + height: height, + threshold: threshold, + c: c, +); Future<void> unlockAllNotes({required Coin c}) => RustLib.instance.api.crateApiAccountUnlockAllNotes(c: c); @@ -175,10 +220,13 @@ Future<String> showLedgerSaplingAddress({required Coin c}) => Future<String> showLedgerTransparentAddress({required Coin c}) => RustLib.instance.api.crateApiAccountShowLedgerTransparentAddress(c: c); -Stream<SigningEvent> signLedgerTransaction( - {required PcztPackage package, required Coin c}) => - RustLib.instance.api - .crateApiAccountSignLedgerTransaction(package: package, c: c); +Stream<SigningEvent> signLedgerTransaction({ + required PcztPackage package, + required Coin c, +}) => RustLib.instance.api.crateApiAccountSignLedgerTransaction( + package: package, + c: c, +); Future<void> dummyExport({required SigningEvent a}) => RustLib.instance.api.crateApiAccountDummyExport(a: a); @@ -269,19 +317,13 @@ sealed class Category with _$Category { @freezed sealed class Folder with _$Folder { - const factory Folder({ - required int id, - required String name, - }) = _Folder; + const factory Folder({required int id, required String name}) = _Folder; } @freezed sealed class FrostParams with _$FrostParams { - const factory FrostParams({ - required int id, - required int n, - required int t, - }) = _FrostParams; + const factory FrostParams({required int id, required int n, required int t}) = + _FrostParams; } @freezed @@ -324,11 +366,7 @@ class Receivers { final String? saddr; final String? oaddr; - const Receivers({ - this.taddr, - this.saddr, - this.oaddr, - }); + const Receivers({this.taddr, this.saddr, this.oaddr}); static Future<Receivers> default_() => RustLib.instance.api.crateApiAccountReceiversDefault(); diff --git a/lib/src/rust/api/coin.dart b/lib/src/rust/api/coin.dart index ebeab917d..cf694a308 100644 --- a/lib/src/rust/api/coin.dart +++ b/lib/src/rust/api/coin.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -8,7 +8,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'coin.freezed.dart'; -// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_nym`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `is_mixnet`, `network`, `open_proxied_stream`, `try_open` +// These functions are ignored because they are not marked as `pub`: `build_tor`, `client`, `connect_over_proxy`, `connect_over_tor`, `get_connect_options`, `get_connection`, `get_pool`, `http_connect_tunnel`, `is_mixnet`, `network`, `open_proxied_stream`, `try_open` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` Future<void> initDatadir({required String directory}) => @@ -31,23 +31,26 @@ sealed class Coin with _$Coin { required int transport, required String proxy, }) = _Coin; - Future<void> getName() => RustLib.instance.api.crateApiCoinCoinGetName( - that: this, - ); + Future<void> getName() => + RustLib.instance.api.crateApiCoinCoinGetName(that: this); factory Coin({int? defaultCoin}) => RustLib.instance.api.crateApiCoinCoinNew(defaultCoin: defaultCoin); Future<Coin> openDatabase({required String dbFilepath, String? password}) => RustLib.instance.api.crateApiCoinCoinOpenDatabase( - that: this, dbFilepath: dbFilepath, password: password); + that: this, + dbFilepath: dbFilepath, + password: password, + ); Future<Coin> setAccount({required int account}) => RustLib.instance.api .crateApiCoinCoinSetAccount(that: this, account: account); - Coin setLwd({required int serverType, required String url}) => - RustLib.instance.api - .crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); + Coin setLwd({required int serverType, required String url}) => RustLib + .instance + .api + .crateApiCoinCoinSetLwd(that: this, serverType: serverType, url: url); Coin setProxy({required String proxy}) => RustLib.instance.api.crateApiCoinCoinSetProxy(that: this, proxy: proxy); diff --git a/lib/src/rust/api/contacts.dart b/lib/src/rust/api/contacts.dart index 7f5ff0da9..74ba51618 100644 --- a/lib/src/rust/api/contacts.dart +++ b/lib/src/rust/api/contacts.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -14,22 +14,31 @@ part 'contacts.freezed.dart'; Future<List<Contact>> listContacts({required Coin c}) => RustLib.instance.api.crateApiContactsListContacts(c: c); -Future<Contact> createContact( - {required String name, - required List<String> addresses, - required String notes, - required Coin c}) => - RustLib.instance.api.crateApiContactsCreateContact( - name: name, addresses: addresses, notes: notes, c: c); +Future<Contact> createContact({ + required String name, + required List<String> addresses, + required String notes, + required Coin c, +}) => RustLib.instance.api.crateApiContactsCreateContact( + name: name, + addresses: addresses, + notes: notes, + c: c, +); -Future<void> updateContact( - {required int id, - String? name, - List<String>? addresses, - String? notes, - required Coin c}) => - RustLib.instance.api.crateApiContactsUpdateContact( - id: id, name: name, addresses: addresses, notes: notes, c: c); +Future<void> updateContact({ + required int id, + String? name, + List<String>? addresses, + String? notes, + required Coin c, +}) => RustLib.instance.api.crateApiContactsUpdateContact( + id: id, + name: name, + addresses: addresses, + notes: notes, + c: c, +); Future<void> deleteContacts({required List<int> ids, required Coin c}) => RustLib.instance.api.crateApiContactsDeleteContacts(ids: ids, c: c); @@ -39,18 +48,24 @@ Future<void> deleteContacts({required List<int> ids, required Coin c}) => /// The input address can be either a unified address (which will be expanded /// to its constituent receivers) or a single-pool receiver address. /// Returns matching contacts with the original address that produced the match. -Future<List<ContactMatch>> findContactsForAddress( - {required String address, required Coin c}) => - RustLib.instance.api - .crateApiContactsFindContactsForAddress(address: address, c: c); +Future<List<ContactMatch>> findContactsForAddress({ + required String address, + required Coin c, +}) => RustLib.instance.api.crateApiContactsFindContactsForAddress( + address: address, + c: c, +); Future<String> exportContactsVcard({required Coin c}) => RustLib.instance.api.crateApiContactsExportContactsVcard(c: c); -Future<List<Contact>> importContactsVcard( - {required String vcardData, required Coin c}) => - RustLib.instance.api - .crateApiContactsImportContactsVcard(vcardData: vcardData, c: c); +Future<List<Contact>> importContactsVcard({ + required String vcardData, + required Coin c, +}) => RustLib.instance.api.crateApiContactsImportContactsVcard( + vcardData: vcardData, + c: c, +); @freezed sealed class Contact with _$Contact { diff --git a/lib/src/rust/api/db.dart b/lib/src/rust/api/db.dart index bd56ce4ad..bfb232f55 100644 --- a/lib/src/rust/api/db.dart +++ b/lib/src/rust/api/db.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -10,23 +10,26 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; Future<List<DbAccountPreview>> listDbAccounts({required String dbFilepath}) => RustLib.instance.api.crateApiDbListDbAccounts(dbFilepath: dbFilepath); -Future<void> changeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}) => - RustLib.instance.api.crateApiDbChangeDbPassword( - dbFilepath: dbFilepath, - tmpDir: tmpDir, - oldPassword: oldPassword, - newPassword: newPassword); +Future<void> changeDbPassword({ + required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword, +}) => RustLib.instance.api.crateApiDbChangeDbPassword( + dbFilepath: dbFilepath, + tmpDir: tmpDir, + oldPassword: oldPassword, + newPassword: newPassword, +); Future<String?> getProp({required String key, required Coin c}) => RustLib.instance.api.crateApiDbGetProp(key: key, c: c); -Future<void> putProp( - {required String key, required String value, required Coin c}) => - RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); +Future<void> putProp({ + required String key, + required String value, + required Coin c, +}) => RustLib.instance.api.crateApiDbPutProp(key: key, value: value, c: c); Future<List<String>> listDbNames({required String dir}) => RustLib.instance.api.crateApiDbListDbNames(dir: dir); @@ -35,10 +38,7 @@ class DbAccountPreview { final int id; final String name; - const DbAccountPreview({ - required this.id, - required this.name, - }); + const DbAccountPreview({required this.id, required this.name}); @override int get hashCode => id.hashCode ^ name.hashCode; diff --git a/lib/src/rust/api/frost.dart b/lib/src/rust/api/frost.dart index e3ef36cc5..aad06d65d 100644 --- a/lib/src/rust/api/frost.dart +++ b/lib/src/rust/api/frost.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -15,15 +15,21 @@ part 'frost.freezed.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DKGParams` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt` -Future<void> setDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}) => - RustLib.instance.api.crateApiFrostSetDkgParams( - name: name, id: id, n: n, t: t, fundingAccount: fundingAccount, c: c); +Future<void> setDkgParams({ + required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c, +}) => RustLib.instance.api.crateApiFrostSetDkgParams( + name: name, + id: id, + n: n, + t: t, + fundingAccount: fundingAccount, + c: c, +); Future<bool> hasDkgParams({required Coin c}) => RustLib.instance.api.crateApiFrostHasDkgParams(c: c); @@ -54,10 +60,15 @@ Stream<DKGStatus> doDkg({required Coin c}) => Future<List<String>> getDkgAddresses({required Coin c}) => RustLib.instance.api.crateApiFrostGetDkgAddresses(c: c); -Future<void> setDkgAddress( - {required int id, required String address, required Coin c}) => - RustLib.instance.api - .crateApiFrostSetDkgAddress(id: id, address: address, c: c); +Future<void> setDkgAddress({ + required int id, + required String address, + required Coin c, +}) => RustLib.instance.api.crateApiFrostSetDkgAddress( + id: id, + address: address, + c: c, +); Future<void> cancelDkg({required Coin c}) => RustLib.instance.api.crateApiFrostCancelDkg(c: c); @@ -65,16 +76,17 @@ Future<void> cancelDkg({required Coin c}) => Future<void> resetSign({required Coin c}) => RustLib.instance.api.crateApiFrostResetSign(c: c); -Future<void> initSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}) => - RustLib.instance.api.crateApiFrostInitSign( - coordinator: coordinator, - fundingAccount: fundingAccount, - pczt: pczt, - c: c); +Future<void> initSign({ + required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c, +}) => RustLib.instance.api.crateApiFrostInitSign( + coordinator: coordinator, + fundingAccount: fundingAccount, + pczt: pczt, + c: c, +); Future<bool> isSigningInProgress({required Coin c}) => RustLib.instance.api.crateApiFrostIsSigningInProgress(c: c); @@ -94,9 +106,8 @@ sealed class DKGStatus with _$DKGStatus { const DKGStatus._(); const factory DKGStatus.waitParams() = DKGStatus_WaitParams; - const factory DKGStatus.waitAddresses( - List<String> field0, - ) = DKGStatus_WaitAddresses; + const factory DKGStatus.waitAddresses(List<String> field0) = + DKGStatus_WaitAddresses; /// Round 0 exchanges participant signing keys before the FROST rounds /// proper; it needs its own status so the UI does not report it as round 1. @@ -112,9 +123,8 @@ sealed class DKGStatus with _$DKGStatus { /// next block retries. Shown as an info/warning, not an error. const factory DKGStatus.waitingForFunds() = DKGStatus_WaitingForFunds; const factory DKGStatus.finalize() = DKGStatus_Finalize; - const factory DKGStatus.sharedAddress( - String field0, - ) = DKGStatus_SharedAddress; + const factory DKGStatus.sharedAddress(String field0) = + DKGStatus_SharedAddress; } @freezed @@ -155,7 +165,6 @@ sealed class SigningStatus with _$SigningStatus { SigningStatus_PreparingTransaction; const factory SigningStatus.sendingTransaction() = SigningStatus_SendingTransaction; - const factory SigningStatus.transactionSent( - String field0, - ) = SigningStatus_TransactionSent; + const factory SigningStatus.transactionSent(String field0) = + SigningStatus_TransactionSent; } diff --git a/lib/src/rust/api/init.dart b/lib/src/rust/api/init.dart index e8b0a78aa..2502df761 100644 --- a/lib/src/rust/api/init.dart +++ b/lib/src/rust/api/init.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/api/issuance.dart b/lib/src/rust/api/issuance.dart index a6b0cf466..8c1c8394a 100644 --- a/lib/src/rust/api/issuance.dart +++ b/lib/src/rust/api/issuance.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -27,19 +27,20 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// /// # Returns /// Serialized transaction bytes, ready for broadcast via `api::pay::broadcast_transaction`. -Future<Uint8List> issueAsset( - {required String assetName, - required BigInt amount, - required bool firstIssuance, - required bool finalize, - Uint8List? descHash, - required int idAccount, - required Coin c}) => - RustLib.instance.api.crateApiIssuanceIssueAsset( - assetName: assetName, - amount: amount, - firstIssuance: firstIssuance, - finalize: finalize, - descHash: descHash, - idAccount: idAccount, - c: c); +Future<Uint8List> issueAsset({ + required String assetName, + required BigInt amount, + required bool firstIssuance, + required bool finalize, + Uint8List? descHash, + required int idAccount, + required Coin c, +}) => RustLib.instance.api.crateApiIssuanceIssueAsset( + assetName: assetName, + amount: amount, + firstIssuance: firstIssuance, + finalize: finalize, + descHash: descHash, + idAccount: idAccount, + c: c, +); diff --git a/lib/src/rust/api/key.dart b/lib/src/rust/api/key.dart index 31a45b0cf..acfc13372 100644 --- a/lib/src/rust/api/key.dart +++ b/lib/src/rust/api/key.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -22,8 +22,10 @@ bool isValidAddress({required String address}) => RustLib.instance.api.crateApiKeyIsValidAddress(address: address); bool isValidTransparentAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiKeyIsValidTransparentAddress(address: address, c: c); + RustLib.instance.api.crateApiKeyIsValidTransparentAddress( + address: address, + c: c, + ); bool isTexAddress({required String address, required Coin c}) => RustLib.instance.api.crateApiKeyIsTexAddress(address: address, c: c); diff --git a/lib/src/rust/api/ledger.dart b/lib/src/rust/api/ledger.dart new file mode 100644 index 000000000..b1e9fdfdb --- /dev/null +++ b/lib/src/rust/api/ledger.dart @@ -0,0 +1,52 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import '../lib.dart'; +import 'coin.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'pay.dart'; + +/// Version of the Zcash app open on the device, e.g. "3.9.3". +/// +/// Fails with the device's status word when another app is open, which is +/// the cheapest way to tell the user to switch apps before asking for keys. +Future<String> ledgerAppVersion({ + required FutureOr<Uint8List> Function(Uint8List) exchange, +}) => RustLib.instance.api.crateApiLedgerLedgerAppVersion(exchange: exchange); + +/// Unified full viewing key of ZIP-32 account `aindex` on the device +/// (transparent + orchard receivers). The user approves the export on the +/// device screen, so this blocks until they do. +Future<String> ledgerGetUfvk({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, +}) => RustLib.instance.api.crateApiLedgerLedgerGetUfvk( + aindex: aindex, + c: c, + exchange: exchange, +); + +/// Default unified address of a viewing key, for showing which account a +/// device key belongs to before the account exists in the database. +String ufvkDefaultAddress({required String ufvk, required Coin c}) => + RustLib.instance.api.crateApiLedgerUfvkDefaultAddress(ufvk: ufvk, c: c); + +/// Signs a transaction plan on the Official Zcash app. +/// +/// Streams `SigningEvent::Progress` while the device reviews and signs, then +/// `SigningEvent::Result` with the proven, finalized package ready for +/// `extract_transaction`. Errors, including a refusal on the device, close +/// the stream with the error. +Stream<SigningEvent> ledgerSignTransaction({ + required PcztPackage package, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, +}) => RustLib.instance.api.crateApiLedgerLedgerSignTransaction( + package: package, + c: c, + exchange: exchange, +); diff --git a/lib/src/rust/api/mempool.dart b/lib/src/rust/api/mempool.dart index 603137f1b..7d8f66f37 100644 --- a/lib/src/rust/api/mempool.dart +++ b/lib/src/rust/api/mempool.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -52,12 +52,8 @@ class MempoolAmount { sealed class MempoolMsg with _$MempoolMsg { const MempoolMsg._(); - const factory MempoolMsg.blockHeight( - int field0, - ) = MempoolMsg_BlockHeight; - const factory MempoolMsg.txId( - MempoolTx field0, - ) = MempoolMsg_TxId; + const factory MempoolMsg.blockHeight(int field0) = MempoolMsg_BlockHeight; + const factory MempoolMsg.txId(MempoolTx field0) = MempoolMsg_TxId; } class MempoolNote { diff --git a/lib/src/rust/api/migrate.dart b/lib/src/rust/api/migrate.dart index 2e22c9ad5..6fa1e4ca1 100644 --- a/lib/src/rust/api/migrate.dart +++ b/lib/src/rust/api/migrate.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -38,17 +38,14 @@ abstract class NoteMigration implements RustOpaqueInterface { sealed class MigrationEvent with _$MigrationEvent { const MigrationEvent._(); - const factory MigrationEvent.splitComplete({ - required BigInt fee, - }) = MigrationEvent_SplitComplete; - const factory MigrationEvent.migrateComplete({ - required BigInt fee, - }) = MigrationEvent_MigrateComplete; + const factory MigrationEvent.splitComplete({required BigInt fee}) = + MigrationEvent_SplitComplete; + const factory MigrationEvent.migrateComplete({required BigInt fee}) = + MigrationEvent_MigrateComplete; const factory MigrationEvent.complete() = MigrationEvent_Complete; const factory MigrationEvent.nothingToDo() = MigrationEvent_NothingToDo; - const factory MigrationEvent.error({ - required String message, - }) = MigrationEvent_Error; + const factory MigrationEvent.error({required String message}) = + MigrationEvent_Error; } /// Current migration status — streamed to Flutter by run_migration(). diff --git a/lib/src/rust/api/network.dart b/lib/src/rust/api/network.dart index d476a9921..c3b111723 100644 --- a/lib/src/rust/api/network.dart +++ b/lib/src/rust/api/network.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -21,10 +21,13 @@ Future<bool> isIronwoodActive({required Coin c}) => Future<int> getCurrentHeight({required Coin c}) => RustLib.instance.api.crateApiNetworkGetCurrentHeight(c: c); -Future<double> getCoingeckoPrice( - {required String api, required String currency}) => - RustLib.instance.api - .crateApiNetworkGetCoingeckoPrice(api: api, currency: currency); +Future<double> getCoingeckoPrice({ + required String api, + required String currency, +}) => RustLib.instance.api.crateApiNetworkGetCoingeckoPrice( + api: api, + currency: currency, +); Future<List<String>> getSupportedVsCurrencies({required String api}) => RustLib.instance.api.crateApiNetworkGetSupportedVsCurrencies(api: api); @@ -32,12 +35,15 @@ Future<List<String>> getSupportedVsCurrencies({required String api}) => /// Returns the ZEC price in both `from_currency` and `to_currency`. /// The exchange rate from `from_currency` to `to_currency` can be computed as /// `to_price / from_price`. -Future<ExchangeRate> getExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}) => - RustLib.instance.api.crateApiNetworkGetExchangeRate( - api: api, fromCurrency: fromCurrency, toCurrency: toCurrency); +Future<ExchangeRate> getExchangeRate({ + required String api, + required String fromCurrency, + required String toCurrency, +}) => RustLib.instance.api.crateApiNetworkGetExchangeRate( + api: api, + fromCurrency: fromCurrency, + toCurrency: toCurrency, +); Future<String> getNetworkName({required Coin c}) => RustLib.instance.api.crateApiNetworkGetNetworkName(c: c); @@ -47,6 +53,9 @@ Future<List<LWDInfo>> queryLwdList({required int coin}) => /// True when `url` is a mixnet-native server address /// (`nym://<identity>.<encryption>@<gateway>`). +/// +/// Always exported so the generated bindings do not depend on the `nym` +/// feature; without it no URL is a mixnet address. bool isValidNymUrl({required String url}) => RustLib.instance.api.crateApiNetworkIsValidNymUrl(url: url); diff --git a/lib/src/rust/api/openalias.dart b/lib/src/rust/api/openalias.dart index 417a3f8cd..7901d5a35 100644 --- a/lib/src/rust/api/openalias.dart +++ b/lib/src/rust/api/openalias.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -15,8 +15,10 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// /// Performs DNS TXT lookup, parses OA1 records, filters for Zcash /// addresses, and validates them against the wallet's network type. -Future<OpenAliasResolution> resolveOpenalias( - {required String alias, required Coin c}) => +Future<OpenAliasResolution> resolveOpenalias({ + required String alias, + required Coin c, +}) => RustLib.instance.api.crateApiOpenaliasResolveOpenalias(alias: alias, c: c); /// Resolve an OpenAlias name and return ALL cryptocurrency addresses @@ -34,16 +36,19 @@ bool validateOpenaliasName({required String alias}) => /// /// See [`try_validate_zcash_address`] for the `Result`-returning variant /// that provides error details. -bool validateZcashAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiOpenaliasValidateZcashAddress(address: address, c: c); +bool validateZcashAddress({required String address, required Coin c}) => RustLib + .instance + .api + .crateApiOpenaliasValidateZcashAddress(address: address, c: c); /// Try to validate that an address string is a syntactically valid Zcash /// address for the wallet's network, returning `Ok(())` or an error with /// details about why validation failed. void tryValidateZcashAddress({required String address, required Coin c}) => - RustLib.instance.api - .crateApiOpenaliasTryValidateZcashAddress(address: address, c: c); + RustLib.instance.api.crateApiOpenaliasTryValidateZcashAddress( + address: address, + c: c, + ); /// Get the raw OpenAlias TXT record strings for diagnostic purposes. Future<RawOpenAliasResolution> resolveOpenaliasRaw({required String alias}) => diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index 4de71a5dd..277516897 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -11,30 +11,89 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'pay.freezed.dart'; -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `borrow_decode`, `decode`, `encode` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `borrow_decode`, `clone`, `clone`, `decode`, `encode`, `fmt`, `fmt` Future<String> buildPuri({required List<Recipient> recipients}) => RustLib.instance.api.crateApiPayBuildPuri(recipients: recipients); -Future<PcztPackage> prepare( - {required List<Recipient> recipients, - required PaymentOptions options, - required Coin c}) => - RustLib.instance.api - .crateApiPayPrepare(recipients: recipients, options: options, c: c); +Future<PcztPackage> prepare({ + required List<Recipient> recipients, + required PaymentOptions options, + required Coin c, +}) => RustLib.instance.api.crateApiPayPrepare( + recipients: recipients, + options: options, + c: c, +); /// Prepare a migration transaction (splitting or migrating). /// Uses `migration=true` to allow Orchard outputs when Ironwood is active. -Future<PcztPackage> prepareMigration( - {required List<Recipient> recipients, - required int srcPools, - required Coin c}) => - RustLib.instance.api.crateApiPayPrepareMigration( - recipients: recipients, srcPools: srcPools, c: c); +Future<PcztPackage> prepareMigration({ + required List<Recipient> recipients, + required int srcPools, + required Coin c, +}) => RustLib.instance.api.crateApiPayPrepareMigration( + recipients: recipients, + srcPools: srcPools, + c: c, +); + +Future<PcztPackage> signTransaction({ + required PcztPackage pczt, + required Coin c, +}) => RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); + +/// Proves and finalizes a PCZT signed by an external airgapped signer +/// (Keystone, Cupcake). Uses no spending keys, so it works on watch-only +/// accounts; pass the result to [`extract_transaction`] to broadcast. +Future<PcztPackage> proveAndFinalize({ + required PcztPackage pczt, + required Coin c, +}) => RustLib.instance.api.crateApiPayProveAndFinalize(pczt: pczt, c: c); + +/// Rewrites a PCZT into the encoding a Keystone reads. +/// +/// Cake pins an older `pczt` than the device's firmware, and the two disagree +/// on enough of the v2 layout that each silently misreads the other. Translate +/// on the way out, and [`pczt_from_keystone`] on the way back. +Future<Uint8List> pcztToKeystone({required List<int> pczt}) => + RustLib.instance.api.crateApiPayPcztToKeystone(pczt: pczt); -Future<PcztPackage> signTransaction( - {required PcztPackage pczt, required Coin c}) => - RustLib.instance.api.crateApiPaySignTransaction(pczt: pczt, c: c); +/// Rewrites a PCZT signed by a Keystone back into the encoding Cake uses. +Future<Uint8List> pcztFromKeystone({required List<int> pczt}) => + RustLib.instance.api.crateApiPayPcztFromKeystone(pczt: pczt); + +/// Takes a Keystone's signatures into the PCZT this wallet built. +/// +/// The device redacts prover-only fields, so its reply cannot be proved on its +/// own; `original` supplies those, `signed` supplies only the signatures. +Future<Uint8List> pcztApplyKeystoneSignatures({ + required List<int> original, + required List<int> signed, +}) => RustLib.instance.api.crateApiPayPcztApplyKeystoneSignatures( + original: original, + signed: signed, +); + +/// Builds a `zcash-sign-batch` request for a Keystone from one or more PCZTs in +/// Cake's dialect. +/// +/// The batch path returns only signatures rather than a whole PCZT, so the reply +/// is far smaller over animated QR. It carries shielded spends only; a PCZT with +/// transparent inputs (a shield) must use the single [`pczt_to_keystone`] path. +Future<Uint8List> pcztToBatchRequest({required List<Uint8List> pczts}) => + RustLib.instance.api.crateApiPayPcztToBatchRequest(pczts: pczts); + +/// Takes a Keystone's `zcash-batch-sig-result` reply into the PCZT this wallet +/// built. `original` is the single PCZT sent in the batch; `response` carries +/// only its spend-auth signatures. +Future<Uint8List> pcztApplyBatchSignatures({ + required List<int> original, + required List<int> response, +}) => RustLib.instance.api.crateApiPayPcztApplyBatchSignatures( + original: original, + response: response, +); Future<Uint8List> extractTransaction({required PcztPackage package}) => RustLib.instance.api.crateApiPayExtractTransaction(package: package); @@ -51,26 +110,38 @@ Future<Uint8List> packTransaction({required PcztPackage pczt}) => Future<PcztPackage> unpackTransaction({required List<int> bytes}) => RustLib.instance.api.crateApiPayUnpackTransaction(bytes: bytes); -Future<String> broadcastTransaction( - {required int height, required List<int> txBytes, required Coin c}) => - RustLib.instance.api.crateApiPayBroadcastTransaction( - height: height, txBytes: txBytes, c: c); +Future<String> broadcastTransaction({ + required int height, + required List<int> txBytes, + required Coin c, +}) => RustLib.instance.api.crateApiPayBroadcastTransaction( + height: height, + txBytes: txBytes, + c: c, +); TxPlan toPlan({required PcztPackage package, required Coin c}) => RustLib.instance.api.crateApiPayToPlan(package: package, c: c); -Future<String> send( - {required int height, required List<int> data, required Coin c}) => - RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); - -Future<void> storePendingTx( - {required int height, - required List<int> txid, - double? price, - int? category, - required Coin c}) => - RustLib.instance.api.crateApiPayStorePendingTx( - height: height, txid: txid, price: price, category: category, c: c); +Future<String> send({ + required int height, + required List<int> data, + required Coin c, +}) => RustLib.instance.api.crateApiPaySend(height: height, data: data, c: c); + +Future<void> storePendingTx({ + required int height, + required List<int> txid, + double? price, + int? category, + required Coin c, +}) => RustLib.instance.api.crateApiPayStorePendingTx( + height: height, + txid: txid, + price: price, + category: category, + c: c, +); List<Recipient>? parsePaymentUri({required String uri}) => RustLib.instance.api.crateApiPayParsePaymentUri(uri: uri); @@ -126,10 +197,6 @@ sealed class PcztPackage with _$PcztPackage { sealed class SigningEvent with _$SigningEvent { const SigningEvent._(); - const factory SigningEvent.progress( - String field0, - ) = SigningEvent_Progress; - const factory SigningEvent.result( - PcztPackage field0, - ) = SigningEvent_Result; + const factory SigningEvent.progress(String field0) = SigningEvent_Progress; + const factory SigningEvent.result(PcztPackage field0) = SigningEvent_Result; } diff --git a/lib/src/rust/api/plugin.dart b/lib/src/rust/api/plugin.dart index cc3501b1d..78d243a5e 100644 --- a/lib/src/rust/api/plugin.dart +++ b/lib/src/rust/api/plugin.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -22,18 +22,26 @@ Future<void> removePlugin({required String id, required Coin c}) => RustLib.instance.api.crateApiPluginRemovePlugin(id: id, c: c); /// Enable or disable a plugin. -Future<void> setPluginEnabled( - {required String id, required bool enabled, required Coin c}) => - RustLib.instance.api - .crateApiPluginSetPluginEnabled(id: id, enabled: enabled, c: c); +Future<void> setPluginEnabled({ + required String id, + required bool enabled, + required Coin c, +}) => RustLib.instance.api.crateApiPluginSetPluginEnabled( + id: id, + enabled: enabled, + c: c, +); /// Parse a memo with all matching plugins. /// `memo_bytes` is the full 512-byte memo (including the 0xFF type byte). /// Returns sections from all plugins whose prefixes match. -Future<List<MemoSection>> parseMemoWithPlugins( - {required List<int> memoBytes, required Coin c}) => - RustLib.instance.api - .crateApiPluginParseMemoWithPlugins(memoBytes: memoBytes, c: c); +Future<List<MemoSection>> parseMemoWithPlugins({ + required List<int> memoBytes, + required Coin c, +}) => RustLib.instance.api.crateApiPluginParseMemoWithPlugins( + memoBytes: memoBytes, + c: c, +); /// Initialize the plugin system at app startup (creates plugins directory). void initPlugins() => RustLib.instance.api.crateApiPluginInitPlugins(); @@ -41,18 +49,14 @@ void initPlugins() => RustLib.instance.api.crateApiPluginInitPlugins(); /// A single typed cell in a memo table. @freezed sealed class MemoCell with _$MemoCell { - const factory MemoCell({ - required String cellType, - required String value, - }) = _MemoCell; + const factory MemoCell({required String cellType, required String value}) = + _MemoCell; } /// A row of cells in a memo section. @freezed sealed class MemoRow with _$MemoRow { - const factory MemoRow({ - required List<MemoCell> cells, - }) = _MemoRow; + const factory MemoRow({required List<MemoCell> cells}) = _MemoRow; } /// A parsed memo section — a titled table. diff --git a/lib/src/rust/api/raptor.dart b/lib/src/rust/api/raptor.dart index d56383f0f..e2102fd9f 100644 --- a/lib/src/rust/api/raptor.dart +++ b/lib/src/rust/api/raptor.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -8,9 +8,10 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `ec_level_of` -Future<List<Uint8List>> encode( - {required String path, required RaptorQParams params}) => - RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); +Future<List<Uint8List>> encode({ + required String path, + required RaptorQParams params, +}) => RustLib.instance.api.crateApiRaptorEncode(path: path, params: params); Uint8List getQrBytes({required List<int> data}) => RustLib.instance.api.crateApiRaptorGetQrBytes(data: data); diff --git a/lib/src/rust/api/sapling.dart b/lib/src/rust/api/sapling.dart index 0a9b7ba5c..95076bcae 100644 --- a/lib/src/rust/api/sapling.dart +++ b/lib/src/rust/api/sapling.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -28,9 +28,7 @@ Future<void> downloadSaplingParams() => class SaplingParamsStatus { final bool downloaded; - const SaplingParamsStatus({ - required this.downloaded, - }); + const SaplingParamsStatus({required this.downloaded}); @override int get hashCode => downloaded.hashCode; diff --git a/lib/src/rust/api/sweep.dart b/lib/src/rust/api/sweep.dart index 5dd6ab3ba..b9def5cbc 100644 --- a/lib/src/rust/api/sweep.dart +++ b/lib/src/rust/api/sweep.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -15,6 +15,9 @@ abstract class TransparentScanner implements RustOpaqueInterface { static Future<TransparentScanner> newInstance() => RustLib.instance.api.crateApiSweepTransparentScannerNew(); - Stream<String> run( - {required int endHeight, required int gapLimit, required Coin c}); + Stream<String> run({ + required int endHeight, + required int gapLimit, + required Coin c, + }); } diff --git a/lib/src/rust/api/sync.dart b/lib/src/rust/api/sync.dart index 8ef4d3d88..48093471a 100644 --- a/lib/src/rust/api/sync.dart +++ b/lib/src/rust/api/sync.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -10,32 +10,38 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `fmt` -Stream<SyncProgress> synchronize( - {required List<int> accounts, - required int currentHeight, - required int actionsPerSync, - required int transparentLimit, - required int checkpointAge, - required bool fast, - required Coin c}) => - RustLib.instance.api.crateApiSyncSynchronize( - accounts: accounts, - currentHeight: currentHeight, - actionsPerSync: actionsPerSync, - transparentLimit: transparentLimit, - checkpointAge: checkpointAge, - fast: fast, - c: c); +Stream<SyncProgress> synchronize({ + required List<int> accounts, + required int currentHeight, + required int actionsPerSync, + required int transparentLimit, + required int checkpointAge, + required bool fast, + required Coin c, +}) => RustLib.instance.api.crateApiSyncSynchronize( + accounts: accounts, + currentHeight: currentHeight, + actionsPerSync: actionsPerSync, + transparentLimit: transparentLimit, + checkpointAge: checkpointAge, + fast: fast, + c: c, +); Future<PoolBalance> balance({required Coin c}) => RustLib.instance.api.crateApiSyncBalance(c: c); Future<void> cancelSync() => RustLib.instance.api.crateApiSyncCancelSync(); -Future<void> rewindSync( - {required int height, required int account, required Coin c}) => - RustLib.instance.api - .crateApiSyncRewindSync(height: height, account: account, c: c); +Future<void> rewindSync({ + required int height, + required int account, + required Coin c, +}) => RustLib.instance.api.crateApiSyncRewindSync( + height: height, + account: account, + c: c, +); Future<SyncHeight> getDbHeight({required Coin c}) => RustLib.instance.api.crateApiSyncGetDbHeight(c: c); @@ -57,9 +63,7 @@ Future<void> cacheBlockTime({required int height, required Coin c}) => class PoolBalance { final Uint64List field0; - const PoolBalance({ - required this.field0, - }); + const PoolBalance({required this.field0}); @override int get hashCode => field0.hashCode; @@ -76,10 +80,7 @@ class SyncProgress { final int height; final int time; - const SyncProgress({ - required this.height, - required this.time, - }); + const SyncProgress({required this.height, required this.time}); @override int get hashCode => height.hashCode ^ time.hashCode; diff --git a/lib/src/rust/api/transaction.dart b/lib/src/rust/api/transaction.dart index 4702254f7..644a685e4 100644 --- a/lib/src/rust/api/transaction.dart +++ b/lib/src/rust/api/transaction.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -7,36 +7,65 @@ import '../frb_generated.dart'; import 'coin.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -Future<int> fillMissingTxPrices( - {required String api, required String currency, required Coin c}) => - RustLib.instance.api.crateApiTransactionFillMissingTxPrices( - api: api, currency: currency, c: c); +Future<int> fillMissingTxPrices({ + required String api, + required String currency, + required Coin c, +}) => RustLib.instance.api.crateApiTransactionFillMissingTxPrices( + api: api, + currency: currency, + c: c, +); -Future<void> updateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}) => - RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices( - currency: currency, exchangeRate: exchangeRate, c: c); +Future<void> updateHistoricalPrices({ + required String currency, + required double exchangeRate, + required Coin c, +}) => RustLib.instance.api.crateApiTransactionUpdateHistoricalPrices( + currency: currency, + exchangeRate: exchangeRate, + c: c, +); Future<void> setUserMemo({required int idTx, String? memo, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetUserMemo(idTx: idTx, memo: memo, c: c); + RustLib.instance.api.crateApiTransactionSetUserMemo( + idTx: idTx, + memo: memo, + c: c, + ); Future<void> setTxCategory({required int id, int? category, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetTxCategory(id: id, category: category, c: c); + RustLib.instance.api.crateApiTransactionSetTxCategory( + id: id, + category: category, + c: c, + ); Future<void> setTxPrice({required int id, double? price, required Coin c}) => - RustLib.instance.api - .crateApiTransactionSetTxPrice(id: id, price: price, c: c); - -Future<List<(String, double, bool)>> fetchCategoryAmounts( - {int? from, int? to, required Coin c}) => - RustLib.instance.api - .crateApiTransactionFetchCategoryAmounts(from: from, to: to, c: c); - -Future<List<(int, double)>> fetchAmounts( - {int? from, int? to, required int category, required Coin c}) => - RustLib.instance.api.crateApiTransactionFetchAmounts( - from: from, to: to, category: category, c: c); + RustLib.instance.api.crateApiTransactionSetTxPrice( + id: id, + price: price, + c: c, + ); + +Future<List<(String, double, bool)>> fetchCategoryAmounts({ + int? from, + int? to, + required Coin c, +}) => RustLib.instance.api.crateApiTransactionFetchCategoryAmounts( + from: from, + to: to, + c: c, +); + +Future<List<(int, double)>> fetchAmounts({ + int? from, + int? to, + required int category, + required Coin c, +}) => RustLib.instance.api.crateApiTransactionFetchAmounts( + from: from, + to: to, + category: category, + c: c, +); diff --git a/lib/src/rust/api/vault.dart b/lib/src/rust/api/vault.dart index 5b8532f0a..416a192f8 100644 --- a/lib/src/rust/api/vault.dart +++ b/lib/src/rust/api/vault.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -8,37 +8,45 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` -Future<DartVault> initVault( - {required FutureOr<void> Function(Uint8List) append}) => - RustLib.instance.api.crateApiVaultInitVault(append: append); +Future<DartVault> initVault({ + required FutureOr<void> Function(Uint8List) append, +}) => RustLib.instance.api.crateApiVaultInitVault(append: append); // Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<DartVault>> abstract class DartVault implements RustOpaqueInterface { - Future<List<RestoredAccount>> recover( - {required List<int> vaultBytes, required String masterPassword}); + Future<List<RestoredAccount>> recover({ + required List<int> vaultBytes, + required String masterPassword, + }); - Future<List<RestoredAccount>> recoverWithPrf( - {required List<int> vaultBytes, - required String deviceIdStr, - required List<int> prfOutput}); + Future<List<RestoredAccount>> recoverWithPrf({ + required List<int> vaultBytes, + required String deviceIdStr, + required List<int> prfOutput, + }); - Future<void> registerDevice( - {required List<int> initBytes, - required String masterPassword, - required String deviceIdStr, - required List<int> prfOutput}); + Future<void> registerDevice({ + required List<int> initBytes, + required String masterPassword, + required String deviceIdStr, + required List<int> prfOutput, + }); - Future<Uint8List> setMasterPassword( - {String? oldPassword, required String newPassword, Uint8List? oldBytes}); + Future<Uint8List> setMasterPassword({ + String? oldPassword, + required String newPassword, + Uint8List? oldBytes, + }); - Future<void> storeAccount( - {required int timestamp, - required String name, - required String seed, - required int aindex, - required bool useInternal, - required int birthHeight, - required List<int> pk}); + Future<void> storeAccount({ + required int timestamp, + required String name, + required String seed, + required int aindex, + required bool useInternal, + required int birthHeight, + required List<int> pk, + }); Future<void> test(); } diff --git a/lib/src/rust/api/voting.dart b/lib/src/rust/api/voting.dart index a3cd66111..0c7bb7ad2 100644 --- a/lib/src/rust/api/voting.dart +++ b/lib/src/rust/api/voting.dart @@ -28,77 +28,86 @@ Future<String> votingHotkeyGet({required Coin c}) => /// witnesses are rooted at the snapshot's Ironwood `nc_root`. On success the /// round inputs are persisted (props table) so a restart can re-prepare via /// [`delegation_prepare_resume`]. -Future<VotingPreparedInfo> delegationPrepare( - {required String roundParamsJson, - required String roundName, - String? sessionJson, - required int bundleIndex, - int? maxRealNotesPerBundle, - required String lightwalletdUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationPrepare( - roundParamsJson: roundParamsJson, - roundName: roundName, - sessionJson: sessionJson, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl, - c: c); +Future<VotingPreparedInfo> delegationPrepare({ + required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationPrepare( + roundParamsJson: roundParamsJson, + roundName: roundName, + sessionJson: sessionJson, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c, +); /// Re-runs [`delegation_prepare`] for a round whose prepared bundle was lost /// with the process (the prepared-bundle cache is process-local). Inputs come /// from the config saved by the first prepare; the optional params override /// the saved values when present. -Future<VotingPreparedInfo> delegationPrepareResume( - {required String roundId, - required int bundleIndex, - int? maxRealNotesPerBundle, - String? lightwalletdUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationPrepareResume( - roundId: roundId, - bundleIndex: bundleIndex, - maxRealNotesPerBundle: maxRealNotesPerBundle, - lightwalletdUrl: lightwalletdUrl, - c: c); +Future<VotingPreparedInfo> delegationPrepareResume({ + required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationPrepareResume( + roundId: roundId, + bundleIndex: bundleIndex, + maxRealNotesPerBundle: maxRealNotesPerBundle, + lightwalletdUrl: lightwalletdUrl, + c: c, +); /// Builds and persists the governance PCZT setup for a prepared bundle. -Future<VotingDelegationSetup> delegationSetup( - {required String roundId, required int bundleIndex, required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationSetup( - roundId: roundId, bundleIndex: bundleIndex, c: c); +Future<VotingDelegationSetup> delegationSetup({ + required String roundId, + required int bundleIndex, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationSetup( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, +); /// Signs with the wallet seed, proves against the PIR server, and assembles /// the chain-ready delegation submission for the vote chain. -Future<VotingDelegationSubmission> delegationSignAndSubmit( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - required VotingPirLayout pirLayout, - required String pirServerUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationSignAndSubmit( - roundId: roundId, - bundleIndex: bundleIndex, - pcztBytes: pcztBytes, - pirLayout: pirLayout, - pirServerUrl: pirServerUrl, - c: c); +Future<VotingDelegationSubmission> delegationSignAndSubmit({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationSignAndSubmit( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: pcztBytes, + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c, +); /// Records a confirmed delegation transaction and persists the bundle's VAN /// position (required before any vote). -Future<VotingDelegationConfirmation> delegationConfirm( - {required String roundId, - required int bundleIndex, - required String txHash, - required String eventsJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationConfirm( - roundId: roundId, - bundleIndex: bundleIndex, - txHash: txHash, - eventsJson: eventsJson, - c: c); +Future<VotingDelegationConfirmation> delegationConfirm({ + required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: txHash, + eventsJson: eventsJson, + c: c, +); /// Builds and signs the delegation payload with live progress events /// (`delegation_sign_and_submit` without the progress stream). @@ -106,79 +115,101 @@ Future<VotingDelegationConfirmation> delegationConfirm( /// `pir_layout` is persisted on first use; pass `None` after a restart to /// resume with the saved layout. Returns the submission together with its /// vote-chain wire JSON body (ready for `votechain_submit_delegation`). -Stream<VotingDelegationProgress> delegationBuildSubmission( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - VotingPirLayout? pirLayout, - required String pirServerUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationBuildSubmission( - roundId: roundId, - bundleIndex: bundleIndex, - pcztBytes: pcztBytes, - pirLayout: pirLayout, - pirServerUrl: pirServerUrl, - c: c); +Stream<VotingDelegationProgress> delegationBuildSubmission({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationBuildSubmission( + roundId: roundId, + bundleIndex: bundleIndex, + pcztBytes: pcztBytes, + pirLayout: pirLayout, + pirServerUrl: pirServerUrl, + c: c, +); /// Returns the vote-chain wire JSON built by the last /// [`delegation_build_submission`] run for a bundle, if any. -Future<String?> delegationWireJson( - {required String roundId, required int bundleIndex, required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationWireJson( - roundId: roundId, bundleIndex: bundleIndex, c: c); +Future<String?> delegationWireJson({ + required String roundId, + required int bundleIndex, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, +); /// Atomically records a delegation transaction hash with idempotency checks, /// so a restart between broadcast and confirmation resumes via `PollDelegation` /// instead of re-broadcasting. -Future<void> delegationMarkSubmitted( - {required String roundId, - required int bundleIndex, - required String txHash, - required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationMarkSubmitted( - roundId: roundId, bundleIndex: bundleIndex, txHash: txHash, c: c); +Future<void> delegationMarkSubmitted({ + required String roundId, + required int bundleIndex, + required String txHash, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationMarkSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + txHash: txHash, + c: c, +); /// Returns the recorded delegation transaction hash for a bundle, if any. -Future<String?> delegationTxHash( - {required String roundId, required int bundleIndex, required Coin c}) => - RustLib.instance.api.crateApiVotingDelegationTxHash( - roundId: roundId, bundleIndex: bundleIndex, c: c); +Future<String?> delegationTxHash({ + required String roundId, + required int bundleIndex, + required Coin c, +}) => RustLib.instance.api.crateApiVotingDelegationTxHash( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, +); /// Persists the voter's terminal decision for one proposal before any /// zero-knowledge work, so a crash cannot lose the ballot and later votes are /// conflict-checked against it. -Future<void> votingSetBallotIntent( - {required String roundId, - required int proposalId, - required bool skipped, - required int choice, - required int numOptions, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingSetBallotIntent( - roundId: roundId, - proposalId: proposalId, - skipped: skipped, - choice: choice, - numOptions: numOptions, - c: c); +Future<void> votingSetBallotIntent({ + required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSetBallotIntent( + roundId: roundId, + proposalId: proposalId, + skipped: skipped, + choice: choice, + numOptions: numOptions, + c: c, +); /// Returns the quantized voting weight (zatoshi) for the account's eligible /// shielded notes at `snapshot_height`, computed with the same canonical /// bundle planning as the delegation prepare step — but from the local DB /// only (no witnesses, no tree state). Shown pre-submission as an estimate. -Future<BigInt> votingEligibleWeight( - {required int snapshotHeight, required Coin c}) => - RustLib.instance.api.crateApiVotingVotingEligibleWeight( - snapshotHeight: snapshotHeight, c: c); +Future<BigInt> votingEligibleWeight({ + required int snapshotHeight, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingEligibleWeight( + snapshotHeight: snapshotHeight, + c: c, +); /// Persists the draft ballot for a round (props table, wallet-scoped). -Future<void> votingDraftsSave( - {required String roundId, - required String draftsJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingDraftsSave( - roundId: roundId, draftsJson: draftsJson, c: c); +Future<void> votingDraftsSave({ + required String roundId, + required String draftsJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingDraftsSave( + roundId: roundId, + draftsJson: draftsJson, + c: c, +); /// Returns the persisted draft ballot for a round, if any. Future<String?> votingDraftsLoad({required String roundId, required Coin c}) => @@ -187,173 +218,191 @@ Future<String?> votingDraftsLoad({required String roundId, required Coin c}) => /// Commits one bundle's votes with live stage events. Draft votes are /// JSON-serialized fork `DraftVote`s; the VAN witness is derived internally /// after syncing the vote tree. -Stream<VotingVoteCommitStage> votingCommitWithProgress( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingCommitWithProgress( - roundId: roundId, - bundleIndex: bundleIndex, - draftsJson: draftsJson, - voteNodeUrl: voteNodeUrl, - c: c); +Stream<VotingVoteCommitStage> votingCommitWithProgress({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingCommitWithProgress( + roundId: roundId, + bundleIndex: bundleIndex, + draftsJson: draftsJson, + voteNodeUrl: voteNodeUrl, + c: c, +); /// Reconstructs the chain-ready wire JSON for a committed vote. -Future<String> votingVoteWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingVoteWireJson( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - c: c); +Future<String> votingVoteWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingVoteWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, +); /// Atomically records a cast-vote transaction hash with idempotency checks, so /// a restart between broadcast and confirmation resumes via `PollVote`. -Future<void> votingMarkVoteSubmitted( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingMarkVoteSubmitted( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - txHash: txHash, - c: c); +Future<void> votingMarkVoteSubmitted({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingMarkVoteSubmitted( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + c: c, +); /// Records a helper-share submission (derives the nullifier from recovery /// state). -Future<void> votingShareRecord( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> sentToUrls, - required BigInt submitAt, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingShareRecord( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - shareIndex: shareIndex, - sentToUrls: sentToUrls, - submitAt: submitAt, - c: c); +Future<void> votingShareRecord({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> sentToUrls, + required BigInt submitAt, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingShareRecord( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + sentToUrls: sentToUrls, + submitAt: submitAt, + c: c, +); /// Lists unconfirmed helper-share records for a round. -Future<List<VotingShareDelegationRecord>> votingShareUnconfirmed( - {required String roundId, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingShareUnconfirmed(roundId: roundId, c: c); +Future<List<VotingShareDelegationRecord>> votingShareUnconfirmed({ + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingShareUnconfirmed( + roundId: roundId, + c: c, +); /// Marks one helper-share record confirmed. -Future<void> votingShareConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingShareConfirm( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - shareIndex: shareIndex, - c: c); +Future<void> votingShareConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingShareConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + c: c, +); /// Adds helper URLs to an existing share record after resubmission. -Future<void> votingShareAddServers( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> newUrls, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingShareAddServers( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - shareIndex: shareIndex, - newUrls: newUrls, - c: c); +Future<void> votingShareAddServers({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> newUrls, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingShareAddServers( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + newUrls: newUrls, + c: c, +); /// Reconstructs one helper-share payload as helper wire JSON from the /// persisted commitment bundle. -Future<String> votingShareWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - BigInt? vcTreePosition, - required BigInt submitAt, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingShareWireJson( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - shareIndex: shareIndex, - vcTreePosition: vcTreePosition, - submitAt: submitAt, - c: c); +Future<String> votingShareWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingShareWireJson( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + shareIndex: shareIndex, + vcTreePosition: vcTreePosition, + submitAt: submitAt, + c: c, +); /// Best-effort pre-sync of the vote commitment tree for a round, returning /// the latest synced tree height. Requires the round to exist locally (it is /// created by the first prepare); callers may ignore failures. -Future<int> votingSyncTree( - {required String roundId, - required String voteNodeUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingSyncTree( - roundId: roundId, voteNodeUrl: voteNodeUrl, c: c); +Future<int> votingSyncTree({ + required String roundId, + required String voteNodeUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSyncTree( + roundId: roundId, + voteNodeUrl: voteNodeUrl, + c: c, +); /// Enumerates the share payloads of the round's confirmed votes — the /// first-pass submission source. -Future<List<VotingShareSubmissionPayload>> votingSharePayloads( - {required String roundId, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingSharePayloads(roundId: roundId, c: c); +Future<List<VotingShareSubmissionPayload>> votingSharePayloads({ + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSharePayloads( + roundId: roundId, + c: c, +); /// Count-based share submission plans (submitAt + target servers per share), /// mirroring vizor's `planShareSubmissions`: policy-sized CSPRNG entropy /// drawn per call, timing from the round's ceremony start / vote end. -Future<List<VotingSharePlanItem>> votingSharePlans( - {required int shareCount, - required List<String> serverUrls, - required BigInt now, - required BigInt voteEnd, - required BigInt ceremonyStart, - required bool singleShare, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingSharePlans( - shareCount: shareCount, - serverUrls: serverUrls, - now: now, - voteEnd: voteEnd, - ceremonyStart: ceremonyStart, - singleShare: singleShare, - c: c); - -Future<VotingSharePlan> votingSharePlan( - {required String roundId, - required BigInt now, - required BigInt ceremonyStart, - BigInt? voteEnd, - required List<String> serverUrls, - required bool singleShare, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingSharePlan( - roundId: roundId, - now: now, - ceremonyStart: ceremonyStart, - voteEnd: voteEnd, - serverUrls: serverUrls, - singleShare: singleShare, - c: c); +Future<List<VotingSharePlanItem>> votingSharePlans({ + required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSharePlans( + shareCount: shareCount, + serverUrls: serverUrls, + now: now, + voteEnd: voteEnd, + ceremonyStart: ceremonyStart, + singleShare: singleShare, + c: c, +); + +Future<VotingSharePlan> votingSharePlan({ + required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List<String> serverUrls, + required bool singleShare, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSharePlan( + roundId: roundId, + now: now, + ceremonyStart: ceremonyStart, + voteEnd: voteEnd, + serverUrls: serverUrls, + singleShare: singleShare, + c: c, +); /// Resolves and authenticates the voting config for a source URL. /// @@ -362,188 +411,211 @@ Future<VotingSharePlan> votingSharePlan( /// the config switch against the previously resolved summary. The result is /// cached in the props table so [`voting_config_cached`] can serve as a /// last-good fallback. -Future<VotingConfig> votingConfigResolve( - {required String source, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingConfigResolve(source: source, c: c); +Future<VotingConfig> votingConfigResolve({ + required String source, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingConfigResolve( + source: source, + c: c, +); /// Returns the last cached resolved config for a source URL, if any. -Future<VotingConfig?> votingConfigCached( - {required String source, required Coin c}) => +Future<VotingConfig?> votingConfigCached({ + required String source, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingConfigCached(source: source, c: c); /// Builds the round params JSON for `delegation_prepare` from the cached /// authenticated config plus chain-reported snapshot fields (`ea_pk` is /// pinned to the authenticated config, so a stale endpoint cannot steer /// voting to the wrong authority or roots). -Future<String> votingRoundParamsJson( - {required String source, - required String roundId, - required BigInt snapshotHeight, - required List<int> ncRoot, - required List<int> nullifierImtRoot, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingRoundParamsJson( - source: source, - roundId: roundId, - snapshotHeight: snapshotHeight, - ncRoot: ncRoot, - nullifierImtRoot: nullifierImtRoot, - c: c); +Future<String> votingRoundParamsJson({ + required String source, + required String roundId, + required BigInt snapshotHeight, + required List<int> ncRoot, + required List<int> nullifierImtRoot, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingRoundParamsJson( + source: source, + roundId: roundId, + snapshotHeight: snapshotHeight, + ncRoot: ncRoot, + nullifierImtRoot: nullifierImtRoot, + c: c, +); /// Clears the cached resolved configs (all sources). Future<void> votingConfigClearCache({required Coin c}) => RustLib.instance.api.crateApiVotingVotingConfigClearCache(c: c); /// Syncs the vote-authority-note tree and derives this bundle's VAN witness. -Future<VotingVanWitness> votingVanWitness( - {required String roundId, - required int bundleIndex, - required String voteNodeUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingVanWitness( - roundId: roundId, - bundleIndex: bundleIndex, - voteNodeUrl: voteNodeUrl, - c: c); +Future<VotingVanWitness> votingVanWitness({ + required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingVanWitness( + roundId: roundId, + bundleIndex: bundleIndex, + voteNodeUrl: voteNodeUrl, + c: c, +); /// Commits a batch of vote drafts for one bundle (hotkey-signed). /// /// Chains the VAN witness derivation internally, so this may be called right /// after `voting_van_witness` or standalone. -Future<VotingVoteCommitments> votingCommit( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingCommit( - roundId: roundId, - bundleIndex: bundleIndex, - draftsJson: draftsJson, - voteNodeUrl: voteNodeUrl, - c: c); +Future<VotingVoteCommitments> votingCommit({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingCommit( + roundId: roundId, + bundleIndex: bundleIndex, + draftsJson: draftsJson, + voteNodeUrl: voteNodeUrl, + c: c, +); /// Returns the chain-ready vote submission and helper-share payloads for one /// committed vote. -Future<VotingVotePayloads> votingPayloads( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingPayloads( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - c: c); +Future<VotingVotePayloads> votingPayloads({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingPayloads( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, +); /// Records successful vote-chain and helper-share submissions for one vote. -Future<void> votingRecordExecution( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String voteTxHash, - required BigInt vcTreePosition, - required String shareDeliveriesJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingRecordExecution( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - voteTxHash: voteTxHash, - vcTreePosition: vcTreePosition, - shareDeliveriesJson: shareDeliveriesJson, - c: c); +Future<void> votingRecordExecution({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingRecordExecution( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + voteTxHash: voteTxHash, + vcTreePosition: vcTreePosition, + shareDeliveriesJson: shareDeliveriesJson, + c: c, +); /// Records a confirmed cast-vote transaction. -Future<VotingVoteConfirmation> votingConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required String eventsJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingConfirm( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - txHash: txHash, - eventsJson: eventsJson, - c: c); +Future<VotingVoteConfirmation> votingConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingConfirm( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + txHash: txHash, + eventsJson: eventsJson, + c: c, +); /// Hex-encoded vote commitment leaf value for one committed vote, used to /// locate the vote's commitment-tree leaf when the tx hash is unknown. -Future<String> votingVoteCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingVoteCommitmentHex( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - c: c); +Future<String> votingVoteCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingVoteCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, +); /// Hex-encoded cast-vote VAN output commitment for one committed vote (the /// commitment-tree leaf appended immediately before the vote commitment). -Future<String> votingVoteVanCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingVoteVanCommitmentHex( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - c: c); +Future<String> votingVoteVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingVoteVanCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + c: c, +); /// Hex-encoded delegation VAN commitment (`gov_comm`) for a bundle, or `None` /// when it was never persisted. Used to locate the delegation's tree leaf. -Future<String?> votingDelegationVanCommitmentHex( - {required String roundId, required int bundleIndex, required Coin c}) => - RustLib.instance.api.crateApiVotingVotingDelegationVanCommitmentHex( - roundId: roundId, bundleIndex: bundleIndex, c: c); +Future<String?> votingDelegationVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingDelegationVanCommitmentHex( + roundId: roundId, + bundleIndex: bundleIndex, + c: c, +); /// Scans the round's commitment tree for a leaf matching `target_hex` and /// returns its global position, or `None` when absent. -Future<BigInt?> votingTreeFindLeaf( - {required String roundId, - required String nodeUrl, - required String targetHex}) => - RustLib.instance.api.crateApiVotingVotingTreeFindLeaf( - roundId: roundId, nodeUrl: nodeUrl, targetHex: targetHex); +Future<BigInt?> votingTreeFindLeaf({ + required String roundId, + required String nodeUrl, + required String targetHex, +}) => RustLib.instance.api.crateApiVotingVotingTreeFindLeaf( + roundId: roundId, + nodeUrl: nodeUrl, + targetHex: targetHex, +); /// Records a cast-vote confirmation whose evidence came from a /// commitment-tree scan (no tx hash available). The vote's phase becomes /// Confirmed so the resume plan proceeds to share submission. -Future<VotingTreeVoteConfirmation> votingRecoverConfirmVoteFromTree( - {required String roundId, - required int bundleIndex, - required int proposalId, - required BigInt vcTreePosition, - int? vanLeafPosition, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingRecoverConfirmVoteFromTree( - roundId: roundId, - bundleIndex: bundleIndex, - proposalId: proposalId, - vcTreePosition: vcTreePosition, - vanLeafPosition: vanLeafPosition, - c: c); +Future<VotingTreeVoteConfirmation> votingRecoverConfirmVoteFromTree({ + required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingRecoverConfirmVoteFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + proposalId: proposalId, + vcTreePosition: vcTreePosition, + vanLeafPosition: vanLeafPosition, + c: c, +); /// Records a delegation confirmation recovered from a commitment-tree scan /// (no tx hash available). The bundle's phase becomes Confirmed so voting can /// proceed. -Future<void> votingRecoverConfirmDelegationFromTree( - {required String roundId, - required int bundleIndex, - required int vanLeafPosition, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingRecoverConfirmDelegationFromTree( - roundId: roundId, - bundleIndex: bundleIndex, - vanLeafPosition: vanLeafPosition, - c: c); +Future<void> votingRecoverConfirmDelegationFromTree({ + required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingRecoverConfirmDelegationFromTree( + roundId: roundId, + bundleIndex: bundleIndex, + vanLeafPosition: vanLeafPosition, + c: c, +); /// Lists rounds persisted in the voting DB for the current wallet. Future<List<VotingRoundInfo>> votingRounds({required Coin c}) => @@ -552,112 +624,160 @@ Future<List<VotingRoundInfo>> votingRounds({required Coin c}) => /// Returns the derived resume plan for a round (the ordered work that remains /// after any restart; empty `next_steps` with `primary_action == "done"` means /// the round is complete for this wallet). -Future<VotingRoundPlan> votingPlan( - {required String roundId, - required List<int> proposalIds, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotingPlan( - roundId: roundId, proposalIds: proposalIds, c: c); +Future<VotingRoundPlan> votingPlan({ + required String roundId, + required List<int> proposalIds, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingPlan( + roundId: roundId, + proposalIds: proposalIds, + c: c, +); /// Returns the full read-only recovery snapshot for a round. -Future<VotingRoundRecovery> votingRecovery( - {required String roundId, required Coin c}) => - RustLib.instance.api.crateApiVotingVotingRecovery(roundId: roundId, c: c); +Future<VotingRoundRecovery> votingRecovery({ + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingRecovery(roundId: roundId, c: c); /// Clears unconfirmed recovery artifacts for a round. Ballot intents, recorded /// confirmations, and imported delegation capabilities are preserved. Future<void> votingRecoveryClear({required String roundId, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingRecoveryClear(roundId: roundId, c: c); + RustLib.instance.api.crateApiVotingVotingRecoveryClear( + roundId: roundId, + c: c, + ); /// Resets process-local vote-tree cache and clears unsigned delegation setup /// fields for a round (the fork's recovery when a restart after /// `build_governance_pczt` persisted `pczt_sighash` makes re-setup refuse to /// overwrite it). Submitted bundles, imported capabilities, and bundles with /// persisted Keystone signatures are preserved. -Future<void> votingResetSessionState( - {required String roundId, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingResetSessionState(roundId: roundId, c: c); +Future<void> votingResetSessionState({ + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingResetSessionState( + roundId: roundId, + c: c, +); /// Returns the persisted ballot intents for a round, sorted by proposal id. -Future<List<VotingBallotIntent>> votingBallotIntents( - {required String roundId, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotingBallotIntents(roundId: roundId, c: c); +Future<List<VotingBallotIntent>> votingBallotIntents({ + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingBallotIntents( + roundId: roundId, + c: c, +); /// Loads sessions for many rounds in a single Rust call that holds ONE pool /// connection (the per-round entry points above would need one connection per /// round and stall the pool once the page has many rounds). -Future<List<VotingRoundSession>> votingSessions( - {required List<String> roundIds, required Coin c}) => +Future<List<VotingRoundSession>> votingSessions({ + required List<String> roundIds, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotingSessions(roundIds: roundIds, c: c); /// Lists rounds from the vote server (`{ "rounds": [...] }`). -Future<VotingChainResponse> votechainListRounds( - {required String baseUrl, required Coin c}) => - RustLib.instance.api - .crateApiVotingVotechainListRounds(baseUrl: baseUrl, c: c); +Future<VotingChainResponse> votechainListRounds({ + required String baseUrl, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainListRounds( + baseUrl: baseUrl, + c: c, +); /// Fetches one round's status (`{ "round": ... }` envelope). -Future<VotingChainResponse> votechainRoundStatus( - {required String baseUrl, required String roundId, required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainRoundStatus( - baseUrl: baseUrl, roundId: roundId, c: c); +Future<VotingChainResponse> votechainRoundStatus({ + required String baseUrl, + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainRoundStatus( + baseUrl: baseUrl, + roundId: roundId, + c: c, +); /// Fetches the round tally envelope. -Future<VotingChainResponse> votechainRoundTally( - {required String baseUrl, required String roundId, required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainRoundTally( - baseUrl: baseUrl, roundId: roundId, c: c); +Future<VotingChainResponse> votechainRoundTally({ + required String baseUrl, + required String roundId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainRoundTally( + baseUrl: baseUrl, + roundId: roundId, + c: c, +); /// Broadcasts a delegation transaction to the vote chain. -Future<VotingChainResponse> votechainSubmitDelegation( - {required String baseUrl, - required String submissionJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainSubmitDelegation( - baseUrl: baseUrl, submissionJson: submissionJson, c: c); +Future<VotingChainResponse> votechainSubmitDelegation({ + required String baseUrl, + required String submissionJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainSubmitDelegation( + baseUrl: baseUrl, + submissionJson: submissionJson, + c: c, +); /// Broadcasts a vote commitment transaction to the vote chain. -Future<VotingChainResponse> votechainSubmitVote( - {required String baseUrl, - required String submissionJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainSubmitVote( - baseUrl: baseUrl, submissionJson: submissionJson, c: c); +Future<VotingChainResponse> votechainSubmitVote({ + required String baseUrl, + required String submissionJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainSubmitVote( + baseUrl: baseUrl, + submissionJson: submissionJson, + c: c, +); /// Fetches the on-chain confirmation for a transaction; 404 = not confirmed. -Future<VotingChainResponse> votechainTxConfirmation( - {required String baseUrl, required String txHash, required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainTxConfirmation( - baseUrl: baseUrl, txHash: txHash, c: c); +Future<VotingChainResponse> votechainTxConfirmation({ + required String baseUrl, + required String txHash, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainTxConfirmation( + baseUrl: baseUrl, + txHash: txHash, + c: c, +); /// Posts one encrypted share to a helper server. -Future<VotingChainResponse> votechainSubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainSubmitShare( - serverUrl: serverUrl, payloadJson: payloadJson, c: c); +Future<VotingChainResponse> votechainSubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainSubmitShare( + serverUrl: serverUrl, + payloadJson: payloadJson, + c: c, +); /// Resends a previously generated share to a helper server (same endpoint as /// the initial submission). -Future<VotingChainResponse> votechainResubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainResubmitShare( - serverUrl: serverUrl, payloadJson: payloadJson, c: c); +Future<VotingChainResponse> votechainResubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainResubmitShare( + serverUrl: serverUrl, + payloadJson: payloadJson, + c: c, +); /// Checks whether a helper has confirmed a share identified by its nullifier. -Future<VotingChainResponse> votechainShareStatus( - {required String serverUrl, - required String roundId, - required String shareId, - required Coin c}) => - RustLib.instance.api.crateApiVotingVotechainShareStatus( - serverUrl: serverUrl, roundId: roundId, shareId: shareId, c: c); +Future<VotingChainResponse> votechainShareStatus({ + required String serverUrl, + required String roundId, + required String shareId, + required Coin c, +}) => RustLib.instance.api.crateApiVotingVotechainShareStatus( + serverUrl: serverUrl, + roundId: roundId, + shareId: shareId, + c: c, +); /// The voter's terminal decision for one proposal. @freezed diff --git a/lib/src/rust/api/zsa.dart b/lib/src/rust/api/zsa.dart index 5268a566c..7912a5ad1 100644 --- a/lib/src/rust/api/zsa.dart +++ b/lib/src/rust/api/zsa.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -16,12 +16,15 @@ Future<List<ZsaHolding>> listZsaHoldings({required Coin c}) => /// Set or update the human-readable name for a ZSA asset. /// Pass an empty string to clear the name (reverting to the hex fallback display). -Future<void> setAssetName( - {required PlatformInt64 idAsset, - required String name, - required Coin c}) => - RustLib.instance.api - .crateApiZsaSetAssetName(idAsset: idAsset, name: name, c: c); +Future<void> setAssetName({ + required PlatformInt64 idAsset, + required String name, + required Coin c, +}) => RustLib.instance.api.crateApiZsaSetAssetName( + idAsset: idAsset, + name: name, + c: c, +); /// Check whether ZSA (Zcash Shielded Assets) is available on the current network. /// diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 7763dfcbc..1294f856e 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -11,6 +11,7 @@ import 'api/frost.dart'; import 'api/init.dart'; import 'api/issuance.dart'; import 'api/key.dart'; +import 'api/ledger.dart'; import 'api/mempool.dart'; import 'api/migrate.dart'; import 'api/network.dart'; @@ -59,12 +60,8 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { /// Initialize flutter_rust_bridge in mock mode. /// No libraries for FFI are loaded. - static void initMock({ - required RustLibApi api, - }) { - instance.initMockImpl( - api: api, - ); + static void initMock({required RustLibApi api}) { + instance.initMockImpl(api: api); } /// Dispose flutter_rust_bridge @@ -95,51 +92,56 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -353494689; + int get rustContentHash => 1355211904; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( - stem: 'rlz', - ioDirectory: 'rust/target/release/', - webPrefix: 'pkg/', - wasmBindgenName: 'wasm_bindgen', - ); + stem: 'rlz', + ioDirectory: 'rust/target/release/', + webPrefix: 'pkg/', + wasmBindgenName: 'wasm_bindgen', + ); } abstract class RustLibApi extends BaseApi { - Future<List<RestoredAccount>> crateApiVaultDartVaultRecover( - {required DartVault that, - required List<int> vaultBytes, - required String masterPassword}); - - Future<List<RestoredAccount>> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, - required List<int> vaultBytes, - required String deviceIdStr, - required List<int> prfOutput}); - - Future<void> crateApiVaultDartVaultRegisterDevice( - {required DartVault that, - required List<int> initBytes, - required String masterPassword, - required String deviceIdStr, - required List<int> prfOutput}); - - Future<Uint8List> crateApiVaultDartVaultSetMasterPassword( - {required DartVault that, - String? oldPassword, - required String newPassword, - Uint8List? oldBytes}); - - Future<void> crateApiVaultDartVaultStoreAccount( - {required DartVault that, - required int timestamp, - required String name, - required String seed, - required int aindex, - required bool useInternal, - required int birthHeight, - required List<int> pk}); + Future<List<RestoredAccount>> crateApiVaultDartVaultRecover({ + required DartVault that, + required List<int> vaultBytes, + required String masterPassword, + }); + + Future<List<RestoredAccount>> crateApiVaultDartVaultRecoverWithPrf({ + required DartVault that, + required List<int> vaultBytes, + required String deviceIdStr, + required List<int> prfOutput, + }); + + Future<void> crateApiVaultDartVaultRegisterDevice({ + required DartVault that, + required List<int> initBytes, + required String masterPassword, + required String deviceIdStr, + required List<int> prfOutput, + }); + + Future<Uint8List> crateApiVaultDartVaultSetMasterPassword({ + required DartVault that, + String? oldPassword, + required String newPassword, + Uint8List? oldBytes, + }); + + Future<void> crateApiVaultDartVaultStoreAccount({ + required DartVault that, + required int timestamp, + required String name, + required String seed, + required int aindex, + required bool useInternal, + required int birthHeight, + required List<int> pk, + }); Future<void> crateApiVaultDartVaultTest({required DartVault that}); @@ -147,52 +149,66 @@ abstract class RustLibApi extends BaseApi { Mempool crateApiMempoolMempoolNew(); - Stream<MempoolMsg> crateApiMempoolMempoolRun( - {required Mempool that, required Coin c}); + Stream<MempoolMsg> crateApiMempoolMempoolRun({ + required Mempool that, + required Coin c, + }); - Future<void> crateApiMigrateNoteMigrationCancel( - {required NoteMigration that}); + Future<void> crateApiMigrateNoteMigrationCancel({ + required NoteMigration that, + }); NoteMigration crateApiMigrateNoteMigrationNew(); - Stream<MigrationStatus> crateApiMigrateNoteMigrationRun( - {required NoteMigration that, - required Coin c, - required BigInt meanDelayMs}); + Stream<MigrationStatus> crateApiMigrateNoteMigrationRun({ + required NoteMigration that, + required Coin c, + required BigInt meanDelayMs, + }); - void crateApiMigrateNoteMigrationUpdateHeight( - {required NoteMigration that, required int height}); + void crateApiMigrateNoteMigrationUpdateHeight({ + required NoteMigration that, + required int height, + }); - Future<void> crateApiSweepTransparentScannerCancel( - {required TransparentScanner that}); + Future<void> crateApiSweepTransparentScannerCancel({ + required TransparentScanner that, + }); Future<TransparentScanner> crateApiSweepTransparentScannerNew(); - Stream<String> crateApiSweepTransparentScannerRun( - {required TransparentScanner that, - required int endHeight, - required int gapLimit, - required Coin c}); + Stream<String> crateApiSweepTransparentScannerRun({ + required TransparentScanner that, + required int endHeight, + required int gapLimit, + required Coin c, + }); Future<PoolBalance> crateApiSyncBalance({required Coin c}); - Future<String> crateApiPayBroadcastTransaction( - {required int height, required List<int> txBytes, required Coin c}); + Future<String> crateApiPayBroadcastTransaction({ + required int height, + required List<int> txBytes, + required Coin c, + }); Future<String> crateApiPayBuildPuri({required List<Recipient> recipients}); - Future<void> crateApiSyncCacheBlockTime( - {required int height, required Coin c}); + Future<void> crateApiSyncCacheBlockTime({ + required int height, + required Coin c, + }); Future<void> crateApiFrostCancelDkg({required Coin c}); Future<void> crateApiSyncCancelSync(); - Future<void> crateApiDbChangeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}); + Future<void> crateApiDbChangeDbPassword({ + required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword, + }); SaplingParamsStatus crateApiSaplingCheckSaplingParams(); @@ -202,99 +218,137 @@ abstract class RustLibApi extends BaseApi { Coin crateApiCoinCoinNew({int? defaultCoin}); - Future<Coin> crateApiCoinCoinOpenDatabase( - {required Coin that, required String dbFilepath, String? password}); + Future<Coin> crateApiCoinCoinOpenDatabase({ + required Coin that, + required String dbFilepath, + String? password, + }); - Future<Coin> crateApiCoinCoinSetAccount( - {required Coin that, required int account}); + Future<Coin> crateApiCoinCoinSetAccount({ + required Coin that, + required int account, + }); - Coin crateApiCoinCoinSetLwd( - {required Coin that, required int serverType, required String url}); + Coin crateApiCoinCoinSetLwd({ + required Coin that, + required int serverType, + required String url, + }); Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}); - Coin crateApiCoinCoinSetTransport( - {required Coin that, required int transport}); + Coin crateApiCoinCoinSetTransport({ + required Coin that, + required int transport, + }); - Future<Contact> crateApiContactsCreateContact( - {required String name, - required List<String> addresses, - required String notes, - required Coin c}); + Future<Contact> crateApiContactsCreateContact({ + required String name, + required List<String> addresses, + required String notes, + required Coin c, + }); - Future<int> crateApiAccountCreateNewCategory( - {required Category category, required Coin c}); + Future<int> crateApiAccountCreateNewCategory({ + required Category category, + required Coin c, + }); - Future<Folder> crateApiAccountCreateNewFolder( - {required String name, required Coin c}); + Future<Folder> crateApiAccountCreateNewFolder({ + required String name, + required Coin c, + }); Future<Uint8List?> crateApiRaptorDecode({required List<int> packet}); - Stream<VotingDelegationProgress> crateApiVotingDelegationBuildSubmission( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - VotingPirLayout? pirLayout, - required String pirServerUrl, - required Coin c}); - - Future<VotingDelegationConfirmation> crateApiVotingDelegationConfirm( - {required String roundId, - required int bundleIndex, - required String txHash, - required String eventsJson, - required Coin c}); - - Future<void> crateApiVotingDelegationMarkSubmitted( - {required String roundId, - required int bundleIndex, - required String txHash, - required Coin c}); - - Future<VotingPreparedInfo> crateApiVotingDelegationPrepare( - {required String roundParamsJson, - required String roundName, - String? sessionJson, - required int bundleIndex, - int? maxRealNotesPerBundle, - required String lightwalletdUrl, - required Coin c}); - - Future<VotingPreparedInfo> crateApiVotingDelegationPrepareResume( - {required String roundId, - required int bundleIndex, - int? maxRealNotesPerBundle, - String? lightwalletdUrl, - required Coin c}); - - Future<VotingDelegationSetup> crateApiVotingDelegationSetup( - {required String roundId, required int bundleIndex, required Coin c}); - - Future<VotingDelegationSubmission> crateApiVotingDelegationSignAndSubmit( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - required VotingPirLayout pirLayout, - required String pirServerUrl, - required Coin c}); - - Future<String?> crateApiVotingDelegationTxHash( - {required String roundId, required int bundleIndex, required Coin c}); - - Future<String?> crateApiVotingDelegationWireJson( - {required String roundId, required int bundleIndex, required Coin c}); - - Future<void> crateApiAccountDeleteAccount( - {required int account, required Coin c}); - - Future<void> crateApiAccountDeleteCategories( - {required List<int> ids, required Coin c}); - - Future<void> crateApiContactsDeleteContacts( - {required List<int> ids, required Coin c}); - - Future<void> crateApiAccountDeleteFolders( - {required List<int> ids, required Coin c}); + Stream<VotingDelegationProgress> crateApiVotingDelegationBuildSubmission({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c, + }); + + Future<VotingDelegationConfirmation> crateApiVotingDelegationConfirm({ + required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c, + }); + + Future<void> crateApiVotingDelegationMarkSubmitted({ + required String roundId, + required int bundleIndex, + required String txHash, + required Coin c, + }); + + Future<VotingPreparedInfo> crateApiVotingDelegationPrepare({ + required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c, + }); + + Future<VotingPreparedInfo> crateApiVotingDelegationPrepareResume({ + required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c, + }); + + Future<VotingDelegationSetup> crateApiVotingDelegationSetup({ + required String roundId, + required int bundleIndex, + required Coin c, + }); + + Future<VotingDelegationSubmission> crateApiVotingDelegationSignAndSubmit({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c, + }); + + Future<String?> crateApiVotingDelegationTxHash({ + required String roundId, + required int bundleIndex, + required Coin c, + }); + + Future<String?> crateApiVotingDelegationWireJson({ + required String roundId, + required int bundleIndex, + required Coin c, + }); + + Future<void> crateApiAccountDeleteAccount({ + required int account, + required Coin c, + }); + + Future<void> crateApiAccountDeleteCategories({ + required List<int> ids, + required Coin c, + }); + + Future<void> crateApiContactsDeleteContacts({ + required List<int> ids, + required Coin c, + }); + + Future<void> crateApiAccountDeleteFolders({ + required List<int> ids, + required Coin c, + }); Stream<DKGStatus> crateApiFrostDoDkg({required Coin c}); @@ -304,39 +358,63 @@ abstract class RustLibApi extends BaseApi { Future<void> crateApiAccountDummyExport({required SigningEvent a}); - Future<List<Uint8List>> crateApiRaptorEncode( - {required String path, required RaptorQParams params}); + Future<List<Uint8List>> crateApiRaptorEncode({ + required String path, + required RaptorQParams params, + }); Future<void> crateApiRaptorEndDecode(); - Future<Uint8List> crateApiAccountExportAccount( - {required int id, required String passphrase, required Coin c}); + Future<Uint8List> crateApiAccountExportAccount({ + required int id, + required String passphrase, + required Coin c, + }); Future<String> crateApiContactsExportContactsVcard({required Coin c}); - Future<Uint8List> crateApiPayExtractTransaction( - {required PcztPackage package}); + Future<Uint8List> crateApiPayExtractTransaction({ + required PcztPackage package, + }); - Future<List<TAddressTxCount>> crateApiAccountFetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}); + Future<List<TAddressTxCount>> crateApiAccountFetchAddressTxCount({ + required Coin c, + required bool aggregate, + required int poolFilter, + }); - Future<List<(int, double)>> crateApiTransactionFetchAmounts( - {int? from, int? to, required int category, required Coin c}); + Future<List<(int, double)>> crateApiTransactionFetchAmounts({ + int? from, + int? to, + required int category, + required Coin c, + }); - Future<List<(String, double, bool)>> crateApiTransactionFetchCategoryAmounts( - {int? from, int? to, required Coin c}); + Future<List<(String, double, bool)>> crateApiTransactionFetchCategoryAmounts({ + int? from, + int? to, + required Coin c, + }); - Future<List<TAddressTxCount>> crateApiAccountFetchTransparentAddressTxCount( - {required Coin c}); + Future<List<TAddressTxCount>> crateApiAccountFetchTransparentAddressTxCount({ + required Coin c, + }); - Future<void> crateApiSyncFetchTxDetails( - {required int account, required Coin c}); + Future<void> crateApiSyncFetchTxDetails({ + required int account, + required Coin c, + }); - Future<int> crateApiTransactionFillMissingTxPrices( - {required String api, required String currency, required Coin c}); + Future<int> crateApiTransactionFillMissingTxPrices({ + required String api, + required String currency, + required Coin c, + }); - Future<List<ContactMatch>> crateApiContactsFindContactsForAddress( - {required String address, required Coin c}); + Future<List<ContactMatch>> crateApiContactsFindContactsForAddress({ + required String address, + required Coin c, + }); Future<FrostSignParams> crateApiFrostFrostSignParamsDefault(); @@ -346,28 +424,44 @@ abstract class RustLibApi extends BaseApi { String crateApiKeyGenerateSeed(); - Future<Addresses> crateApiAccountGetAccountAddresses( - {required int account, required int uaPools, required Coin c}); + Future<Addresses> crateApiAccountGetAccountAddresses({ + required int account, + required int uaPools, + required Coin c, + }); - Future<String?> crateApiAccountGetAccountFingerprint( - {required int account, required Coin c}); + Future<String?> crateApiAccountGetAccountFingerprint({ + required int account, + required Coin c, + }); Future<FrostParams?> crateApiAccountGetAccountFrostParams({required Coin c}); - Future<int> crateApiAccountGetAccountPools( - {required int account, required Coin c}); + Future<int> crateApiAccountGetAccountPools({ + required int account, + required Coin c, + }); - Future<Seed?> crateApiAccountGetAccountSeed( - {required int account, required Coin c}); + Future<Seed?> crateApiAccountGetAccountSeed({ + required int account, + required Coin c, + }); - Future<String> crateApiAccountGetAccountUfvk( - {required int account, required int pools, required Coin c}); + Future<String> crateApiAccountGetAccountUfvk({ + required int account, + required int pools, + required Coin c, + }); - Future<Addresses> crateApiAccountGetAddresses( - {required int uaPools, required Coin c}); + Future<Addresses> crateApiAccountGetAddresses({ + required int uaPools, + required Coin c, + }); - Future<double> crateApiNetworkGetCoingeckoPrice( - {required String api, required String currency}); + Future<double> crateApiNetworkGetCoingeckoPrice({ + required String api, + required String currency, + }); Future<int> crateApiNetworkGetCurrentHeight({required Coin c}); @@ -375,18 +469,23 @@ abstract class RustLibApi extends BaseApi { Future<List<String>> crateApiFrostGetDkgAddresses({required Coin c}); - Future<ExchangeRate> crateApiNetworkGetExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}); + Future<ExchangeRate> crateApiNetworkGetExchangeRate({ + required String api, + required String fromCurrency, + required String toCurrency, + }); - Future<String> crateApiAccountGetExportedData( - {required int type, required Coin c}); + Future<String> crateApiAccountGetExportedData({ + required int type, + required Coin c, + }); int crateApiKeyGetKeyPools({required String key, required Coin c}); - Future<Uint8List> crateApiMempoolGetMempoolTx( - {required String txId, required Coin c}); + Future<Uint8List> crateApiMempoolGetMempoolTx({ + required String txId, + required Coin c, + }); Future<MigrationStatus> crateApiMigrateGetMigrationStatus({required Coin c}); @@ -396,13 +495,16 @@ abstract class RustLibApi extends BaseApi { Uint8List crateApiRaptorGetQrBytes({required List<int> data}); - Future<List<String>> crateApiNetworkGetSupportedVsCurrencies( - {required String api}); + Future<List<String>> crateApiNetworkGetSupportedVsCurrencies({ + required String api, + }); Future<void> crateApiCoinGetTorClient(); - Future<TxAccount> crateApiAccountGetTxDetails( - {required int idTx, required Coin c}); + Future<TxAccount> crateApiAccountGetTxDetails({ + required int idTx, + required Coin c, + }); Future<bool> crateApiFrostHasDkgAddresses({required Coin c}); @@ -410,11 +512,16 @@ abstract class RustLibApi extends BaseApi { Future<bool> crateApiAccountHasTransparentPubKey({required Coin c}); - Future<void> crateApiAccountImportAccount( - {required String passphrase, required List<int> data, required Coin c}); + Future<void> crateApiAccountImportAccount({ + required String passphrase, + required List<int> data, + required Coin c, + }); - Future<List<Contact>> crateApiContactsImportContactsVcard( - {required String vcardData, required Coin c}); + Future<List<Contact>> crateApiContactsImportContactsVcard({ + required String vcardData, + required Coin c, + }); Future<void> crateApiInitInitApp(); @@ -428,17 +535,21 @@ abstract class RustLibApi extends BaseApi { void crateApiPluginInitPlugins(); - Future<void> crateApiFrostInitSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}); + Future<void> crateApiFrostInitSign({ + required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c, + }); - Future<DartVault> crateApiVaultInitVault( - {required FutureOr<void> Function(Uint8List) append}); + Future<DartVault> crateApiVaultInitVault({ + required FutureOr<void> Function(Uint8List) append, + }); - Future<PluginInfo> crateApiPluginInstallPlugin( - {required String url, required Coin c}); + Future<PluginInfo> crateApiPluginInstallPlugin({ + required String url, + required Coin c, + }); Future<bool> crateApiNetworkIsIronwoodActive({required Coin c}); @@ -456,19 +567,38 @@ abstract class RustLibApi extends BaseApi { bool crateApiKeyIsValidPhrase({required String phrase}); - bool crateApiKeyIsValidTransparentAddress( - {required String address, required Coin c}); + bool crateApiKeyIsValidTransparentAddress({ + required String address, + required Coin c, + }); Future<bool> crateApiZsaIsZsaAvailable({required Coin c}); - Future<Uint8List> crateApiIssuanceIssueAsset( - {required String assetName, - required BigInt amount, - required bool firstIssuance, - required bool finalize, - Uint8List? descHash, - required int idAccount, - required Coin c}); + Future<Uint8List> crateApiIssuanceIssueAsset({ + required String assetName, + required BigInt amount, + required bool firstIssuance, + required bool finalize, + Uint8List? descHash, + required int idAccount, + required Coin c, + }); + + Future<String> crateApiLedgerLedgerAppVersion({ + required FutureOr<Uint8List> Function(Uint8List) exchange, + }); + + Future<String> crateApiLedgerLedgerGetUfvk({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }); + + Stream<SigningEvent> crateApiLedgerLedgerSignTransaction({ + required PcztPackage package, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }); Future<List<Account>> crateApiAccountListAccounts({required Coin c}); @@ -476,8 +606,9 @@ abstract class RustLibApi extends BaseApi { Future<List<Contact>> crateApiContactsListContacts({required Coin c}); - Future<List<DbAccountPreview>> crateApiDbListDbAccounts( - {required String dbFilepath}); + Future<List<DbAccountPreview>> crateApiDbListDbAccounts({ + required String dbFilepath, + }); Future<List<String>> crateApiDbListDbNames({required String dir}); @@ -487,150 +618,241 @@ abstract class RustLibApi extends BaseApi { Future<List<TxNote>> crateApiAccountListNotes({required Coin c}); + Future<List<String>> crateApiAccountListOwnedAddresses({required Coin c}); + Future<List<PluginInfo>> crateApiPluginListPlugins({required Coin c}); Future<List<Tx>> crateApiAccountListTxHistory({required Coin c}); Future<List<ZsaHolding>> crateApiZsaListZsaHoldings({required Coin c}); - Future<void> crateApiAccountLockNote( - {required int id, required bool locked, required Coin c}); + Future<void> crateApiAccountLockNote({ + required int id, + required bool locked, + required Coin c, + }); - Future<void> crateApiAccountLockRecentNotes( - {required int height, required int threshold, required Coin c}); + Future<void> crateApiAccountLockRecentNotes({ + required int height, + required int threshold, + required Coin c, + }); Future<BigInt> crateApiAccountMaxSpendable({required Coin c}); - Future<int> crateApiAccountNewAccount( - {required NewAccount na, required Coin c}); + Future<int> crateApiAccountNewAccount({ + required NewAccount na, + required Coin c, + }); Future<Uint8List> crateApiPayPackTransaction({required PcztPackage pczt}); - Future<List<MemoSection>> crateApiPluginParseMemoWithPlugins( - {required List<int> memoBytes, required Coin c}); + Future<List<MemoSection>> crateApiPluginParseMemoWithPlugins({ + required List<int> memoBytes, + required Coin c, + }); List<Recipient>? crateApiPayParsePaymentUri({required String uri}); - Future<PcztPackage> crateApiPayPrepare( - {required List<Recipient> recipients, - required PaymentOptions options, - required Coin c}); + Future<Uint8List> crateApiPayPcztApplyBatchSignatures({ + required List<int> original, + required List<int> response, + }); + + Future<Uint8List> crateApiPayPcztApplyKeystoneSignatures({ + required List<int> original, + required List<int> signed, + }); + + Future<Uint8List> crateApiPayPcztFromKeystone({required List<int> pczt}); + + Future<Uint8List> crateApiPayPcztToBatchRequest({ + required List<Uint8List> pczts, + }); + + Future<Uint8List> crateApiPayPcztToKeystone({required List<int> pczt}); + + Future<PcztPackage> crateApiPayPrepare({ + required List<Recipient> recipients, + required PaymentOptions options, + required Coin c, + }); - Future<PcztPackage> crateApiPayPrepareMigration( - {required List<Recipient> recipients, - required int srcPools, - required Coin c}); + Future<PcztPackage> crateApiPayPrepareMigration({ + required List<Recipient> recipients, + required int srcPools, + required Coin c, + }); Future<void> crateApiAccountPrintKeys({required int id, required Coin c}); - Future<void> crateApiDbPutProp( - {required String key, required String value, required Coin c}); + Future<PcztPackage> crateApiPayProveAndFinalize({ + required PcztPackage pczt, + required Coin c, + }); + + Future<void> crateApiDbPutProp({ + required String key, + required String value, + required Coin c, + }); Future<List<LWDInfo>> crateApiNetworkQueryLwdList({required int coin}); Future<Receivers> crateApiAccountReceiversDefault(); - Receivers crateApiAccountReceiversFromUa( - {required String ua, required Coin c}); + Receivers crateApiAccountReceiversFromUa({ + required String ua, + required Coin c, + }); - Future<void> crateApiAccountRemoveAccount( - {required int accountId, required Coin c}); + Future<void> crateApiAccountRemoveAccount({ + required int accountId, + required Coin c, + }); - Future<void> crateApiPluginRemovePlugin( - {required String id, required Coin c}); + Future<void> crateApiPluginRemovePlugin({ + required String id, + required Coin c, + }); - Future<void> crateApiAccountRenameCategory( - {required Category category, required Coin c}); + Future<void> crateApiAccountRenameCategory({ + required Category category, + required Coin c, + }); - Future<void> crateApiAccountRenameFolder( - {required int id, required String name, required Coin c}); + Future<void> crateApiAccountRenameFolder({ + required int id, + required String name, + required Coin c, + }); - Future<void> crateApiAccountReorderAccount( - {required int oldPosition, required int newPosition, required Coin c}); + Future<void> crateApiAccountReorderAccount({ + required int oldPosition, + required int newPosition, + required Coin c, + }); Future<void> crateApiFrostResetSign({required Coin c}); Future<void> crateApiAccountResetSync({required int id, required Coin c}); - Future<OpenAliasResolution> crateApiOpenaliasResolveOpenalias( - {required String alias, required Coin c}); + Future<OpenAliasResolution> crateApiOpenaliasResolveOpenalias({ + required String alias, + required Coin c, + }); - Future<OpenAliasResolution> crateApiOpenaliasResolveOpenaliasAll( - {required String alias}); + Future<OpenAliasResolution> crateApiOpenaliasResolveOpenaliasAll({ + required String alias, + }); - Future<RawOpenAliasResolution> crateApiOpenaliasResolveOpenaliasRaw( - {required String alias}); + Future<RawOpenAliasResolution> crateApiOpenaliasResolveOpenaliasRaw({ + required String alias, + }); - Future<void> crateApiSyncRewindSync( - {required int height, required int account, required Coin c}); + Future<void> crateApiSyncRewindSync({ + required int height, + required int account, + required Coin c, + }); - Future<String> crateApiPaySend( - {required int height, required List<int> data, required Coin c}); + Future<String> crateApiPaySend({ + required int height, + required List<int> data, + required Coin c, + }); - Future<void> crateApiZsaSetAssetName( - {required PlatformInt64 idAsset, required String name, required Coin c}); + Future<void> crateApiZsaSetAssetName({ + required PlatformInt64 idAsset, + required String name, + required Coin c, + }); - Future<void> crateApiFrostSetDkgAddress( - {required int id, required String address, required Coin c}); + Future<void> crateApiFrostSetDkgAddress({ + required int id, + required String address, + required Coin c, + }); - Future<void> crateApiFrostSetDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}); + Future<void> crateApiFrostSetDkgParams({ + required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c, + }); void crateApiInitSetExpertMode({required bool enabled}); Stream<LogMessage> crateApiInitSetLogStream(); - Future<void> crateApiPluginSetPluginEnabled( - {required String id, required bool enabled, required Coin c}); + Future<void> crateApiPluginSetPluginEnabled({ + required String id, + required bool enabled, + required Coin c, + }); - Future<void> crateApiTransactionSetTxCategory( - {required int id, int? category, required Coin c}); + Future<void> crateApiTransactionSetTxCategory({ + required int id, + int? category, + required Coin c, + }); - Future<void> crateApiTransactionSetTxPrice( - {required int id, double? price, required Coin c}); + Future<void> crateApiTransactionSetTxPrice({ + required int id, + double? price, + required Coin c, + }); - Future<void> crateApiTransactionSetUserMemo( - {required int idTx, String? memo, required Coin c}); + Future<void> crateApiTransactionSetUserMemo({ + required int idTx, + String? memo, + required Coin c, + }); Future<String> crateApiAccountShowLedgerSaplingAddress({required Coin c}); Future<String> crateApiAccountShowLedgerTransparentAddress({required Coin c}); - Stream<SigningEvent> crateApiAccountSignLedgerTransaction( - {required PcztPackage package, required Coin c}); + Stream<SigningEvent> crateApiAccountSignLedgerTransaction({ + required PcztPackage package, + required Coin c, + }); - Future<PcztPackage> crateApiPaySignTransaction( - {required PcztPackage pczt, required Coin c}); + Future<PcztPackage> crateApiPaySignTransaction({ + required PcztPackage pczt, + required Coin c, + }); Future<MigrationEvent> crateApiMigrateStepMigration({required Coin c}); - Future<void> crateApiPayStorePendingTx( - {required int height, - required List<int> txid, - double? price, - int? category, - required Coin c}); - - Stream<SyncProgress> crateApiSyncSynchronize( - {required List<int> accounts, - required int currentHeight, - required int actionsPerSync, - required int transparentLimit, - required int checkpointAge, - required bool fast, - required Coin c}); + Future<void> crateApiPayStorePendingTx({ + required int height, + required List<int> txid, + double? price, + int? category, + required Coin c, + }); + + Stream<SyncProgress> crateApiSyncSynchronize({ + required List<int> accounts, + required int currentHeight, + required int actionsPerSync, + required int transparentLimit, + required int checkpointAge, + required bool fast, + required Coin c, + }); TxPlan crateApiPayToPlan({required PcztPackage package, required Coin c}); Future<void> crateApiAccountToggleAllNotes({required Coin c}); - void crateApiOpenaliasTryValidateZcashAddress( - {required String address, required Coin c}); + void crateApiOpenaliasTryValidateZcashAddress({ + required String address, + required Coin c, + }); Future<TxAccount> crateApiAccountTxAccountDefault(); @@ -642,287 +864,370 @@ abstract class RustLibApi extends BaseApi { Future<TxSpend> crateApiAccountTxSpendDefault(); - String crateApiAccountUaFromUfvk( - {required String ufvk, int? di, required Coin c}); + String crateApiAccountUaFromUfvk({ + required String ufvk, + int? di, + required Coin c, + }); + + String crateApiLedgerUfvkDefaultAddress({ + required String ufvk, + required Coin c, + }); Future<void> crateApiAccountUnlockAllNotes({required Coin c}); Future<PcztPackage> crateApiPayUnpackTransaction({required List<int> bytes}); - Future<void> crateApiAccountUpdateAccount( - {required AccountUpdate update, required Coin c}); + Future<void> crateApiAccountUpdateAccount({ + required AccountUpdate update, + required Coin c, + }); - Future<void> crateApiContactsUpdateContact( - {required int id, - String? name, - List<String>? addresses, - String? notes, - required Coin c}); + Future<void> crateApiContactsUpdateContact({ + required int id, + String? name, + List<String>? addresses, + String? notes, + required Coin c, + }); - Future<void> crateApiTransactionUpdateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}); + Future<void> crateApiTransactionUpdateHistoricalPrices({ + required String currency, + required double exchangeRate, + required Coin c, + }); bool crateApiOpenaliasValidateOpenaliasName({required String alias}); - bool crateApiOpenaliasValidateZcashAddress( - {required String address, required Coin c}); + bool crateApiOpenaliasValidateZcashAddress({ + required String address, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainListRounds( - {required String baseUrl, required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainListRounds({ + required String baseUrl, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainResubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainResubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainRoundStatus( - {required String baseUrl, required String roundId, required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainRoundStatus({ + required String baseUrl, + required String roundId, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainRoundTally( - {required String baseUrl, required String roundId, required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainRoundTally({ + required String baseUrl, + required String roundId, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainShareStatus( - {required String serverUrl, - required String roundId, - required String shareId, - required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainShareStatus({ + required String serverUrl, + required String roundId, + required String shareId, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainSubmitDelegation( - {required String baseUrl, - required String submissionJson, - required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainSubmitDelegation({ + required String baseUrl, + required String submissionJson, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainSubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainSubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainSubmitVote( - {required String baseUrl, - required String submissionJson, - required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainSubmitVote({ + required String baseUrl, + required String submissionJson, + required Coin c, + }); - Future<VotingChainResponse> crateApiVotingVotechainTxConfirmation( - {required String baseUrl, required String txHash, required Coin c}); + Future<VotingChainResponse> crateApiVotingVotechainTxConfirmation({ + required String baseUrl, + required String txHash, + required Coin c, + }); - Future<List<VotingBallotIntent>> crateApiVotingVotingBallotIntents( - {required String roundId, required Coin c}); + Future<List<VotingBallotIntent>> crateApiVotingVotingBallotIntents({ + required String roundId, + required Coin c, + }); - Future<VotingVoteCommitments> crateApiVotingVotingCommit( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}); + Future<VotingVoteCommitments> crateApiVotingVotingCommit({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, + }); - Stream<VotingVoteCommitStage> crateApiVotingVotingCommitWithProgress( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}); + Stream<VotingVoteCommitStage> crateApiVotingVotingCommitWithProgress({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, + }); - Future<VotingConfig?> crateApiVotingVotingConfigCached( - {required String source, required Coin c}); + Future<VotingConfig?> crateApiVotingVotingConfigCached({ + required String source, + required Coin c, + }); Future<void> crateApiVotingVotingConfigClearCache({required Coin c}); - Future<VotingConfig> crateApiVotingVotingConfigResolve( - {required String source, required Coin c}); + Future<VotingConfig> crateApiVotingVotingConfigResolve({ + required String source, + required Coin c, + }); - Future<VotingVoteConfirmation> crateApiVotingVotingConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required String eventsJson, - required Coin c}); + Future<VotingVoteConfirmation> crateApiVotingVotingConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c, + }); - Future<String?> crateApiVotingVotingDelegationVanCommitmentHex( - {required String roundId, required int bundleIndex, required Coin c}); + Future<String?> crateApiVotingVotingDelegationVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required Coin c, + }); - Future<String?> crateApiVotingVotingDraftsLoad( - {required String roundId, required Coin c}); + Future<String?> crateApiVotingVotingDraftsLoad({ + required String roundId, + required Coin c, + }); - Future<void> crateApiVotingVotingDraftsSave( - {required String roundId, required String draftsJson, required Coin c}); + Future<void> crateApiVotingVotingDraftsSave({ + required String roundId, + required String draftsJson, + required Coin c, + }); - Future<BigInt> crateApiVotingVotingEligibleWeight( - {required int snapshotHeight, required Coin c}); + Future<BigInt> crateApiVotingVotingEligibleWeight({ + required int snapshotHeight, + required Coin c, + }); Future<String> crateApiVotingVotingHotkeyCreate({required Coin c}); Future<String> crateApiVotingVotingHotkeyGet({required Coin c}); - Future<void> crateApiVotingVotingMarkVoteSubmitted( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required Coin c}); - - Future<VotingVotePayloads> crateApiVotingVotingPayloads( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}); - - Future<VotingRoundPlan> crateApiVotingVotingPlan( - {required String roundId, - required List<int> proposalIds, - required Coin c}); - - Future<void> crateApiVotingVotingRecordExecution( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String voteTxHash, - required BigInt vcTreePosition, - required String shareDeliveriesJson, - required Coin c}); - - Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree( - {required String roundId, - required int bundleIndex, - required int vanLeafPosition, - required Coin c}); + Future<void> crateApiVotingVotingMarkVoteSubmitted({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c, + }); + + Future<VotingVotePayloads> crateApiVotingVotingPayloads({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }); + + Future<VotingRoundPlan> crateApiVotingVotingPlan({ + required String roundId, + required List<int> proposalIds, + required Coin c, + }); + + Future<void> crateApiVotingVotingRecordExecution({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c, + }); + + Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree({ + required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c, + }); Future<VotingTreeVoteConfirmation> - crateApiVotingVotingRecoverConfirmVoteFromTree( - {required String roundId, - required int bundleIndex, - required int proposalId, - required BigInt vcTreePosition, - int? vanLeafPosition, - required Coin c}); - - Future<VotingRoundRecovery> crateApiVotingVotingRecovery( - {required String roundId, required Coin c}); - - Future<void> crateApiVotingVotingRecoveryClear( - {required String roundId, required Coin c}); - - Future<void> crateApiVotingVotingResetSessionState( - {required String roundId, required Coin c}); - - Future<String> crateApiVotingVotingRoundParamsJson( - {required String source, - required String roundId, - required BigInt snapshotHeight, - required List<int> ncRoot, - required List<int> nullifierImtRoot, - required Coin c}); + crateApiVotingVotingRecoverConfirmVoteFromTree({ + required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c, + }); + + Future<VotingRoundRecovery> crateApiVotingVotingRecovery({ + required String roundId, + required Coin c, + }); + + Future<void> crateApiVotingVotingRecoveryClear({ + required String roundId, + required Coin c, + }); + + Future<void> crateApiVotingVotingResetSessionState({ + required String roundId, + required Coin c, + }); + + Future<String> crateApiVotingVotingRoundParamsJson({ + required String source, + required String roundId, + required BigInt snapshotHeight, + required List<int> ncRoot, + required List<int> nullifierImtRoot, + required Coin c, + }); Future<List<VotingRoundInfo>> crateApiVotingVotingRounds({required Coin c}); - Future<List<VotingRoundSession>> crateApiVotingVotingSessions( - {required List<String> roundIds, required Coin c}); - - Future<void> crateApiVotingVotingSetBallotIntent( - {required String roundId, - required int proposalId, - required bool skipped, - required int choice, - required int numOptions, - required Coin c}); - - Future<void> crateApiVotingVotingShareAddServers( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> newUrls, - required Coin c}); - - Future<void> crateApiVotingVotingShareConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required Coin c}); - - Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads( - {required String roundId, required Coin c}); - - Future<VotingSharePlan> crateApiVotingVotingSharePlan( - {required String roundId, - required BigInt now, - required BigInt ceremonyStart, - BigInt? voteEnd, - required List<String> serverUrls, - required bool singleShare, - required Coin c}); - - Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans( - {required int shareCount, - required List<String> serverUrls, - required BigInt now, - required BigInt voteEnd, - required BigInt ceremonyStart, - required bool singleShare, - required Coin c}); - - Future<void> crateApiVotingVotingShareRecord( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> sentToUrls, - required BigInt submitAt, - required Coin c}); + Future<List<VotingRoundSession>> crateApiVotingVotingSessions({ + required List<String> roundIds, + required Coin c, + }); + + Future<void> crateApiVotingVotingSetBallotIntent({ + required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, + required Coin c, + }); + + Future<void> crateApiVotingVotingShareAddServers({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> newUrls, + required Coin c, + }); + + Future<void> crateApiVotingVotingShareConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c, + }); + + Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads({ + required String roundId, + required Coin c, + }); + + Future<VotingSharePlan> crateApiVotingVotingSharePlan({ + required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List<String> serverUrls, + required bool singleShare, + required Coin c, + }); + + Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans({ + required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c, + }); + + Future<void> crateApiVotingVotingShareRecord({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> sentToUrls, + required BigInt submitAt, + required Coin c, + }); Future<List<VotingShareDelegationRecord>> - crateApiVotingVotingShareUnconfirmed( - {required String roundId, required Coin c}); - - Future<String> crateApiVotingVotingShareWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - BigInt? vcTreePosition, - required BigInt submitAt, - required Coin c}); - - Future<int> crateApiVotingVotingSyncTree( - {required String roundId, required String voteNodeUrl, required Coin c}); - - Future<BigInt?> crateApiVotingVotingTreeFindLeaf( - {required String roundId, - required String nodeUrl, - required String targetHex}); - - Future<VotingVanWitness> crateApiVotingVotingVanWitness( - {required String roundId, - required int bundleIndex, - required String voteNodeUrl, - required Coin c}); - - Future<String> crateApiVotingVotingVoteCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}); - - Future<String> crateApiVotingVotingVoteVanCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}); - - Future<String> crateApiVotingVotingVoteWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}); + crateApiVotingVotingShareUnconfirmed({ + required String roundId, + required Coin c, + }); + + Future<String> crateApiVotingVotingShareWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, + required Coin c, + }); + + Future<int> crateApiVotingVotingSyncTree({ + required String roundId, + required String voteNodeUrl, + required Coin c, + }); + + Future<BigInt?> crateApiVotingVotingTreeFindLeaf({ + required String roundId, + required String nodeUrl, + required String targetHex, + }); + + Future<VotingVanWitness> crateApiVotingVotingVanWitness({ + required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c, + }); + + Future<String> crateApiVotingVotingVoteCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }); + + Future<String> crateApiVotingVotingVoteVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }); + + Future<String> crateApiVotingVotingVoteWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }); RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_DartVault; + get rust_arc_increment_strong_count_DartVault; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_DartVault; + get rust_arc_decrement_strong_count_DartVault; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr; @@ -933,22 +1238,22 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr; RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_NoteMigration; + get rust_arc_increment_strong_count_NoteMigration; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_NoteMigration; + get rust_arc_decrement_strong_count_NoteMigration; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr; + get rust_arc_decrement_strong_count_NoteMigrationPtr; RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_TransparentScanner; + get rust_arc_increment_strong_count_TransparentScanner; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_TransparentScanner; + get rust_arc_decrement_strong_count_TransparentScanner; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr; + get rust_arc_decrement_strong_count_TransparentScannerPtr; } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -960,20 +1265,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { }); @override - Future<List<RestoredAccount>> crateApiVaultDartVaultRecover( - {required DartVault that, - required List<int> vaultBytes, - required String masterPassword}) { + Future<List<RestoredAccount>> crateApiVaultDartVaultRecover({ + required DartVault that, + required List<int> vaultBytes, + required String masterPassword, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + that, + serializer, + ); sse_encode_list_prim_u_8_loose(vaultBytes, serializer); sse_encode_String(masterPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 1, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 1, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_restored_account, @@ -993,22 +1305,29 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<RestoredAccount>> crateApiVaultDartVaultRecoverWithPrf( - {required DartVault that, - required List<int> vaultBytes, - required String deviceIdStr, - required List<int> prfOutput}) { + Future<List<RestoredAccount>> crateApiVaultDartVaultRecoverWithPrf({ + required DartVault that, + required List<int> vaultBytes, + required String deviceIdStr, + required List<int> prfOutput, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + that, + serializer, + ); sse_encode_list_prim_u_8_loose(vaultBytes, serializer); sse_encode_String(deviceIdStr, serializer); sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 2, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 2, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_restored_account, @@ -1028,24 +1347,31 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVaultDartVaultRegisterDevice( - {required DartVault that, - required List<int> initBytes, - required String masterPassword, - required String deviceIdStr, - required List<int> prfOutput}) { + Future<void> crateApiVaultDartVaultRegisterDevice({ + required DartVault that, + required List<int> initBytes, + required String masterPassword, + required String deviceIdStr, + required List<int> prfOutput, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + that, + serializer, + ); sse_encode_list_prim_u_8_loose(initBytes, serializer); sse_encode_String(masterPassword, serializer); sse_encode_String(deviceIdStr, serializer); sse_encode_list_prim_u_8_loose(prfOutput, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 3, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 3, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1066,27 +1392,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "initBytes", "masterPassword", "deviceIdStr", - "prfOutput" + "prfOutput", ], ); @override - Future<Uint8List> crateApiVaultDartVaultSetMasterPassword( - {required DartVault that, - String? oldPassword, - required String newPassword, - Uint8List? oldBytes}) { + Future<Uint8List> crateApiVaultDartVaultSetMasterPassword({ + required DartVault that, + String? oldPassword, + required String newPassword, + Uint8List? oldBytes, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + that, + serializer, + ); sse_encode_opt_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); sse_encode_opt_list_prim_u_8_strict(oldBytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 4, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 4, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -1106,21 +1439,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVaultDartVaultStoreAccount( - {required DartVault that, - required int timestamp, - required String name, - required String seed, - required int aindex, - required bool useInternal, - required int birthHeight, - required List<int> pk}) { + Future<void> crateApiVaultDartVaultStoreAccount({ + required DartVault that, + required int timestamp, + required String name, + required String seed, + required int aindex, + required bool useInternal, + required int birthHeight, + required List<int> pk, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); + that, + serializer, + ); sse_encode_u_32(timestamp, serializer); sse_encode_String(name, serializer); sse_encode_String(seed, serializer); @@ -1128,8 +1464,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(useInternal, serializer); sse_encode_u_32(birthHeight, serializer); sse_encode_list_prim_u_8_loose(pk, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 5, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 5, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1144,7 +1484,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { aindex, useInternal, birthHeight, - pk + pk, ], apiImpl: this, ), @@ -1162,7 +1502,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "aindex", "useInternal", "birthHeight", - "pk" + "pk", ], ); @@ -1173,9 +1513,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 6, port: port_); + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 6, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1188,10 +1534,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultDartVaultTestConstMeta => const TaskConstMeta( - debugName: "DartVault_test", - argNames: ["that"], - ); + TaskConstMeta get kCrateApiVaultDartVaultTestConstMeta => + const TaskConstMeta(debugName: "DartVault_test", argNames: ["that"]); @override Future<void> crateApiMempoolMempoolCancel({required Mempool that}) { @@ -1200,9 +1544,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 7, port: port_); + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 7, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1216,10 +1566,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMempoolMempoolCancelConstMeta => - const TaskConstMeta( - debugName: "Mempool_cancel", - argNames: ["that"], - ); + const TaskConstMeta(debugName: "Mempool_cancel", argNames: ["that"]); @override Mempool crateApiMempoolMempoolNew() { @@ -1241,14 +1588,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiMempoolMempoolNewConstMeta => const TaskConstMeta( - debugName: "Mempool_new", - argNames: [], - ); + TaskConstMeta get kCrateApiMempoolMempoolNewConstMeta => + const TaskConstMeta(debugName: "Mempool_new", argNames: []); @override - Stream<MempoolMsg> crateApiMempoolMempoolRun( - {required Mempool that, required Coin c}) { + Stream<MempoolMsg> crateApiMempoolMempoolRun({ + required Mempool that, + required Coin c, + }) { final mempoolSink = RustStreamSink<MempoolMsg>(); unawaited( handler.executeNormal( @@ -1256,11 +1603,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - that, serializer); + that, + serializer, + ); sse_encode_StreamSink_mempool_msg_Sse(mempoolSink, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 9, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 9, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1276,21 +1629,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMempoolMempoolRunConstMeta => const TaskConstMeta( - debugName: "Mempool_run", - argNames: ["that", "mempoolSink", "c"], - ); + debugName: "Mempool_run", + argNames: ["that", "mempoolSink", "c"], + ); @override - Future<void> crateApiMigrateNoteMigrationCancel( - {required NoteMigration that}) { + Future<void> crateApiMigrateNoteMigrationCancel({ + required NoteMigration that, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 10, port: port_); + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 10, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1330,16 +1690,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMigrateNoteMigrationNewConstMeta => - const TaskConstMeta( - debugName: "NoteMigration_new", - argNames: [], - ); + const TaskConstMeta(debugName: "NoteMigration_new", argNames: []); @override - Stream<MigrationStatus> crateApiMigrateNoteMigrationRun( - {required NoteMigration that, - required Coin c, - required BigInt meanDelayMs}) { + Stream<MigrationStatus> crateApiMigrateNoteMigrationRun({ + required NoteMigration that, + required Coin c, + required BigInt meanDelayMs, + }) { final sink = RustStreamSink<MigrationStatus>(); unawaited( handler.executeNormal( @@ -1347,12 +1705,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); + that, + serializer, + ); sse_encode_StreamSink_migration_status_Sse(sink, serializer); sse_encode_box_autoadd_coin(c, serializer); sse_encode_u_64(meanDelayMs, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 12, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 12, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1374,14 +1738,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - void crateApiMigrateNoteMigrationUpdateHeight( - {required NoteMigration that, required int height}) { + void crateApiMigrateNoteMigrationUpdateHeight({ + required NoteMigration that, + required int height, + }) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - that, serializer); + that, + serializer, + ); sse_encode_u_32(height, serializer); return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!; }, @@ -1403,16 +1771,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiSweepTransparentScannerCancel( - {required TransparentScanner that}) { + Future<void> crateApiSweepTransparentScannerCancel({ + required TransparentScanner that, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 14, port: port_); + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 14, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1437,8 +1812,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 15, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 15, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: @@ -1453,17 +1832,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSweepTransparentScannerNewConstMeta => - const TaskConstMeta( - debugName: "TransparentScanner_new", - argNames: [], - ); + const TaskConstMeta(debugName: "TransparentScanner_new", argNames: []); @override - Stream<String> crateApiSweepTransparentScannerRun( - {required TransparentScanner that, - required int endHeight, - required int gapLimit, - required Coin c}) { + Stream<String> crateApiSweepTransparentScannerRun({ + required TransparentScanner that, + required int endHeight, + required int gapLimit, + required Coin c, + }) { final addressStream = RustStreamSink<String>(); unawaited( handler.executeNormal( @@ -1471,13 +1848,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - that, serializer); + that, + serializer, + ); sse_encode_StreamSink_String_Sse(addressStream, serializer); sse_encode_u_32(endHeight, serializer); sse_encode_u_32(gapLimit, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 16, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 16, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1505,8 +1888,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 17, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 17, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_pool_balance, @@ -1519,14 +1906,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSyncBalanceConstMeta => const TaskConstMeta( - debugName: "balance", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiSyncBalanceConstMeta => + const TaskConstMeta(debugName: "balance", argNames: ["c"]); @override - Future<String> crateApiPayBroadcastTransaction( - {required int height, required List<int> txBytes, required Coin c}) { + Future<String> crateApiPayBroadcastTransaction({ + required int height, + required List<int> txBytes, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1534,8 +1922,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(txBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 18, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 18, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1561,8 +1953,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_recipient(recipients, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 19, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 19, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1575,22 +1971,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayBuildPuriConstMeta => const TaskConstMeta( - debugName: "build_puri", - argNames: ["recipients"], - ); + TaskConstMeta get kCrateApiPayBuildPuriConstMeta => + const TaskConstMeta(debugName: "build_puri", argNames: ["recipients"]); @override - Future<void> crateApiSyncCacheBlockTime( - {required int height, required Coin c}) { + Future<void> crateApiSyncCacheBlockTime({ + required int height, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(height, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 20, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 20, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1604,9 +2004,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSyncCacheBlockTimeConstMeta => const TaskConstMeta( - debugName: "cache_block_time", - argNames: ["height", "c"], - ); + debugName: "cache_block_time", + argNames: ["height", "c"], + ); @override Future<void> crateApiFrostCancelDkg({required Coin c}) { @@ -1615,8 +2015,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 21, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 21, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1629,10 +2033,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostCancelDkgConstMeta => const TaskConstMeta( - debugName: "cancel_dkg", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiFrostCancelDkgConstMeta => + const TaskConstMeta(debugName: "cancel_dkg", argNames: ["c"]); @override Future<void> crateApiSyncCancelSync() { @@ -1640,8 +2042,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 22, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 22, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1654,17 +2060,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSyncCancelSyncConstMeta => const TaskConstMeta( - debugName: "cancel_sync", - argNames: [], - ); + TaskConstMeta get kCrateApiSyncCancelSyncConstMeta => + const TaskConstMeta(debugName: "cancel_sync", argNames: []); @override - Future<void> crateApiDbChangeDbPassword( - {required String dbFilepath, - required String tmpDir, - required String oldPassword, - required String newPassword}) { + Future<void> crateApiDbChangeDbPassword({ + required String dbFilepath, + required String tmpDir, + required String oldPassword, + required String newPassword, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1673,8 +2078,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(tmpDir, serializer); sse_encode_String(oldPassword, serializer); sse_encode_String(newPassword, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 23, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 23, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1688,9 +2097,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiDbChangeDbPasswordConstMeta => const TaskConstMeta( - debugName: "change_db_password", - argNames: ["dbFilepath", "tmpDir", "oldPassword", "newPassword"], - ); + debugName: "change_db_password", + argNames: ["dbFilepath", "tmpDir", "oldPassword", "newPassword"], + ); @override SaplingParamsStatus crateApiSaplingCheckSaplingParams() { @@ -1712,10 +2121,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSaplingCheckSaplingParamsConstMeta => - const TaskConstMeta( - debugName: "check_sapling_params", - argNames: [], - ); + const TaskConstMeta(debugName: "check_sapling_params", argNames: []); @override Future<void> crateApiCoinClosePool({required String dbFilepath}) { @@ -1724,8 +2130,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 25, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 25, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1738,10 +2148,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinClosePoolConstMeta => const TaskConstMeta( - debugName: "close_pool", - argNames: ["dbFilepath"], - ); + TaskConstMeta get kCrateApiCoinClosePoolConstMeta => + const TaskConstMeta(debugName: "close_pool", argNames: ["dbFilepath"]); @override Future<void> crateApiCoinCoinGetName({required Coin that}) { @@ -1750,8 +2158,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 26, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 26, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1764,10 +2176,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinCoinGetNameConstMeta => const TaskConstMeta( - debugName: "coin_get_name", - argNames: ["that"], - ); + TaskConstMeta get kCrateApiCoinCoinGetNameConstMeta => + const TaskConstMeta(debugName: "coin_get_name", argNames: ["that"]); @override Coin crateApiCoinCoinNew({int? defaultCoin}) { @@ -1789,14 +2199,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinCoinNewConstMeta => const TaskConstMeta( - debugName: "coin_new", - argNames: ["defaultCoin"], - ); + TaskConstMeta get kCrateApiCoinCoinNewConstMeta => + const TaskConstMeta(debugName: "coin_new", argNames: ["defaultCoin"]); @override - Future<Coin> crateApiCoinCoinOpenDatabase( - {required Coin that, required String dbFilepath, String? password}) { + Future<Coin> crateApiCoinCoinOpenDatabase({ + required Coin that, + required String dbFilepath, + String? password, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1804,8 +2215,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(that, serializer); sse_encode_String(dbFilepath, serializer); sse_encode_opt_String(password, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 28, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 28, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1825,16 +2240,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Coin> crateApiCoinCoinSetAccount( - {required Coin that, required int account}) { + Future<Coin> crateApiCoinCoinSetAccount({ + required Coin that, + required int account, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(that, serializer); sse_encode_u_32(account, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 29, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 29, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_coin, @@ -1848,13 +2269,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiCoinCoinSetAccountConstMeta => const TaskConstMeta( - debugName: "coin_set_account", - argNames: ["that", "account"], - ); + debugName: "coin_set_account", + argNames: ["that", "account"], + ); @override - Coin crateApiCoinCoinSetLwd( - {required Coin that, required int serverType, required String url}) { + Coin crateApiCoinCoinSetLwd({ + required Coin that, + required int serverType, + required String url, + }) { return handler.executeSync( SyncTask( callFfi: () { @@ -1876,9 +2300,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiCoinCoinSetLwdConstMeta => const TaskConstMeta( - debugName: "coin_set_lwd", - argNames: ["that", "serverType", "url"], - ); + debugName: "coin_set_lwd", + argNames: ["that", "serverType", "url"], + ); @override Coin crateApiCoinCoinSetProxy({required Coin that, required String proxy}) { @@ -1902,13 +2326,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiCoinCoinSetProxyConstMeta => const TaskConstMeta( - debugName: "coin_set_proxy", - argNames: ["that", "proxy"], - ); + debugName: "coin_set_proxy", + argNames: ["that", "proxy"], + ); @override - Coin crateApiCoinCoinSetTransport( - {required Coin that, required int transport}) { + Coin crateApiCoinCoinSetTransport({ + required Coin that, + required int transport, + }) { return handler.executeSync( SyncTask( callFfi: () { @@ -1935,11 +2361,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Contact> crateApiContactsCreateContact( - {required String name, - required List<String> addresses, - required String notes, - required Coin c}) { + Future<Contact> crateApiContactsCreateContact({ + required String name, + required List<String> addresses, + required String notes, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -1948,8 +2375,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(addresses, serializer); sse_encode_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 33, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 33, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_contact, @@ -1969,16 +2400,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<int> crateApiAccountCreateNewCategory( - {required Category category, required Coin c}) { + Future<int> crateApiAccountCreateNewCategory({ + required Category category, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 34, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 34, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -1998,16 +2435,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Folder> crateApiAccountCreateNewFolder( - {required String name, required Coin c}) { + Future<Folder> crateApiAccountCreateNewFolder({ + required String name, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 35, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 35, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_folder, @@ -2033,8 +2476,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(packet, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 36, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 36, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_prim_u_8_strict, @@ -2047,19 +2494,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiRaptorDecodeConstMeta => const TaskConstMeta( - debugName: "decode", - argNames: ["packet"], - ); + TaskConstMeta get kCrateApiRaptorDecodeConstMeta => + const TaskConstMeta(debugName: "decode", argNames: ["packet"]); @override - Stream<VotingDelegationProgress> crateApiVotingDelegationBuildSubmission( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - VotingPirLayout? pirLayout, - required String pirServerUrl, - required Coin c}) { + Stream<VotingDelegationProgress> crateApiVotingDelegationBuildSubmission({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + VotingPirLayout? pirLayout, + required String pirServerUrl, + required Coin c, + }) { final sink = RustStreamSink<VotingDelegationProgress>(); unawaited( handler.executeNormal( @@ -2067,15 +2513,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_voting_delegation_progress_Sse( - sink, serializer); + sink, + serializer, + ); sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_list_prim_u_8_loose(pcztBytes, serializer); sse_encode_opt_box_autoadd_voting_pir_layout(pirLayout, serializer); sse_encode_String(pirServerUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 37, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 37, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_build, @@ -2089,7 +2541,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pcztBytes, pirLayout, pirServerUrl, - c + c, ], apiImpl: this, ), @@ -2108,17 +2560,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "pcztBytes", "pirLayout", "pirServerUrl", - "c" + "c", ], ); @override - Future<VotingDelegationConfirmation> crateApiVotingDelegationConfirm( - {required String roundId, - required int bundleIndex, - required String txHash, - required String eventsJson, - required Coin c}) { + Future<VotingDelegationConfirmation> crateApiVotingDelegationConfirm({ + required String roundId, + required int bundleIndex, + required String txHash, + required String eventsJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2128,8 +2581,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txHash, serializer); sse_encode_String(eventsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 38, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 38, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_confirmation, @@ -2149,11 +2606,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVotingDelegationMarkSubmitted( - {required String roundId, - required int bundleIndex, - required String txHash, - required Coin c}) { + Future<void> crateApiVotingDelegationMarkSubmitted({ + required String roundId, + required int bundleIndex, + required String txHash, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2162,8 +2620,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_String(txHash, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 39, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 39, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2183,14 +2645,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingPreparedInfo> crateApiVotingDelegationPrepare( - {required String roundParamsJson, - required String roundName, - String? sessionJson, - required int bundleIndex, - int? maxRealNotesPerBundle, - required String lightwalletdUrl, - required Coin c}) { + Future<VotingPreparedInfo> crateApiVotingDelegationPrepare({ + required String roundParamsJson, + required String roundName, + String? sessionJson, + required int bundleIndex, + int? maxRealNotesPerBundle, + required String lightwalletdUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2202,8 +2665,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(maxRealNotesPerBundle, serializer); sse_encode_String(lightwalletdUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 40, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 40, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_prepared_info, @@ -2217,7 +2684,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { bundleIndex, maxRealNotesPerBundle, lightwalletdUrl, - c + c, ], apiImpl: this, ), @@ -2234,17 +2701,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "bundleIndex", "maxRealNotesPerBundle", "lightwalletdUrl", - "c" + "c", ], ); @override - Future<VotingPreparedInfo> crateApiVotingDelegationPrepareResume( - {required String roundId, - required int bundleIndex, - int? maxRealNotesPerBundle, - String? lightwalletdUrl, - required Coin c}) { + Future<VotingPreparedInfo> crateApiVotingDelegationPrepareResume({ + required String roundId, + required int bundleIndex, + int? maxRealNotesPerBundle, + String? lightwalletdUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2254,8 +2722,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(maxRealNotesPerBundle, serializer); sse_encode_opt_String(lightwalletdUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 41, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 41, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_prepared_info, @@ -2267,7 +2739,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { bundleIndex, maxRealNotesPerBundle, lightwalletdUrl, - c + c, ], apiImpl: this, ), @@ -2282,13 +2754,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "bundleIndex", "maxRealNotesPerBundle", "lightwalletdUrl", - "c" + "c", ], ); @override - Future<VotingDelegationSetup> crateApiVotingDelegationSetup( - {required String roundId, required int bundleIndex, required Coin c}) { + Future<VotingDelegationSetup> crateApiVotingDelegationSetup({ + required String roundId, + required int bundleIndex, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2296,8 +2771,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 42, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 42, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_setup, @@ -2317,13 +2796,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingDelegationSubmission> crateApiVotingDelegationSignAndSubmit( - {required String roundId, - required int bundleIndex, - required List<int> pcztBytes, - required VotingPirLayout pirLayout, - required String pirServerUrl, - required Coin c}) { + Future<VotingDelegationSubmission> crateApiVotingDelegationSignAndSubmit({ + required String roundId, + required int bundleIndex, + required List<int> pcztBytes, + required VotingPirLayout pirLayout, + required String pirServerUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2334,8 +2814,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_voting_pir_layout(pirLayout, serializer); sse_encode_String(pirServerUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 43, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 43, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_delegation_submission, @@ -2348,7 +2832,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pcztBytes, pirLayout, pirServerUrl, - c + c, ], apiImpl: this, ), @@ -2364,13 +2848,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "pcztBytes", "pirLayout", "pirServerUrl", - "c" + "c", ], ); @override - Future<String?> crateApiVotingDelegationTxHash( - {required String roundId, required int bundleIndex, required Coin c}) { + Future<String?> crateApiVotingDelegationTxHash({ + required String roundId, + required int bundleIndex, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2378,8 +2865,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 44, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 44, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2399,8 +2890,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String?> crateApiVotingDelegationWireJson( - {required String roundId, required int bundleIndex, required Coin c}) { + Future<String?> crateApiVotingDelegationWireJson({ + required String roundId, + required int bundleIndex, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2408,8 +2902,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 45, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 45, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -2429,16 +2927,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountDeleteAccount( - {required int account, required Coin c}) { + Future<void> crateApiAccountDeleteAccount({ + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 46, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 46, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2458,16 +2962,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountDeleteCategories( - {required List<int> ids, required Coin c}) { + Future<void> crateApiAccountDeleteCategories({ + required List<int> ids, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 47, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 47, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2487,16 +2997,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiContactsDeleteContacts( - {required List<int> ids, required Coin c}) { + Future<void> crateApiContactsDeleteContacts({ + required List<int> ids, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 48, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 48, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2510,22 +3026,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiContactsDeleteContactsConstMeta => - const TaskConstMeta( - debugName: "delete_contacts", - argNames: ["ids", "c"], - ); + const TaskConstMeta(debugName: "delete_contacts", argNames: ["ids", "c"]); @override - Future<void> crateApiAccountDeleteFolders( - {required List<int> ids, required Coin c}) { + Future<void> crateApiAccountDeleteFolders({ + required List<int> ids, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_32_loose(ids, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 49, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 49, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2539,10 +3058,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountDeleteFoldersConstMeta => - const TaskConstMeta( - debugName: "delete_folders", - argNames: ["ids", "c"], - ); + const TaskConstMeta(debugName: "delete_folders", argNames: ["ids", "c"]); @override Stream<DKGStatus> crateApiFrostDoDkg({required Coin c}) { @@ -2554,8 +3070,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_dkg_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 50, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 50, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2570,10 +3090,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return status.stream; } - TaskConstMeta get kCrateApiFrostDoDkgConstMeta => const TaskConstMeta( - debugName: "do_dkg", - argNames: ["status", "c"], - ); + TaskConstMeta get kCrateApiFrostDoDkgConstMeta => + const TaskConstMeta(debugName: "do_dkg", argNames: ["status", "c"]); @override Stream<SigningStatus> crateApiFrostDoSign({required Coin c}) { @@ -2585,8 +3103,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_signing_status_Sse(status, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 51, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 51, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2601,10 +3123,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return status.stream; } - TaskConstMeta get kCrateApiFrostDoSignConstMeta => const TaskConstMeta( - debugName: "do_sign", - argNames: ["status", "c"], - ); + TaskConstMeta get kCrateApiFrostDoSignConstMeta => + const TaskConstMeta(debugName: "do_sign", argNames: ["status", "c"]); @override Future<void> crateApiSaplingDownloadSaplingParams() { @@ -2612,8 +3132,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 52, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 52, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2627,10 +3151,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSaplingDownloadSaplingParamsConstMeta => - const TaskConstMeta( - debugName: "download_sapling_params", - argNames: [], - ); + const TaskConstMeta(debugName: "download_sapling_params", argNames: []); @override Future<void> crateApiAccountDummyExport({required SigningEvent a}) { @@ -2639,8 +3160,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_signing_event(a, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 53, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 53, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2653,22 +3178,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountDummyExportConstMeta => const TaskConstMeta( - debugName: "dummy_export", - argNames: ["a"], - ); + TaskConstMeta get kCrateApiAccountDummyExportConstMeta => + const TaskConstMeta(debugName: "dummy_export", argNames: ["a"]); @override - Future<List<Uint8List>> crateApiRaptorEncode( - {required String path, required RaptorQParams params}) { + Future<List<Uint8List>> crateApiRaptorEncode({ + required String path, + required RaptorQParams params, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(path, serializer); sse_encode_box_autoadd_raptor_q_params(params, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 54, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 54, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_list_prim_u_8_strict, @@ -2681,10 +3210,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiRaptorEncodeConstMeta => const TaskConstMeta( - debugName: "encode", - argNames: ["path", "params"], - ); + TaskConstMeta get kCrateApiRaptorEncodeConstMeta => + const TaskConstMeta(debugName: "encode", argNames: ["path", "params"]); @override Future<void> crateApiRaptorEndDecode() { @@ -2692,8 +3219,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 55, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 55, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2706,14 +3237,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiRaptorEndDecodeConstMeta => const TaskConstMeta( - debugName: "end_decode", - argNames: [], - ); + TaskConstMeta get kCrateApiRaptorEndDecodeConstMeta => + const TaskConstMeta(debugName: "end_decode", argNames: []); @override - Future<Uint8List> crateApiAccountExportAccount( - {required int id, required String passphrase, required Coin c}) { + Future<Uint8List> crateApiAccountExportAccount({ + required int id, + required String passphrase, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2721,8 +3253,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(passphrase, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 56, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 56, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2748,8 +3284,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 57, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 57, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -2763,21 +3303,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiContactsExportContactsVcardConstMeta => - const TaskConstMeta( - debugName: "export_contacts_vcard", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "export_contacts_vcard", argNames: ["c"]); @override - Future<Uint8List> crateApiPayExtractTransaction( - {required PcztPackage package}) { + Future<Uint8List> crateApiPayExtractTransaction({ + required PcztPackage package, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 58, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 58, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -2797,8 +3339,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<TAddressTxCount>> crateApiAccountFetchAddressTxCount( - {required Coin c, required bool aggregate, required int poolFilter}) { + Future<List<TAddressTxCount>> crateApiAccountFetchAddressTxCount({ + required Coin c, + required bool aggregate, + required int poolFilter, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2806,8 +3351,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_coin(c, serializer); sse_encode_bool(aggregate, serializer); sse_encode_u_8(poolFilter, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 59, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 59, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2827,8 +3376,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<(int, double)>> crateApiTransactionFetchAmounts( - {int? from, int? to, required int category, required Coin c}) { + Future<List<(int, double)>> crateApiTransactionFetchAmounts({ + int? from, + int? to, + required int category, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2837,8 +3390,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 60, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 60, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_u_32_f_64, @@ -2858,8 +3415,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<(String, double, bool)>> crateApiTransactionFetchCategoryAmounts( - {int? from, int? to, required Coin c}) { + Future<List<(String, double, bool)>> crateApiTransactionFetchCategoryAmounts({ + int? from, + int? to, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2867,8 +3427,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_32(from, serializer); sse_encode_opt_box_autoadd_u_32(to, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 61, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 61, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_record_string_f_64_bool, @@ -2888,15 +3452,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<TAddressTxCount>> crateApiAccountFetchTransparentAddressTxCount( - {required Coin c}) { + Future<List<TAddressTxCount>> crateApiAccountFetchTransparentAddressTxCount({ + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 62, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 62, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_t_address_tx_count, @@ -2916,16 +3485,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiSyncFetchTxDetails( - {required int account, required Coin c}) { + Future<void> crateApiSyncFetchTxDetails({ + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 63, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 63, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -2939,13 +3514,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSyncFetchTxDetailsConstMeta => const TaskConstMeta( - debugName: "fetch_tx_details", - argNames: ["account", "c"], - ); + debugName: "fetch_tx_details", + argNames: ["account", "c"], + ); @override - Future<int> crateApiTransactionFillMissingTxPrices( - {required String api, required String currency, required Coin c}) { + Future<int> crateApiTransactionFillMissingTxPrices({ + required String api, + required String currency, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -2953,8 +3531,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(currency, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 64, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 64, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -2974,16 +3556,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<ContactMatch>> crateApiContactsFindContactsForAddress( - {required String address, required Coin c}) { + Future<List<ContactMatch>> crateApiContactsFindContactsForAddress({ + required String address, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 65, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 65, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact_match, @@ -3008,8 +3596,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 66, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 66, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_frost_sign_params, @@ -3023,10 +3615,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostFrostSignParamsDefaultConstMeta => - const TaskConstMeta( - debugName: "frost_sign_params_default", - argNames: [], - ); + const TaskConstMeta(debugName: "frost_sign_params_default", argNames: []); @override Future<String?> crateApiAccountGenerateNextChangeAddress({required Coin c}) { @@ -3035,8 +3624,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 67, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 67, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -3062,8 +3655,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 68, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 68, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -3077,10 +3674,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountGenerateNextDindexConstMeta => - const TaskConstMeta( - debugName: "generate_next_dindex", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "generate_next_dindex", argNames: ["c"]); @override String crateApiKeyGenerateSeed() { @@ -3101,14 +3695,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyGenerateSeedConstMeta => const TaskConstMeta( - debugName: "generate_seed", - argNames: [], - ); + TaskConstMeta get kCrateApiKeyGenerateSeedConstMeta => + const TaskConstMeta(debugName: "generate_seed", argNames: []); @override - Future<Addresses> crateApiAccountGetAccountAddresses( - {required int account, required int uaPools, required Coin c}) { + Future<Addresses> crateApiAccountGetAccountAddresses({ + required int account, + required int uaPools, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3116,8 +3711,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 70, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 70, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -3137,16 +3736,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String?> crateApiAccountGetAccountFingerprint( - {required int account, required Coin c}) { + Future<String?> crateApiAccountGetAccountFingerprint({ + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 71, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 71, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -3172,8 +3777,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 72, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 72, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_frost_params, @@ -3193,16 +3802,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<int> crateApiAccountGetAccountPools( - {required int account, required Coin c}) { + Future<int> crateApiAccountGetAccountPools({ + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 73, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 73, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_8, @@ -3222,16 +3837,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Seed?> crateApiAccountGetAccountSeed( - {required int account, required Coin c}) { + Future<Seed?> crateApiAccountGetAccountSeed({ + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 74, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 74, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_seed, @@ -3251,8 +3872,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiAccountGetAccountUfvk( - {required int account, required int pools, required Coin c}) { + Future<String> crateApiAccountGetAccountUfvk({ + required int account, + required int pools, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3260,8 +3884,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(account, serializer); sse_encode_u_8(pools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 75, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 75, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -3281,16 +3909,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Addresses> crateApiAccountGetAddresses( - {required int uaPools, required Coin c}) { + Future<Addresses> crateApiAccountGetAddresses({ + required int uaPools, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(uaPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 76, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 76, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_addresses, @@ -3310,16 +3944,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<double> crateApiNetworkGetCoingeckoPrice( - {required String api, required String currency}) { + Future<double> crateApiNetworkGetCoingeckoPrice({ + required String api, + required String currency, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); sse_encode_String(currency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 77, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 77, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_f_64, @@ -3345,8 +3985,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 78, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 78, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -3360,10 +4004,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiNetworkGetCurrentHeightConstMeta => - const TaskConstMeta( - debugName: "get_current_height", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "get_current_height", argNames: ["c"]); @override Future<SyncHeight> crateApiSyncGetDbHeight({required Coin c}) { @@ -3372,8 +4013,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 79, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 79, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_sync_height, @@ -3386,10 +4031,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiSyncGetDbHeightConstMeta => const TaskConstMeta( - debugName: "get_db_height", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiSyncGetDbHeightConstMeta => + const TaskConstMeta(debugName: "get_db_height", argNames: ["c"]); @override Future<List<String>> crateApiFrostGetDkgAddresses({required Coin c}) { @@ -3398,8 +4041,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 80, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 80, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3413,16 +4060,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostGetDkgAddressesConstMeta => - const TaskConstMeta( - debugName: "get_dkg_addresses", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "get_dkg_addresses", argNames: ["c"]); @override - Future<ExchangeRate> crateApiNetworkGetExchangeRate( - {required String api, - required String fromCurrency, - required String toCurrency}) { + Future<ExchangeRate> crateApiNetworkGetExchangeRate({ + required String api, + required String fromCurrency, + required String toCurrency, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3430,8 +4075,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(api, serializer); sse_encode_String(fromCurrency, serializer); sse_encode_String(toCurrency, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 81, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 81, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_exchange_rate, @@ -3451,16 +4100,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiAccountGetExportedData( - {required int type, required Coin c}) { + Future<String> crateApiAccountGetExportedData({ + required int type, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(type, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 82, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 82, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -3500,22 +4155,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyGetKeyPoolsConstMeta => const TaskConstMeta( - debugName: "get_key_pools", - argNames: ["key", "c"], - ); + TaskConstMeta get kCrateApiKeyGetKeyPoolsConstMeta => + const TaskConstMeta(debugName: "get_key_pools", argNames: ["key", "c"]); @override - Future<Uint8List> crateApiMempoolGetMempoolTx( - {required String txId, required Coin c}) { + Future<Uint8List> crateApiMempoolGetMempoolTx({ + required String txId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(txId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 84, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 84, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -3529,10 +4188,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMempoolGetMempoolTxConstMeta => - const TaskConstMeta( - debugName: "get_mempool_tx", - argNames: ["txId", "c"], - ); + const TaskConstMeta(debugName: "get_mempool_tx", argNames: ["txId", "c"]); @override Future<MigrationStatus> crateApiMigrateGetMigrationStatus({required Coin c}) { @@ -3541,8 +4197,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 85, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 85, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_status, @@ -3556,10 +4216,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMigrateGetMigrationStatusConstMeta => - const TaskConstMeta( - debugName: "get_migration_status", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "get_migration_status", argNames: ["c"]); @override Future<String> crateApiNetworkGetNetworkName({required Coin c}) { @@ -3568,8 +4225,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 86, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 86, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -3583,10 +4244,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiNetworkGetNetworkNameConstMeta => - const TaskConstMeta( - debugName: "get_network_name", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "get_network_name", argNames: ["c"]); @override Future<String?> crateApiDbGetProp({required String key, required Coin c}) { @@ -3596,8 +4254,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 87, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 87, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -3610,10 +4272,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiDbGetPropConstMeta => const TaskConstMeta( - debugName: "get_prop", - argNames: ["key", "c"], - ); + TaskConstMeta get kCrateApiDbGetPropConstMeta => + const TaskConstMeta(debugName: "get_prop", argNames: ["key", "c"]); @override Uint8List crateApiRaptorGetQrBytes({required List<int> data}) { @@ -3635,21 +4295,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiRaptorGetQrBytesConstMeta => const TaskConstMeta( - debugName: "get_qr_bytes", - argNames: ["data"], - ); + TaskConstMeta get kCrateApiRaptorGetQrBytesConstMeta => + const TaskConstMeta(debugName: "get_qr_bytes", argNames: ["data"]); @override - Future<List<String>> crateApiNetworkGetSupportedVsCurrencies( - {required String api}) { + Future<List<String>> crateApiNetworkGetSupportedVsCurrencies({ + required String api, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(api, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 89, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 89, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -3674,8 +4337,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 90, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 90, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3688,22 +4355,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinGetTorClientConstMeta => const TaskConstMeta( - debugName: "get_tor_client", - argNames: [], - ); + TaskConstMeta get kCrateApiCoinGetTorClientConstMeta => + const TaskConstMeta(debugName: "get_tor_client", argNames: []); @override - Future<TxAccount> crateApiAccountGetTxDetails( - {required int idTx, required Coin c}) { + Future<TxAccount> crateApiAccountGetTxDetails({ + required int idTx, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(idTx, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 91, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 91, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -3717,10 +4388,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountGetTxDetailsConstMeta => - const TaskConstMeta( - debugName: "get_tx_details", - argNames: ["idTx", "c"], - ); + const TaskConstMeta(debugName: "get_tx_details", argNames: ["idTx", "c"]); @override Future<bool> crateApiFrostHasDkgAddresses({required Coin c}) { @@ -3729,8 +4397,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 92, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 92, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3744,10 +4416,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostHasDkgAddressesConstMeta => - const TaskConstMeta( - debugName: "has_dkg_addresses", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "has_dkg_addresses", argNames: ["c"]); @override Future<bool> crateApiFrostHasDkgParams({required Coin c}) { @@ -3756,8 +4425,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 93, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 93, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3770,10 +4443,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostHasDkgParamsConstMeta => const TaskConstMeta( - debugName: "has_dkg_params", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiFrostHasDkgParamsConstMeta => + const TaskConstMeta(debugName: "has_dkg_params", argNames: ["c"]); @override Future<bool> crateApiAccountHasTransparentPubKey({required Coin c}) { @@ -3782,8 +4453,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 94, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 94, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -3803,8 +4478,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountImportAccount( - {required String passphrase, required List<int> data, required Coin c}) { + Future<void> crateApiAccountImportAccount({ + required String passphrase, + required List<int> data, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -3812,8 +4490,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(passphrase, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 95, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 95, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3833,16 +4515,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<Contact>> crateApiContactsImportContactsVcard( - {required String vcardData, required Coin c}) { + Future<List<Contact>> crateApiContactsImportContactsVcard({ + required String vcardData, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(vcardData, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 96, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 96, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -3867,8 +4555,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 97, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 97, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3881,10 +4573,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiInitInitAppConstMeta => const TaskConstMeta( - debugName: "init_app", - argNames: [], - ); + TaskConstMeta get kCrateApiInitInitAppConstMeta => + const TaskConstMeta(debugName: "init_app", argNames: []); @override Future<void> crateApiRaptorInitApp() { @@ -3892,8 +4582,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 98, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 98, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3906,10 +4600,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiRaptorInitAppConstMeta => const TaskConstMeta( - debugName: "init_app", - argNames: [], - ); + TaskConstMeta get kCrateApiRaptorInitAppConstMeta => + const TaskConstMeta(debugName: "init_app", argNames: []); @override Future<void> crateApiCoinInitDatadir({required String directory}) { @@ -3918,8 +4610,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 99, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 99, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3932,10 +4628,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiCoinInitDatadirConstMeta => const TaskConstMeta( - debugName: "init_datadir", - argNames: ["directory"], - ); + TaskConstMeta get kCrateApiCoinInitDatadirConstMeta => + const TaskConstMeta(debugName: "init_datadir", argNames: ["directory"]); @override Future<void> crateApiNetworkInitDatadir({required String directory}) { @@ -3944,8 +4638,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(directory, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 100, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 100, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3958,10 +4656,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiNetworkInitDatadirConstMeta => const TaskConstMeta( - debugName: "init_datadir", - argNames: ["directory"], - ); + TaskConstMeta get kCrateApiNetworkInitDatadirConstMeta => + const TaskConstMeta(debugName: "init_datadir", argNames: ["directory"]); @override Future<void> crateApiFrostInitDkg({required Coin c}) { @@ -3970,8 +4666,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 101, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 101, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -3984,10 +4684,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostInitDkgConstMeta => const TaskConstMeta( - debugName: "init_dkg", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiFrostInitDkgConstMeta => + const TaskConstMeta(debugName: "init_dkg", argNames: ["c"]); @override void crateApiPluginInitPlugins() { @@ -3995,8 +4693,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 102)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 102, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4009,17 +4710,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginInitPluginsConstMeta => const TaskConstMeta( - debugName: "init_plugins", - argNames: [], - ); + TaskConstMeta get kCrateApiPluginInitPluginsConstMeta => + const TaskConstMeta(debugName: "init_plugins", argNames: []); @override - Future<void> crateApiFrostInitSign( - {required int coordinator, - required int fundingAccount, - required PcztPackage pczt, - required Coin c}) { + Future<void> crateApiFrostInitSign({ + required int coordinator, + required int fundingAccount, + required PcztPackage pczt, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4028,8 +4728,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 103, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 103, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4043,21 +4747,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostInitSignConstMeta => const TaskConstMeta( - debugName: "init_sign", - argNames: ["coordinator", "fundingAccount", "pczt", "c"], - ); + debugName: "init_sign", + argNames: ["coordinator", "fundingAccount", "pczt", "c"], + ); @override - Future<DartVault> crateApiVaultInitVault( - {required FutureOr<void> Function(Uint8List) append}) { + Future<DartVault> crateApiVaultInitVault({ + required FutureOr<void> Function(Uint8List) append, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - append, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 104, port: port_); + append, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 104, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: @@ -4071,22 +4782,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVaultInitVaultConstMeta => const TaskConstMeta( - debugName: "init_vault", - argNames: ["append"], - ); + TaskConstMeta get kCrateApiVaultInitVaultConstMeta => + const TaskConstMeta(debugName: "init_vault", argNames: ["append"]); @override - Future<PluginInfo> crateApiPluginInstallPlugin( - {required String url, required Coin c}) { + Future<PluginInfo> crateApiPluginInstallPlugin({ + required String url, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(url, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 105, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 105, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_plugin_info, @@ -4100,10 +4815,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiPluginInstallPluginConstMeta => - const TaskConstMeta( - debugName: "install_plugin", - argNames: ["url", "c"], - ); + const TaskConstMeta(debugName: "install_plugin", argNames: ["url", "c"]); @override Future<bool> crateApiNetworkIsIronwoodActive({required Coin c}) { @@ -4112,8 +4824,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 106, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 106, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4127,10 +4843,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiNetworkIsIronwoodActiveConstMeta => - const TaskConstMeta( - debugName: "is_ironwood_active", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "is_ironwood_active", argNames: ["c"]); @override Future<bool> crateApiFrostIsSigningInProgress({required Coin c}) { @@ -4139,8 +4852,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 107, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 107, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4154,10 +4871,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostIsSigningInProgressConstMeta => - const TaskConstMeta( - debugName: "is_signing_in_progress", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "is_signing_in_progress", argNames: ["c"]); @override bool crateApiKeyIsTexAddress({required String address, required Coin c}) { @@ -4167,8 +4881,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 108)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 108, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4182,9 +4899,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiKeyIsTexAddressConstMeta => const TaskConstMeta( - debugName: "is_tex_address", - argNames: ["address", "c"], - ); + debugName: "is_tex_address", + argNames: ["address", "c"], + ); @override bool crateApiKeyIsValidAddress({required String address}) { @@ -4193,8 +4910,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 109)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 109, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4207,10 +4927,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyIsValidAddressConstMeta => const TaskConstMeta( - debugName: "is_valid_address", - argNames: ["address"], - ); + TaskConstMeta get kCrateApiKeyIsValidAddressConstMeta => + const TaskConstMeta(debugName: "is_valid_address", argNames: ["address"]); @override bool crateApiKeyIsValidFvk({required String fvk, required Coin c}) { @@ -4220,8 +4938,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(fvk, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 110)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 110, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4234,10 +4955,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyIsValidFvkConstMeta => const TaskConstMeta( - debugName: "is_valid_fvk", - argNames: ["fvk", "c"], - ); + TaskConstMeta get kCrateApiKeyIsValidFvkConstMeta => + const TaskConstMeta(debugName: "is_valid_fvk", argNames: ["fvk", "c"]); @override bool crateApiKeyIsValidKey({required String key, required Coin c}) { @@ -4247,8 +4966,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(key, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 111)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 111, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4261,10 +4983,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyIsValidKeyConstMeta => const TaskConstMeta( - debugName: "is_valid_key", - argNames: ["key", "c"], - ); + TaskConstMeta get kCrateApiKeyIsValidKeyConstMeta => + const TaskConstMeta(debugName: "is_valid_key", argNames: ["key", "c"]); @override bool crateApiNetworkIsValidNymUrl({required String url}) { @@ -4273,8 +4993,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(url, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 112)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 112, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4288,10 +5011,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiNetworkIsValidNymUrlConstMeta => - const TaskConstMeta( - debugName: "is_valid_nym_url", - argNames: ["url"], - ); + const TaskConstMeta(debugName: "is_valid_nym_url", argNames: ["url"]); @override bool crateApiKeyIsValidPhrase({required String phrase}) { @@ -4300,8 +5020,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(phrase, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 113)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 113, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4314,22 +5037,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiKeyIsValidPhraseConstMeta => const TaskConstMeta( - debugName: "is_valid_phrase", - argNames: ["phrase"], - ); + TaskConstMeta get kCrateApiKeyIsValidPhraseConstMeta => + const TaskConstMeta(debugName: "is_valid_phrase", argNames: ["phrase"]); @override - bool crateApiKeyIsValidTransparentAddress( - {required String address, required Coin c}) { + bool crateApiKeyIsValidTransparentAddress({ + required String address, + required Coin c, + }) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 114)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 114, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4355,8 +5081,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 115, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 115, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -4369,20 +5099,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiZsaIsZsaAvailableConstMeta => const TaskConstMeta( - debugName: "is_zsa_available", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiZsaIsZsaAvailableConstMeta => + const TaskConstMeta(debugName: "is_zsa_available", argNames: ["c"]); @override - Future<Uint8List> crateApiIssuanceIssueAsset( - {required String assetName, - required BigInt amount, - required bool firstIssuance, - required bool finalize, - Uint8List? descHash, - required int idAccount, - required Coin c}) { + Future<Uint8List> crateApiIssuanceIssueAsset({ + required String assetName, + required BigInt amount, + required bool firstIssuance, + required bool finalize, + Uint8List? descHash, + required int idAccount, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4394,8 +5123,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_prim_u_8_strict(descHash, serializer); sse_encode_u_32(idAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 116, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 116, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4409,7 +5142,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { finalize, descHash, idAccount, - c + c, ], apiImpl: this, ), @@ -4417,16 +5150,137 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiIssuanceIssueAssetConstMeta => const TaskConstMeta( - debugName: "issue_asset", - argNames: [ - "assetName", - "amount", - "firstIssuance", - "finalize", - "descHash", - "idAccount", - "c" - ], + debugName: "issue_asset", + argNames: [ + "assetName", + "amount", + "firstIssuance", + "finalize", + "descHash", + "idAccount", + "c", + ], + ); + + @override + Future<String> crateApiLedgerLedgerAppVersion({ + required FutureOr<Uint8List> Function(Uint8List) exchange, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + exchange, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 117, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLedgerLedgerAppVersionConstMeta, + argValues: [exchange], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiLedgerLedgerAppVersionConstMeta => + const TaskConstMeta( + debugName: "ledger_app_version", + argNames: ["exchange"], + ); + + @override + Future<String> crateApiLedgerLedgerGetUfvk({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(aindex, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + exchange, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 118, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLedgerLedgerGetUfvkConstMeta, + argValues: [aindex, c, exchange], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiLedgerLedgerGetUfvkConstMeta => + const TaskConstMeta( + debugName: "ledger_get_ufvk", + argNames: ["aindex", "c", "exchange"], + ); + + @override + Stream<SigningEvent> crateApiLedgerLedgerSignTransaction({ + required PcztPackage package, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }) { + final sink = RustStreamSink<SigningEvent>(); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_StreamSink_signing_event_Sse(sink, serializer); + sse_encode_box_autoadd_pczt_package(package, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + exchange, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 119, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLedgerLedgerSignTransactionConstMeta, + argValues: [sink, package, c, exchange], + apiImpl: this, + ), + ), + ); + return sink.stream; + } + + TaskConstMeta get kCrateApiLedgerLedgerSignTransactionConstMeta => + const TaskConstMeta( + debugName: "ledger_sign_transaction", + argNames: ["sink", "package", "c", "exchange"], ); @override @@ -4436,8 +5290,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 117, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 120, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_account, @@ -4451,10 +5309,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountListAccountsConstMeta => - const TaskConstMeta( - debugName: "list_accounts", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "list_accounts", argNames: ["c"]); @override Future<List<Category>> crateApiAccountListCategories({required Coin c}) { @@ -4463,8 +5318,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 118, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 121, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_category, @@ -4478,10 +5337,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountListCategoriesConstMeta => - const TaskConstMeta( - debugName: "list_categories", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "list_categories", argNames: ["c"]); @override Future<List<Contact>> crateApiContactsListContacts({required Coin c}) { @@ -4490,8 +5346,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 119, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 122, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_contact, @@ -4505,21 +5365,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiContactsListContactsConstMeta => - const TaskConstMeta( - debugName: "list_contacts", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "list_contacts", argNames: ["c"]); @override - Future<List<DbAccountPreview>> crateApiDbListDbAccounts( - {required String dbFilepath}) { + Future<List<DbAccountPreview>> crateApiDbListDbAccounts({ + required String dbFilepath, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dbFilepath, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 120, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 123, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_db_account_preview, @@ -4533,9 +5395,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiDbListDbAccountsConstMeta => const TaskConstMeta( - debugName: "list_db_accounts", - argNames: ["dbFilepath"], - ); + debugName: "list_db_accounts", + argNames: ["dbFilepath"], + ); @override Future<List<String>> crateApiDbListDbNames({required String dir}) { @@ -4544,8 +5406,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(dir, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 121, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 124, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_String, @@ -4558,10 +5424,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiDbListDbNamesConstMeta => const TaskConstMeta( - debugName: "list_db_names", - argNames: ["dir"], - ); + TaskConstMeta get kCrateApiDbListDbNamesConstMeta => + const TaskConstMeta(debugName: "list_db_names", argNames: ["dir"]); @override Future<List<Folder>> crateApiAccountListFolders({required Coin c}) { @@ -4570,8 +5434,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 122, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 125, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_folder, @@ -4584,10 +5452,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListFoldersConstMeta => const TaskConstMeta( - debugName: "list_folders", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiAccountListFoldersConstMeta => + const TaskConstMeta(debugName: "list_folders", argNames: ["c"]); @override Future<List<Memo>> crateApiAccountListMemos({required Coin c}) { @@ -4596,8 +5462,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 123, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 126, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo, @@ -4610,10 +5480,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListMemosConstMeta => const TaskConstMeta( - debugName: "list_memos", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiAccountListMemosConstMeta => + const TaskConstMeta(debugName: "list_memos", argNames: ["c"]); @override Future<List<TxNote>> crateApiAccountListNotes({required Coin c}) { @@ -4622,8 +5490,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 124, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 127, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx_note, @@ -4636,10 +5508,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountListNotesConstMeta => const TaskConstMeta( - debugName: "list_notes", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiAccountListNotesConstMeta => + const TaskConstMeta(debugName: "list_notes", argNames: ["c"]); + + @override + Future<List<String>> crateApiAccountListOwnedAddresses({required Coin c}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 128, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiAccountListOwnedAddressesConstMeta, + argValues: [c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiAccountListOwnedAddressesConstMeta => + const TaskConstMeta(debugName: "list_owned_addresses", argNames: ["c"]); @override Future<List<PluginInfo>> crateApiPluginListPlugins({required Coin c}) { @@ -4648,8 +5546,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 125, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 129, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_plugin_info, @@ -4662,10 +5564,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginListPluginsConstMeta => const TaskConstMeta( - debugName: "list_plugins", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiPluginListPluginsConstMeta => + const TaskConstMeta(debugName: "list_plugins", argNames: ["c"]); @override Future<List<Tx>> crateApiAccountListTxHistory({required Coin c}) { @@ -4674,8 +5574,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 126, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 130, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tx, @@ -4689,10 +5593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountListTxHistoryConstMeta => - const TaskConstMeta( - debugName: "list_tx_history", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "list_tx_history", argNames: ["c"]); @override Future<List<ZsaHolding>> crateApiZsaListZsaHoldings({required Coin c}) { @@ -4701,8 +5602,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 127, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 131, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_zsa_holding, @@ -4715,14 +5620,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiZsaListZsaHoldingsConstMeta => const TaskConstMeta( - debugName: "list_zsa_holdings", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiZsaListZsaHoldingsConstMeta => + const TaskConstMeta(debugName: "list_zsa_holdings", argNames: ["c"]); @override - Future<void> crateApiAccountLockNote( - {required int id, required bool locked, required Coin c}) { + Future<void> crateApiAccountLockNote({ + required int id, + required bool locked, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4730,8 +5636,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_bool(locked, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 128, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 132, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4745,13 +5655,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountLockNoteConstMeta => const TaskConstMeta( - debugName: "lock_note", - argNames: ["id", "locked", "c"], - ); + debugName: "lock_note", + argNames: ["id", "locked", "c"], + ); @override - Future<void> crateApiAccountLockRecentNotes( - {required int height, required int threshold, required Coin c}) { + Future<void> crateApiAccountLockRecentNotes({ + required int height, + required int threshold, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4759,8 +5672,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(threshold, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 129, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 133, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -4786,8 +5703,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 130, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 134, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -4801,22 +5722,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountMaxSpendableConstMeta => - const TaskConstMeta( - debugName: "max_spendable", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "max_spendable", argNames: ["c"]); @override - Future<int> crateApiAccountNewAccount( - {required NewAccount na, required Coin c}) { + Future<int> crateApiAccountNewAccount({ + required NewAccount na, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_new_account(na, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 131, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 135, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -4829,10 +5753,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountNewAccountConstMeta => const TaskConstMeta( - debugName: "new_account", - argNames: ["na", "c"], - ); + TaskConstMeta get kCrateApiAccountNewAccountConstMeta => + const TaskConstMeta(debugName: "new_account", argNames: ["na", "c"]); @override Future<Uint8List> crateApiPayPackTransaction({required PcztPackage pczt}) { @@ -4841,8 +5763,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 132, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 136, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_prim_u_8_strict, @@ -4855,22 +5781,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayPackTransactionConstMeta => const TaskConstMeta( - debugName: "pack_transaction", - argNames: ["pczt"], - ); + TaskConstMeta get kCrateApiPayPackTransactionConstMeta => + const TaskConstMeta(debugName: "pack_transaction", argNames: ["pczt"]); @override - Future<List<MemoSection>> crateApiPluginParseMemoWithPlugins( - {required List<int> memoBytes, required Coin c}) { + Future<List<MemoSection>> crateApiPluginParseMemoWithPlugins({ + required List<int> memoBytes, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(memoBytes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 133, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 137, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_memo_section, @@ -4896,30 +5826,191 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(uri, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 134)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 138, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_list_recipient, decodeErrorData: null, ), - constMeta: kCrateApiPayParsePaymentUriConstMeta, - argValues: [uri], + constMeta: kCrateApiPayParsePaymentUriConstMeta, + argValues: [uri], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayParsePaymentUriConstMeta => + const TaskConstMeta(debugName: "parse_payment_uri", argNames: ["uri"]); + + @override + Future<Uint8List> crateApiPayPcztApplyBatchSignatures({ + required List<int> original, + required List<int> response, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(original, serializer); + sse_encode_list_prim_u_8_loose(response, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 139, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztApplyBatchSignaturesConstMeta, + argValues: [original, response], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztApplyBatchSignaturesConstMeta => + const TaskConstMeta( + debugName: "pczt_apply_batch_signatures", + argNames: ["original", "response"], + ); + + @override + Future<Uint8List> crateApiPayPcztApplyKeystoneSignatures({ + required List<int> original, + required List<int> signed, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(original, serializer); + sse_encode_list_prim_u_8_loose(signed, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 140, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztApplyKeystoneSignaturesConstMeta, + argValues: [original, signed], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztApplyKeystoneSignaturesConstMeta => + const TaskConstMeta( + debugName: "pczt_apply_keystone_signatures", + argNames: ["original", "signed"], + ); + + @override + Future<Uint8List> crateApiPayPcztFromKeystone({required List<int> pczt}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(pczt, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 141, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztFromKeystoneConstMeta, + argValues: [pczt], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztFromKeystoneConstMeta => + const TaskConstMeta(debugName: "pczt_from_keystone", argNames: ["pczt"]); + + @override + Future<Uint8List> crateApiPayPcztToBatchRequest({ + required List<Uint8List> pczts, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_list_prim_u_8_strict(pczts, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 142, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztToBatchRequestConstMeta, + argValues: [pczts], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztToBatchRequestConstMeta => + const TaskConstMeta( + debugName: "pczt_to_batch_request", + argNames: ["pczts"], + ); + + @override + Future<Uint8List> crateApiPayPcztToKeystone({required List<int> pczt}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(pczt, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 143, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztToKeystoneConstMeta, + argValues: [pczt], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiPayParsePaymentUriConstMeta => const TaskConstMeta( - debugName: "parse_payment_uri", - argNames: ["uri"], - ); + TaskConstMeta get kCrateApiPayPcztToKeystoneConstMeta => + const TaskConstMeta(debugName: "pczt_to_keystone", argNames: ["pczt"]); @override - Future<PcztPackage> crateApiPayPrepare( - {required List<Recipient> recipients, - required PaymentOptions options, - required Coin c}) { + Future<PcztPackage> crateApiPayPrepare({ + required List<Recipient> recipients, + required PaymentOptions options, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4927,8 +6018,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_box_autoadd_payment_options(options, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 135, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 144, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4942,15 +6037,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiPayPrepareConstMeta => const TaskConstMeta( - debugName: "prepare", - argNames: ["recipients", "options", "c"], - ); + debugName: "prepare", + argNames: ["recipients", "options", "c"], + ); @override - Future<PcztPackage> crateApiPayPrepareMigration( - {required List<Recipient> recipients, - required int srcPools, - required Coin c}) { + Future<PcztPackage> crateApiPayPrepareMigration({ + required List<Recipient> recipients, + required int srcPools, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -4958,8 +6054,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_recipient(recipients, serializer); sse_encode_u_8(srcPools, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 136, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 145, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -4986,8 +6086,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 137, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 146, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5000,14 +6104,50 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountPrintKeysConstMeta => const TaskConstMeta( - debugName: "print_keys", - argNames: ["id", "c"], + TaskConstMeta get kCrateApiAccountPrintKeysConstMeta => + const TaskConstMeta(debugName: "print_keys", argNames: ["id", "c"]); + + @override + Future<PcztPackage> crateApiPayProveAndFinalize({ + required PcztPackage pczt, + required Coin c, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_box_autoadd_pczt_package(pczt, serializer); + sse_encode_box_autoadd_coin(c, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 147, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_pczt_package, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayProveAndFinalizeConstMeta, + argValues: [pczt, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayProveAndFinalizeConstMeta => + const TaskConstMeta( + debugName: "prove_and_finalize", + argNames: ["pczt", "c"], ); @override - Future<void> crateApiDbPutProp( - {required String key, required String value, required Coin c}) { + Future<void> crateApiDbPutProp({ + required String key, + required String value, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5015,8 +6155,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_String(value, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 138, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 148, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5030,9 +6174,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiDbPutPropConstMeta => const TaskConstMeta( - debugName: "put_prop", - argNames: ["key", "value", "c"], - ); + debugName: "put_prop", + argNames: ["key", "value", "c"], + ); @override Future<List<LWDInfo>> crateApiNetworkQueryLwdList({required int coin}) { @@ -5041,8 +6185,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_8(coin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 139, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 149, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_lwd_info, @@ -5056,10 +6204,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiNetworkQueryLwdListConstMeta => - const TaskConstMeta( - debugName: "query_lwd_list", - argNames: ["coin"], - ); + const TaskConstMeta(debugName: "query_lwd_list", argNames: ["coin"]); @override Future<Receivers> crateApiAccountReceiversDefault() { @@ -5067,8 +6212,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 140, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 150, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -5082,22 +6231,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountReceiversDefaultConstMeta => - const TaskConstMeta( - debugName: "receivers_default", - argNames: [], - ); + const TaskConstMeta(debugName: "receivers_default", argNames: []); @override - Receivers crateApiAccountReceiversFromUa( - {required String ua, required Coin c}) { + Receivers crateApiAccountReceiversFromUa({ + required String ua, + required Coin c, + }) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(ua, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 141)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 151, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_receivers, @@ -5117,16 +6268,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountRemoveAccount( - {required int accountId, required Coin c}) { + Future<void> crateApiAccountRemoveAccount({ + required int accountId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(accountId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 142, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 152, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5146,16 +6303,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiPluginRemovePlugin( - {required String id, required Coin c}) { + Future<void> crateApiPluginRemovePlugin({ + required String id, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 143, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 153, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5168,22 +6331,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPluginRemovePluginConstMeta => const TaskConstMeta( - debugName: "remove_plugin", - argNames: ["id", "c"], - ); + TaskConstMeta get kCrateApiPluginRemovePluginConstMeta => + const TaskConstMeta(debugName: "remove_plugin", argNames: ["id", "c"]); @override - Future<void> crateApiAccountRenameCategory( - {required Category category, required Coin c}) { + Future<void> crateApiAccountRenameCategory({ + required Category category, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_category(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 144, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 154, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5203,8 +6370,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountRenameFolder( - {required int id, required String name, required Coin c}) { + Future<void> crateApiAccountRenameFolder({ + required int id, + required String name, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5212,8 +6382,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 145, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 155, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5233,8 +6407,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiAccountReorderAccount( - {required int oldPosition, required int newPosition, required Coin c}) { + Future<void> crateApiAccountReorderAccount({ + required int oldPosition, + required int newPosition, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5242,8 +6419,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(oldPosition, serializer); sse_encode_u_32(newPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 146, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 156, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5269,8 +6450,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 147, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 157, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5283,10 +6468,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiFrostResetSignConstMeta => const TaskConstMeta( - debugName: "reset_sign", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiFrostResetSignConstMeta => + const TaskConstMeta(debugName: "reset_sign", argNames: ["c"]); @override Future<void> crateApiAccountResetSync({required int id, required Coin c}) { @@ -5296,8 +6479,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(id, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 148, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 158, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5310,22 +6497,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiAccountResetSyncConstMeta => const TaskConstMeta( - debugName: "reset_sync", - argNames: ["id", "c"], - ); + TaskConstMeta get kCrateApiAccountResetSyncConstMeta => + const TaskConstMeta(debugName: "reset_sync", argNames: ["id", "c"]); @override - Future<OpenAliasResolution> crateApiOpenaliasResolveOpenalias( - {required String alias, required Coin c}) { + Future<OpenAliasResolution> crateApiOpenaliasResolveOpenalias({ + required String alias, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 149, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 159, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -5345,15 +6536,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<OpenAliasResolution> crateApiOpenaliasResolveOpenaliasAll( - {required String alias}) { + Future<OpenAliasResolution> crateApiOpenaliasResolveOpenaliasAll({ + required String alias, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 150, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 160, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_open_alias_resolution, @@ -5373,15 +6569,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<RawOpenAliasResolution> crateApiOpenaliasResolveOpenaliasRaw( - {required String alias}) { + Future<RawOpenAliasResolution> crateApiOpenaliasResolveOpenaliasRaw({ + required String alias, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 151, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 161, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_raw_open_alias_resolution, @@ -5401,8 +6602,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiSyncRewindSync( - {required int height, required int account, required Coin c}) { + Future<void> crateApiSyncRewindSync({ + required int height, + required int account, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5410,8 +6614,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_u_32(account, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 152, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 162, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5425,13 +6633,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSyncRewindSyncConstMeta => const TaskConstMeta( - debugName: "rewind_sync", - argNames: ["height", "account", "c"], - ); + debugName: "rewind_sync", + argNames: ["height", "account", "c"], + ); @override - Future<String> crateApiPaySend( - {required int height, required List<int> data, required Coin c}) { + Future<String> crateApiPaySend({ + required int height, + required List<int> data, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5439,8 +6650,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(height, serializer); sse_encode_list_prim_u_8_loose(data, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 153, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 163, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5453,14 +6668,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPaySendConstMeta => const TaskConstMeta( - debugName: "send", - argNames: ["height", "data", "c"], - ); + TaskConstMeta get kCrateApiPaySendConstMeta => + const TaskConstMeta(debugName: "send", argNames: ["height", "data", "c"]); @override - Future<void> crateApiZsaSetAssetName( - {required PlatformInt64 idAsset, required String name, required Coin c}) { + Future<void> crateApiZsaSetAssetName({ + required PlatformInt64 idAsset, + required String name, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5468,8 +6684,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_64(idAsset, serializer); sse_encode_String(name, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 154, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 164, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5483,13 +6703,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiZsaSetAssetNameConstMeta => const TaskConstMeta( - debugName: "set_asset_name", - argNames: ["idAsset", "name", "c"], - ); + debugName: "set_asset_name", + argNames: ["idAsset", "name", "c"], + ); @override - Future<void> crateApiFrostSetDkgAddress( - {required int id, required String address, required Coin c}) { + Future<void> crateApiFrostSetDkgAddress({ + required int id, + required String address, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5497,8 +6720,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(id, serializer); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 155, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 165, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5512,18 +6739,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostSetDkgAddressConstMeta => const TaskConstMeta( - debugName: "set_dkg_address", - argNames: ["id", "address", "c"], - ); + debugName: "set_dkg_address", + argNames: ["id", "address", "c"], + ); @override - Future<void> crateApiFrostSetDkgParams( - {required String name, - required int id, - required int n, - required int t, - required int fundingAccount, - required Coin c}) { + Future<void> crateApiFrostSetDkgParams({ + required String name, + required int id, + required int n, + required int t, + required int fundingAccount, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5534,8 +6762,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_8(t, serializer); sse_encode_u_32(fundingAccount, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 156, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 166, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5549,9 +6781,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiFrostSetDkgParamsConstMeta => const TaskConstMeta( - debugName: "set_dkg_params", - argNames: ["name", "id", "n", "t", "fundingAccount", "c"], - ); + debugName: "set_dkg_params", + argNames: ["name", "id", "n", "t", "fundingAccount", "c"], + ); @override void crateApiInitSetExpertMode({required bool enabled}) { @@ -5560,8 +6792,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(enabled, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 157)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 167, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5574,10 +6809,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiInitSetExpertModeConstMeta => const TaskConstMeta( - debugName: "set_expert_mode", - argNames: ["enabled"], - ); + TaskConstMeta get kCrateApiInitSetExpertModeConstMeta => + const TaskConstMeta(debugName: "set_expert_mode", argNames: ["enabled"]); @override Stream<LogMessage> crateApiInitSetLogStream() { @@ -5587,8 +6820,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_log_message_Sse(s, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 158)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 168, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5602,14 +6838,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return s.stream; } - TaskConstMeta get kCrateApiInitSetLogStreamConstMeta => const TaskConstMeta( - debugName: "set_log_stream", - argNames: ["s"], - ); + TaskConstMeta get kCrateApiInitSetLogStreamConstMeta => + const TaskConstMeta(debugName: "set_log_stream", argNames: ["s"]); @override - Future<void> crateApiPluginSetPluginEnabled( - {required String id, required bool enabled, required Coin c}) { + Future<void> crateApiPluginSetPluginEnabled({ + required String id, + required bool enabled, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5617,8 +6854,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(id, serializer); sse_encode_bool(enabled, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 159, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 169, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5638,8 +6879,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiTransactionSetTxCategory( - {required int id, int? category, required Coin c}) { + Future<void> crateApiTransactionSetTxCategory({ + required int id, + int? category, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5647,8 +6891,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 160, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 170, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5668,8 +6916,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiTransactionSetTxPrice( - {required int id, double? price, required Coin c}) { + Future<void> crateApiTransactionSetTxPrice({ + required int id, + double? price, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5677,8 +6928,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(id, serializer); sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 161, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 171, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5698,8 +6953,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiTransactionSetUserMemo( - {required int idTx, String? memo, required Coin c}) { + Future<void> crateApiTransactionSetUserMemo({ + required int idTx, + String? memo, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5707,8 +6965,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(idTx, serializer); sse_encode_opt_String(memo, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 162, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 172, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5734,8 +6996,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 163, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 173, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5755,15 +7021,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiAccountShowLedgerTransparentAddress( - {required Coin c}) { + Future<String> crateApiAccountShowLedgerTransparentAddress({ + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 164, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 174, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -5783,8 +7054,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Stream<SigningEvent> crateApiAccountSignLedgerTransaction( - {required PcztPackage package, required Coin c}) { + Stream<SigningEvent> crateApiAccountSignLedgerTransaction({ + required PcztPackage package, + required Coin c, + }) { final sink = RustStreamSink<SigningEvent>(); unawaited( handler.executeNormal( @@ -5794,8 +7067,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_StreamSink_signing_event_Sse(sink, serializer); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 165, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 175, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5817,16 +7094,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<PcztPackage> crateApiPaySignTransaction( - {required PcztPackage pczt, required Coin c}) { + Future<PcztPackage> crateApiPaySignTransaction({ + required PcztPackage pczt, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(pczt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 166, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 176, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -5840,9 +7123,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiPaySignTransactionConstMeta => const TaskConstMeta( - debugName: "sign_transaction", - argNames: ["pczt", "c"], - ); + debugName: "sign_transaction", + argNames: ["pczt", "c"], + ); @override Future<MigrationEvent> crateApiMigrateStepMigration({required Coin c}) { @@ -5851,8 +7134,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 167, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 177, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_migration_event, @@ -5866,18 +7153,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiMigrateStepMigrationConstMeta => - const TaskConstMeta( - debugName: "step_migration", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "step_migration", argNames: ["c"]); @override - Future<void> crateApiPayStorePendingTx( - {required int height, - required List<int> txid, - double? price, - int? category, - required Coin c}) { + Future<void> crateApiPayStorePendingTx({ + required int height, + required List<int> txid, + double? price, + int? category, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5887,8 +7172,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_f_64(price, serializer); sse_encode_opt_box_autoadd_u_32(category, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 168, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 178, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -5902,19 +7191,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiPayStorePendingTxConstMeta => const TaskConstMeta( - debugName: "store_pending_tx", - argNames: ["height", "txid", "price", "category", "c"], - ); + debugName: "store_pending_tx", + argNames: ["height", "txid", "price", "category", "c"], + ); @override - Stream<SyncProgress> crateApiSyncSynchronize( - {required List<int> accounts, - required int currentHeight, - required int actionsPerSync, - required int transparentLimit, - required int checkpointAge, - required bool fast, - required Coin c}) { + Stream<SyncProgress> crateApiSyncSynchronize({ + required List<int> accounts, + required int currentHeight, + required int actionsPerSync, + required int transparentLimit, + required int checkpointAge, + required bool fast, + required Coin c, + }) { final progress = RustStreamSink<SyncProgress>(); unawaited( handler.executeNormal( @@ -5929,8 +7219,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(checkpointAge, serializer); sse_encode_bool(fast, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 169, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 179, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -5945,7 +7239,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { transparentLimit, checkpointAge, fast, - c + c, ], apiImpl: this, ), @@ -5955,18 +7249,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiSyncSynchronizeConstMeta => const TaskConstMeta( - debugName: "synchronize", - argNames: [ - "progress", - "accounts", - "currentHeight", - "actionsPerSync", - "transparentLimit", - "checkpointAge", - "fast", - "c" - ], - ); + debugName: "synchronize", + argNames: [ + "progress", + "accounts", + "currentHeight", + "actionsPerSync", + "transparentLimit", + "checkpointAge", + "fast", + "c", + ], + ); @override TxPlan crateApiPayToPlan({required PcztPackage package, required Coin c}) { @@ -5976,8 +7270,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_pczt_package(package, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 170)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 180, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_tx_plan, @@ -5990,10 +7287,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiPayToPlanConstMeta => const TaskConstMeta( - debugName: "to_plan", - argNames: ["package", "c"], - ); + TaskConstMeta get kCrateApiPayToPlanConstMeta => + const TaskConstMeta(debugName: "to_plan", argNames: ["package", "c"]); @override Future<void> crateApiAccountToggleAllNotes({required Coin c}) { @@ -6002,8 +7297,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 171, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 181, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6017,22 +7316,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountToggleAllNotesConstMeta => - const TaskConstMeta( - debugName: "toggle_all_notes", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "toggle_all_notes", argNames: ["c"]); @override - void crateApiOpenaliasTryValidateZcashAddress( - {required String address, required Coin c}) { + void crateApiOpenaliasTryValidateZcashAddress({ + required String address, + required Coin c, + }) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 172)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 182, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6057,8 +7358,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 173, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 183, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_account, @@ -6072,10 +7377,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountTxAccountDefaultConstMeta => - const TaskConstMeta( - debugName: "tx_account_default", - argNames: [], - ); + const TaskConstMeta(debugName: "tx_account_default", argNames: []); @override Future<TxMemo> crateApiAccountTxMemoDefault() { @@ -6083,8 +7385,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 174, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 184, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_memo, @@ -6098,10 +7404,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountTxMemoDefaultConstMeta => - const TaskConstMeta( - debugName: "tx_memo_default", - argNames: [], - ); + const TaskConstMeta(debugName: "tx_memo_default", argNames: []); @override Future<TxNote> crateApiAccountTxNoteDefault() { @@ -6109,8 +7412,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 175, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 185, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_note, @@ -6124,10 +7431,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountTxNoteDefaultConstMeta => - const TaskConstMeta( - debugName: "tx_note_default", - argNames: [], - ); + const TaskConstMeta(debugName: "tx_note_default", argNames: []); @override Future<TxOutput> crateApiAccountTxOutputDefault() { @@ -6135,8 +7439,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 176, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 186, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_output, @@ -6150,10 +7458,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountTxOutputDefaultConstMeta => - const TaskConstMeta( - debugName: "tx_output_default", - argNames: [], - ); + const TaskConstMeta(debugName: "tx_output_default", argNames: []); @override Future<TxSpend> crateApiAccountTxSpendDefault() { @@ -6161,8 +7466,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 177, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 187, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_tx_spend, @@ -6176,14 +7485,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountTxSpendDefaultConstMeta => - const TaskConstMeta( - debugName: "tx_spend_default", - argNames: [], - ); + const TaskConstMeta(debugName: "tx_spend_default", argNames: []); @override - String crateApiAccountUaFromUfvk( - {required String ufvk, int? di, required Coin c}) { + String crateApiAccountUaFromUfvk({ + required String ufvk, + int? di, + required Coin c, + }) { return handler.executeSync( SyncTask( callFfi: () { @@ -6191,8 +7500,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ufvk, serializer); sse_encode_opt_box_autoadd_u_32(di, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 178)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 188, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -6206,8 +7518,42 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountUaFromUfvkConstMeta => const TaskConstMeta( - debugName: "ua_from_ufvk", - argNames: ["ufvk", "di", "c"], + debugName: "ua_from_ufvk", + argNames: ["ufvk", "di", "c"], + ); + + @override + String crateApiLedgerUfvkDefaultAddress({ + required String ufvk, + required Coin c, + }) { + return handler.executeSync( + SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(ufvk, serializer); + sse_encode_box_autoadd_coin(c, serializer); + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 189, + )!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLedgerUfvkDefaultAddressConstMeta, + argValues: [ufvk, c], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiLedgerUfvkDefaultAddressConstMeta => + const TaskConstMeta( + debugName: "ufvk_default_address", + argNames: ["ufvk", "c"], ); @override @@ -6217,8 +7563,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 179, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 190, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6232,10 +7582,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiAccountUnlockAllNotesConstMeta => - const TaskConstMeta( - debugName: "unlock_all_notes", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "unlock_all_notes", argNames: ["c"]); @override Future<PcztPackage> crateApiPayUnpackTransaction({required List<int> bytes}) { @@ -6244,8 +7591,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 180, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 191, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_pczt_package, @@ -6259,22 +7610,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiPayUnpackTransactionConstMeta => - const TaskConstMeta( - debugName: "unpack_transaction", - argNames: ["bytes"], - ); + const TaskConstMeta(debugName: "unpack_transaction", argNames: ["bytes"]); @override - Future<void> crateApiAccountUpdateAccount( - {required AccountUpdate update, required Coin c}) { + Future<void> crateApiAccountUpdateAccount({ + required AccountUpdate update, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_account_update(update, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 181, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 192, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6294,12 +7648,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiContactsUpdateContact( - {required int id, - String? name, - List<String>? addresses, - String? notes, - required Coin c}) { + Future<void> crateApiContactsUpdateContact({ + required int id, + String? name, + List<String>? addresses, + String? notes, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6309,8 +7664,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_list_String(addresses, serializer); sse_encode_opt_String(notes, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 182, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 193, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6330,10 +7689,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiTransactionUpdateHistoricalPrices( - {required String currency, - required double exchangeRate, - required Coin c}) { + Future<void> crateApiTransactionUpdateHistoricalPrices({ + required String currency, + required double exchangeRate, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6341,8 +7701,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(currency, serializer); sse_encode_f_64(exchangeRate, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 183, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 194, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6368,8 +7732,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(alias, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 184)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 195, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -6389,16 +7756,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - bool crateApiOpenaliasValidateZcashAddress( - {required String address, required Coin c}) { + bool crateApiOpenaliasValidateZcashAddress({ + required String address, + required Coin c, + }) { return handler.executeSync( SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(address, serializer); sse_encode_box_autoadd_coin(c, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 185)!; + return pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 196, + )!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -6418,16 +7790,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainListRounds( - {required String baseUrl, required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainListRounds({ + required String baseUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(baseUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 186, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 197, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6447,10 +7825,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainResubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainResubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6458,8 +7837,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(serverUrl, serializer); sse_encode_String(payloadJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 187, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 198, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6479,8 +7862,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainRoundStatus( - {required String baseUrl, required String roundId, required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainRoundStatus({ + required String baseUrl, + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6488,8 +7874,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(baseUrl, serializer); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 188, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 199, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6509,8 +7899,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainRoundTally( - {required String baseUrl, required String roundId, required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainRoundTally({ + required String baseUrl, + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6518,8 +7911,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(baseUrl, serializer); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 189, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 200, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6539,11 +7936,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainShareStatus( - {required String serverUrl, - required String roundId, - required String shareId, - required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainShareStatus({ + required String serverUrl, + required String roundId, + required String shareId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6552,8 +7950,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_String(shareId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 190, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 201, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6573,10 +7975,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainSubmitDelegation( - {required String baseUrl, - required String submissionJson, - required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainSubmitDelegation({ + required String baseUrl, + required String submissionJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6584,8 +7987,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(baseUrl, serializer); sse_encode_String(submissionJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 191, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 202, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6605,10 +8012,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainSubmitShare( - {required String serverUrl, - required String payloadJson, - required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainSubmitShare({ + required String serverUrl, + required String payloadJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6616,8 +8024,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(serverUrl, serializer); sse_encode_String(payloadJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 192, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 203, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6637,10 +8049,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainSubmitVote( - {required String baseUrl, - required String submissionJson, - required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainSubmitVote({ + required String baseUrl, + required String submissionJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6648,8 +8061,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(baseUrl, serializer); sse_encode_String(submissionJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 193, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 204, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6669,8 +8086,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingChainResponse> crateApiVotingVotechainTxConfirmation( - {required String baseUrl, required String txHash, required Coin c}) { + Future<VotingChainResponse> crateApiVotingVotechainTxConfirmation({ + required String baseUrl, + required String txHash, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6678,8 +8098,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(baseUrl, serializer); sse_encode_String(txHash, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 194, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 205, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_chain_response, @@ -6699,16 +8123,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<VotingBallotIntent>> crateApiVotingVotingBallotIntents( - {required String roundId, required Coin c}) { + Future<List<VotingBallotIntent>> crateApiVotingVotingBallotIntents({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 195, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 206, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_ballot_intent, @@ -6728,12 +8158,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingVoteCommitments> crateApiVotingVotingCommit( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}) { + Future<VotingVoteCommitments> crateApiVotingVotingCommit({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6743,8 +8174,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(draftsJson, serializer); sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 196, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 207, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_commitments, @@ -6758,17 +8193,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiVotingVotingCommitConstMeta => const TaskConstMeta( - debugName: "voting_commit", - argNames: ["roundId", "bundleIndex", "draftsJson", "voteNodeUrl", "c"], - ); + debugName: "voting_commit", + argNames: ["roundId", "bundleIndex", "draftsJson", "voteNodeUrl", "c"], + ); @override - Stream<VotingVoteCommitStage> crateApiVotingVotingCommitWithProgress( - {required String roundId, - required int bundleIndex, - required String draftsJson, - required String voteNodeUrl, - required Coin c}) { + Stream<VotingVoteCommitStage> crateApiVotingVotingCommitWithProgress({ + required String roundId, + required int bundleIndex, + required String draftsJson, + required String voteNodeUrl, + required Coin c, + }) { final sink = RustStreamSink<VotingVoteCommitStage>(); unawaited( handler.executeNormal( @@ -6776,14 +8212,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_StreamSink_voting_vote_commit_stage_Sse( - sink, serializer); + sink, + serializer, + ); sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_String(draftsJson, serializer); sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 197, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 208, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_commitments, @@ -6807,21 +8249,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "bundleIndex", "draftsJson", "voteNodeUrl", - "c" + "c", ], ); @override - Future<VotingConfig?> crateApiVotingVotingConfigCached( - {required String source, required Coin c}) { + Future<VotingConfig?> crateApiVotingVotingConfigCached({ + required String source, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(source, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 198, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 209, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_voting_config, @@ -6847,8 +8295,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 199, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 210, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -6868,16 +8320,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingConfig> crateApiVotingVotingConfigResolve( - {required String source, required Coin c}) { + Future<VotingConfig> crateApiVotingVotingConfigResolve({ + required String source, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(source, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 200, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 211, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_config, @@ -6897,13 +8355,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingVoteConfirmation> crateApiVotingVotingConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required String eventsJson, - required Coin c}) { + Future<VotingVoteConfirmation> crateApiVotingVotingConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required String eventsJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6914,8 +8373,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(txHash, serializer); sse_encode_String(eventsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 201, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 212, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_confirmation, @@ -6937,13 +8400,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "proposalId", "txHash", "eventsJson", - "c" + "c", ], ); @override - Future<String?> crateApiVotingVotingDelegationVanCommitmentHex( - {required String roundId, required int bundleIndex, required Coin c}) { + Future<String?> crateApiVotingVotingDelegationVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -6951,8 +8417,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 202, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 213, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -6972,16 +8442,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String?> crateApiVotingVotingDraftsLoad( - {required String roundId, required Coin c}) { + Future<String?> crateApiVotingVotingDraftsLoad({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 203, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 214, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -7001,8 +8477,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVotingVotingDraftsSave( - {required String roundId, required String draftsJson, required Coin c}) { + Future<void> crateApiVotingVotingDraftsSave({ + required String roundId, + required String draftsJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7010,8 +8489,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_String(draftsJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 204, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 215, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7031,16 +8514,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<BigInt> crateApiVotingVotingEligibleWeight( - {required int snapshotHeight, required Coin c}) { + Future<BigInt> crateApiVotingVotingEligibleWeight({ + required int snapshotHeight, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_u_32(snapshotHeight, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 205, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 216, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_64, @@ -7066,8 +8555,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 206, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 217, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7081,10 +8574,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiVotingVotingHotkeyCreateConstMeta => - const TaskConstMeta( - debugName: "voting_hotkey_create", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "voting_hotkey_create", argNames: ["c"]); @override Future<String> crateApiVotingVotingHotkeyGet({required Coin c}) { @@ -7093,8 +8583,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 207, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 218, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7108,18 +8602,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiVotingVotingHotkeyGetConstMeta => - const TaskConstMeta( - debugName: "voting_hotkey_get", - argNames: ["c"], - ); + const TaskConstMeta(debugName: "voting_hotkey_get", argNames: ["c"]); @override - Future<void> crateApiVotingVotingMarkVoteSubmitted( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String txHash, - required Coin c}) { + Future<void> crateApiVotingVotingMarkVoteSubmitted({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String txHash, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7129,8 +8621,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_String(txHash, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 208, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 219, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7150,11 +8646,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingVotePayloads> crateApiVotingVotingPayloads( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) { + Future<VotingVotePayloads> crateApiVotingVotingPayloads({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7163,8 +8660,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 209, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 220, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_vote_payloads, @@ -7184,10 +8685,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingRoundPlan> crateApiVotingVotingPlan( - {required String roundId, - required List<int> proposalIds, - required Coin c}) { + Future<VotingRoundPlan> crateApiVotingVotingPlan({ + required String roundId, + required List<int> proposalIds, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7195,8 +8697,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_list_prim_u_32_loose(proposalIds, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 210, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 221, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_plan, @@ -7210,19 +8716,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta get kCrateApiVotingVotingPlanConstMeta => const TaskConstMeta( - debugName: "voting_plan", - argNames: ["roundId", "proposalIds", "c"], - ); + debugName: "voting_plan", + argNames: ["roundId", "proposalIds", "c"], + ); @override - Future<void> crateApiVotingVotingRecordExecution( - {required String roundId, - required int bundleIndex, - required int proposalId, - required String voteTxHash, - required BigInt vcTreePosition, - required String shareDeliveriesJson, - required Coin c}) { + Future<void> crateApiVotingVotingRecordExecution({ + required String roundId, + required int bundleIndex, + required int proposalId, + required String voteTxHash, + required BigInt vcTreePosition, + required String shareDeliveriesJson, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7234,8 +8741,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(vcTreePosition, serializer); sse_encode_String(shareDeliveriesJson, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 211, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 222, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7249,7 +8760,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { voteTxHash, vcTreePosition, shareDeliveriesJson, - c + c, ], apiImpl: this, ), @@ -7266,16 +8777,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "voteTxHash", "vcTreePosition", "shareDeliveriesJson", - "c" + "c", ], ); @override - Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree( - {required String roundId, - required int bundleIndex, - required int vanLeafPosition, - required Coin c}) { + Future<void> crateApiVotingVotingRecoverConfirmDelegationFromTree({ + required String roundId, + required int bundleIndex, + required int vanLeafPosition, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7284,8 +8796,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(vanLeafPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 212, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 223, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7300,21 +8816,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } TaskConstMeta - get kCrateApiVotingVotingRecoverConfirmDelegationFromTreeConstMeta => - const TaskConstMeta( - debugName: "voting_recover_confirm_delegation_from_tree", - argNames: ["roundId", "bundleIndex", "vanLeafPosition", "c"], - ); + get kCrateApiVotingVotingRecoverConfirmDelegationFromTreeConstMeta => + const TaskConstMeta( + debugName: "voting_recover_confirm_delegation_from_tree", + argNames: ["roundId", "bundleIndex", "vanLeafPosition", "c"], + ); @override Future<VotingTreeVoteConfirmation> - crateApiVotingVotingRecoverConfirmVoteFromTree( - {required String roundId, - required int bundleIndex, - required int proposalId, - required BigInt vcTreePosition, - int? vanLeafPosition, - required Coin c}) { + crateApiVotingVotingRecoverConfirmVoteFromTree({ + required String roundId, + required int bundleIndex, + required int proposalId, + required BigInt vcTreePosition, + int? vanLeafPosition, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7325,8 +8842,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(vcTreePosition, serializer); sse_encode_opt_box_autoadd_u_32(vanLeafPosition, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 213, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 224, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_tree_vote_confirmation, @@ -7339,7 +8860,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { proposalId, vcTreePosition, vanLeafPosition, - c + c, ], apiImpl: this, ), @@ -7355,21 +8876,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "proposalId", "vcTreePosition", "vanLeafPosition", - "c" + "c", ], ); @override - Future<VotingRoundRecovery> crateApiVotingVotingRecovery( - {required String roundId, required Coin c}) { + Future<VotingRoundRecovery> crateApiVotingVotingRecovery({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 214, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 225, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_round_recovery, @@ -7389,16 +8916,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVotingVotingRecoveryClear( - {required String roundId, required Coin c}) { + Future<void> crateApiVotingVotingRecoveryClear({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 215, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 226, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7418,16 +8951,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVotingVotingResetSessionState( - {required String roundId, required Coin c}) { + Future<void> crateApiVotingVotingResetSessionState({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 216, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 227, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7447,13 +8986,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiVotingVotingRoundParamsJson( - {required String source, - required String roundId, - required BigInt snapshotHeight, - required List<int> ncRoot, - required List<int> nullifierImtRoot, - required Coin c}) { + Future<String> crateApiVotingVotingRoundParamsJson({ + required String source, + required String roundId, + required BigInt snapshotHeight, + required List<int> ncRoot, + required List<int> nullifierImtRoot, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7464,8 +9004,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_8_loose(ncRoot, serializer); sse_encode_list_prim_u_8_loose(nullifierImtRoot, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 217, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 228, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7478,7 +9022,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { snapshotHeight, ncRoot, nullifierImtRoot, - c + c, ], apiImpl: this, ), @@ -7494,7 +9038,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "snapshotHeight", "ncRoot", "nullifierImtRoot", - "c" + "c", ], ); @@ -7505,8 +9049,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 218, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 229, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_info, @@ -7519,22 +9067,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - TaskConstMeta get kCrateApiVotingVotingRoundsConstMeta => const TaskConstMeta( - debugName: "voting_rounds", - argNames: ["c"], - ); + TaskConstMeta get kCrateApiVotingVotingRoundsConstMeta => + const TaskConstMeta(debugName: "voting_rounds", argNames: ["c"]); @override - Future<List<VotingRoundSession>> crateApiVotingVotingSessions( - {required List<String> roundIds, required Coin c}) { + Future<List<VotingRoundSession>> crateApiVotingVotingSessions({ + required List<String> roundIds, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_list_String(roundIds, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 219, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 230, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_round_session, @@ -7554,13 +9106,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<void> crateApiVotingVotingSetBallotIntent( - {required String roundId, - required int proposalId, - required bool skipped, - required int choice, - required int numOptions, - required Coin c}) { + Future<void> crateApiVotingVotingSetBallotIntent({ + required String roundId, + required int proposalId, + required bool skipped, + required int choice, + required int numOptions, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7571,8 +9124,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(choice, serializer); sse_encode_u_32(numOptions, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 220, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 231, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7594,18 +9151,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "skipped", "choice", "numOptions", - "c" + "c", ], ); @override - Future<void> crateApiVotingVotingShareAddServers( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> newUrls, - required Coin c}) { + Future<void> crateApiVotingVotingShareAddServers({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> newUrls, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7616,8 +9174,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(shareIndex, serializer); sse_encode_list_String(newUrls, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 221, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 232, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7639,17 +9201,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "proposalId", "shareIndex", "newUrls", - "c" + "c", ], ); @override - Future<void> crateApiVotingVotingShareConfirm( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required Coin c}) { + Future<void> crateApiVotingVotingShareConfirm({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7659,8 +9222,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(proposalId, serializer); sse_encode_u_32(shareIndex, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 222, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 233, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7680,16 +9247,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads( - {required String roundId, required Coin c}) { + Future<List<VotingShareSubmissionPayload>> crateApiVotingVotingSharePayloads({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 223, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 234, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_submission_payload, @@ -7709,14 +9282,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingSharePlan> crateApiVotingVotingSharePlan( - {required String roundId, - required BigInt now, - required BigInt ceremonyStart, - BigInt? voteEnd, - required List<String> serverUrls, - required bool singleShare, - required Coin c}) { + Future<VotingSharePlan> crateApiVotingVotingSharePlan({ + required String roundId, + required BigInt now, + required BigInt ceremonyStart, + BigInt? voteEnd, + required List<String> serverUrls, + required bool singleShare, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7728,8 +9302,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(serverUrls, serializer); sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 224, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 235, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_share_plan, @@ -7743,7 +9321,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { voteEnd, serverUrls, singleShare, - c + c, ], apiImpl: this, ), @@ -7760,19 +9338,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "voteEnd", "serverUrls", "singleShare", - "c" + "c", ], ); @override - Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans( - {required int shareCount, - required List<String> serverUrls, - required BigInt now, - required BigInt voteEnd, - required BigInt ceremonyStart, - required bool singleShare, - required Coin c}) { + Future<List<VotingSharePlanItem>> crateApiVotingVotingSharePlans({ + required int shareCount, + required List<String> serverUrls, + required BigInt now, + required BigInt voteEnd, + required BigInt ceremonyStart, + required bool singleShare, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7784,8 +9363,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_64(ceremonyStart, serializer); sse_encode_bool(singleShare, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 225, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 236, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_plan_item, @@ -7799,7 +9382,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { voteEnd, ceremonyStart, singleShare, - c + c, ], apiImpl: this, ), @@ -7816,19 +9399,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "voteEnd", "ceremonyStart", "singleShare", - "c" + "c", ], ); @override - Future<void> crateApiVotingVotingShareRecord( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - required List<String> sentToUrls, - required BigInt submitAt, - required Coin c}) { + Future<void> crateApiVotingVotingShareRecord({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + required List<String> sentToUrls, + required BigInt submitAt, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7840,8 +9424,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_String(sentToUrls, serializer); sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 226, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 237, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -7855,7 +9443,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { shareIndex, sentToUrls, submitAt, - c + c, ], apiImpl: this, ), @@ -7872,22 +9460,28 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "shareIndex", "sentToUrls", "submitAt", - "c" + "c", ], ); @override Future<List<VotingShareDelegationRecord>> - crateApiVotingVotingShareUnconfirmed( - {required String roundId, required Coin c}) { + crateApiVotingVotingShareUnconfirmed({ + required String roundId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(roundId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 227, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 238, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_list_voting_share_delegation_record, @@ -7907,14 +9501,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiVotingVotingShareWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required int shareIndex, - BigInt? vcTreePosition, - required BigInt submitAt, - required Coin c}) { + Future<String> crateApiVotingVotingShareWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required int shareIndex, + BigInt? vcTreePosition, + required BigInt submitAt, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7926,8 +9521,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_u_64(vcTreePosition, serializer); sse_encode_u_64(submitAt, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 228, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 239, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -7941,7 +9540,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { shareIndex, vcTreePosition, submitAt, - c + c, ], apiImpl: this, ), @@ -7958,13 +9557,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { "shareIndex", "vcTreePosition", "submitAt", - "c" + "c", ], ); @override - Future<int> crateApiVotingVotingSyncTree( - {required String roundId, required String voteNodeUrl, required Coin c}) { + Future<int> crateApiVotingVotingSyncTree({ + required String roundId, + required String voteNodeUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -7972,8 +9574,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 229, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 240, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -7993,10 +9599,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<BigInt?> crateApiVotingVotingTreeFindLeaf( - {required String roundId, - required String nodeUrl, - required String targetHex}) { + Future<BigInt?> crateApiVotingVotingTreeFindLeaf({ + required String roundId, + required String nodeUrl, + required String targetHex, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -8004,8 +9611,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(roundId, serializer); sse_encode_String(nodeUrl, serializer); sse_encode_String(targetHex, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 230, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 241, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_box_autoadd_u_64, @@ -8025,11 +9636,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<VotingVanWitness> crateApiVotingVotingVanWitness( - {required String roundId, - required int bundleIndex, - required String voteNodeUrl, - required Coin c}) { + Future<VotingVanWitness> crateApiVotingVotingVanWitness({ + required String roundId, + required int bundleIndex, + required String voteNodeUrl, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -8038,8 +9650,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_String(voteNodeUrl, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 231, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 242, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_voting_van_witness, @@ -8059,11 +9675,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiVotingVotingVoteCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) { + Future<String> crateApiVotingVotingVoteCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -8072,8 +9689,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 232, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 243, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -8093,11 +9714,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiVotingVotingVoteVanCommitmentHex( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) { + Future<String> crateApiVotingVotingVoteVanCommitmentHex({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -8106,8 +9728,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 233, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 244, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -8127,11 +9753,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<String> crateApiVotingVotingVoteWireJson( - {required String roundId, - required int bundleIndex, - required int proposalId, - required Coin c}) { + Future<String> crateApiVotingVotingVoteWireJson({ + required String roundId, + required int bundleIndex, + required int proposalId, + required Coin c, + }) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -8140,8 +9767,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_u_32(bundleIndex, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_box_autoadd_coin(c, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 234, port: port_); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 245, + port: port_, + ); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -8161,8 +9792,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); Future<void> Function(int, dynamic) - encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr<void> Function(Uint8List) raw) { + encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + FutureOr<Uint8List> Function(Uint8List) raw, + ) { + return (callId, rawArg0) async { + final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); + + Box<Uint8List>? rawOutput; + Box<AnyhowException>? rawError; + try { + rawOutput = Box(await raw(arg0)); + } catch (e, s) { + rawError = Box(AnyhowException("$e\n\n$s")); + } + + final serializer = SseSerializer(generalizedFrbRustBinding); + assert((rawOutput != null) ^ (rawError != null)); + if (rawOutput != null) { + serializer.buffer.putUint8(0); + sse_encode_list_prim_u_8_strict(rawOutput.value, serializer); + } else { + serializer.buffer.putUint8(1); + sse_encode_AnyhowException(rawError!.value, serializer); + } + final output = serializer.intoRaw(); + + generalizedFrbRustBinding.dartFnDeliverOutput( + callId: callId, + ptr: output.ptr, + rustVecLen: output.rustVecLen, + dataLen: output.dataLen, + ); + }; + } + + Future<void> Function(int, dynamic) + encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr<void> Function(Uint8List) raw, + ) { return (callId, rawArg0) async { final arg0 = dco_decode_list_prim_u_8_strict(rawArg0); @@ -8195,36 +9862,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_DartVault => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + get rust_arc_increment_strong_count_DartVault => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_DartVault => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + get rust_arc_decrement_strong_count_DartVault => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_Mempool => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + get rust_arc_increment_strong_count_Mempool => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_Mempool => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; + get rust_arc_decrement_strong_count_Mempool => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_NoteMigration => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + get rust_arc_increment_strong_count_NoteMigration => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_NoteMigration => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + get rust_arc_decrement_strong_count_NoteMigration => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_TransparentScanner => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + get rust_arc_increment_strong_count_TransparentScanner => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_TransparentScanner => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + get rust_arc_decrement_strong_count_TransparentScanner => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw) { @@ -8234,80 +9901,99 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List<dynamic>); } + @protected + FutureOr<Uint8List> Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + throw UnimplementedError(''); + } + @protected FutureOr<void> Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw) { + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(''); } @@ -8320,32 +10006,36 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw) { + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return DartVaultImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw) { + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return MempoolImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw) { + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return NoteMigrationImpl.frbInternalDcoDecode(raw as List<dynamic>); } @protected TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw) { + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return TransparentScannerImpl.frbInternalDcoDecode(raw as List<dynamic>); } @@ -8364,56 +10054,62 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected RustStreamSink<LogMessage> dco_decode_StreamSink_log_message_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<MempoolMsg> dco_decode_StreamSink_mempool_msg_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<MigrationStatus> dco_decode_StreamSink_migration_status_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<SigningEvent> dco_decode_StreamSink_signing_event_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<SigningStatus> dco_decode_StreamSink_signing_status_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<SyncProgress> dco_decode_StreamSink_sync_progress_Sse( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<VotingDelegationProgress> - dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw) { + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected RustStreamSink<VotingVoteCommitStage> - dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw) { + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @@ -8603,7 +10299,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteDisplay - dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw) { + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return dco_decode_voting_completed_vote_display(raw); } @@ -8695,9 +10391,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 0: return DKGStatus_WaitParams(); case 1: - return DKGStatus_WaitAddresses( - dco_decode_list_String(raw[1]), - ); + return DKGStatus_WaitAddresses(dco_decode_list_String(raw[1])); case 2: return DKGStatus_PublishRound0Pkg(); case 3: @@ -8715,9 +10409,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 9: return DKGStatus_Finalize(); case 10: - return DKGStatus_SharedAddress( - dco_decode_String(raw[1]), - ); + return DKGStatus_SharedAddress(dco_decode_String(raw[1])); default: throw Exception("unreachable"); } @@ -8749,10 +10441,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final arr = raw as List<dynamic>; if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); - return Folder( - id: dco_decode_u_32(arr[0]), - name: dco_decode_String(arr[1]), - ); + return Folder(id: dco_decode_u_32(arr[0]), name: dco_decode_String(arr[1])); } @protected @@ -8939,7 +10628,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_record_string_f_64_bool) @@ -9014,7 +10704,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingCompletedVoteChoice> dco_decode_list_voting_completed_vote_choice( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_completed_vote_choice) @@ -9029,7 +10720,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingDelegationRecovery> dco_decode_list_voting_delegation_recovery( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_delegation_recovery) @@ -9038,7 +10730,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingDelegationStatus> dco_decode_list_voting_delegation_status( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_delegation_status) @@ -9047,7 +10740,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingEncryptedShare> dco_decode_list_voting_encrypted_share( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_encrypted_share) @@ -9074,7 +10768,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_service_endpoint) @@ -9083,7 +10778,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingShareDelegationRecord> - dco_decode_list_voting_share_delegation_record(dynamic raw) { + dco_decode_list_voting_share_delegation_record(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_share_delegation_record) @@ -9098,7 +10793,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingSharePlanItem> dco_decode_list_voting_share_plan_item( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_share_plan_item) @@ -9107,7 +10803,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingShareSubmissionPayload> - dco_decode_list_voting_share_submission_payload(dynamic raw) { + dco_decode_list_voting_share_submission_payload(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_share_submission_payload) @@ -9124,7 +10820,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingSignedVoteCommitment> - dco_decode_list_voting_signed_vote_commitment(dynamic raw) { + dco_decode_list_voting_signed_vote_commitment(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return (raw as List<dynamic>) .map(dco_decode_voting_signed_vote_commitment) @@ -9211,9 +10907,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final arr = raw as List<dynamic>; if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); - return MemoRow( - cells: dco_decode_list_memo_cell(arr[0]), - ); + return MemoRow(cells: dco_decode_list_memo_cell(arr[0])); } @protected @@ -9247,13 +10941,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Dco (DartCObject based), see doc to use other codecs switch (raw[0]) { case 0: - return MempoolMsg_BlockHeight( - dco_decode_u_32(raw[1]), - ); + return MempoolMsg_BlockHeight(dco_decode_u_32(raw[1])); case 1: - return MempoolMsg_TxId( - dco_decode_box_autoadd_mempool_tx(raw[1]), - ); + return MempoolMsg_TxId(dco_decode_box_autoadd_mempool_tx(raw[1])); default: throw Exception("unreachable"); } @@ -9297,21 +10987,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Dco (DartCObject based), see doc to use other codecs switch (raw[0]) { case 0: - return MigrationEvent_SplitComplete( - fee: dco_decode_u_64(raw[1]), - ); + return MigrationEvent_SplitComplete(fee: dco_decode_u_64(raw[1])); case 1: - return MigrationEvent_MigrateComplete( - fee: dco_decode_u_64(raw[1]), - ); + return MigrationEvent_MigrateComplete(fee: dco_decode_u_64(raw[1])); case 2: return MigrationEvent_Complete(); case 3: return MigrationEvent_NothingToDo(); case 4: - return MigrationEvent_Error( - message: dco_decode_String(raw[1]), - ); + return MigrationEvent_Error(message: dco_decode_String(raw[1])); default: throw Exception("unreachable"); } @@ -9434,7 +11118,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteDisplay? - dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw) { + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs return raw == null ? null @@ -9529,9 +11213,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final arr = raw as List<dynamic>; if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); - return PoolBalance( - field0: dco_decode_list_prim_u_64_strict(arr[0]), - ); + return PoolBalance(field0: dco_decode_list_prim_u_64_strict(arr[0])); } @protected @@ -9611,10 +11293,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { if (arr.length != 2) { throw Exception('Expected 2 elements, got ${arr.length}'); } - return ( - dco_decode_u_32(arr[0]), - dco_decode_f_64(arr[1]), - ); + return (dco_decode_u_32(arr[0]), dco_decode_f_64(arr[1])); } @protected @@ -9639,9 +11318,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final arr = raw as List<dynamic>; if (arr.length != 1) throw Exception('unexpected arr length: expect 1 but see ${arr.length}'); - return SaplingParamsStatus( - downloaded: dco_decode_bool(arr[0]), - ); + return SaplingParamsStatus(downloaded: dco_decode_bool(arr[0])); } @protected @@ -9662,13 +11339,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { // Codec=Dco (DartCObject based), see doc to use other codecs switch (raw[0]) { case 0: - return SigningEvent_Progress( - dco_decode_String(raw[1]), - ); + return SigningEvent_Progress(dco_decode_String(raw[1])); case 1: - return SigningEvent_Result( - dco_decode_box_autoadd_pczt_package(raw[1]), - ); + return SigningEvent_Result(dco_decode_box_autoadd_pczt_package(raw[1])); default: throw Exception("unreachable"); } @@ -9699,9 +11372,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { case 9: return SigningStatus_SendingTransaction(); case 10: - return SigningStatus_TransactionSent( - dco_decode_String(raw[1]), - ); + return SigningStatus_TransactionSent(dco_decode_String(raw[1])); default: throw Exception("unreachable"); } @@ -9978,7 +11649,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 2) @@ -9991,7 +11663,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 2) @@ -10046,7 +11719,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 2) @@ -10130,7 +11804,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 11) @@ -10295,7 +11970,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingShareDelegationRecord dco_decode_voting_share_delegation_record( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 9) @@ -10360,7 +12036,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 4) @@ -10375,7 +12052,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 5) @@ -10405,7 +12083,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 11) @@ -10427,7 +12106,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( - dynamic raw) { + dynamic raw, + ) { // Codec=Dco (DartCObject based), see doc to use other codecs final arr = raw as List<dynamic>; if (arr.length != 2) @@ -10582,83 +12262,110 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected @@ -10670,108 +12377,130 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer) { + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return DartVaultImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer) { + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return MempoolImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer) { + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return NoteMigrationImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer) { + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return TransparentScannerImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); } @protected RustStreamSink<String> sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<DKGStatus> sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<LogMessage> sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<MempoolMsg> sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<MigrationStatus> sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<SigningEvent> sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<SigningStatus> sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<SyncProgress> sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<VotingDelegationProgress> - sse_decode_StreamSink_voting_delegation_progress_Sse( - SseDeserializer deserializer) { + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected RustStreamSink<VotingVoteCommitStage> - sse_decode_StreamSink_voting_vote_commit_stage_Sse( - SseDeserializer deserializer) { + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @@ -10807,26 +12536,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_time = sse_decode_u_32(deserializer); var var_balance = sse_decode_u_64(deserializer); return Account( - coin: var_coin, - id: var_id, - name: var_name, - seed: var_seed, - passphrase: var_passphrase, - aindex: var_aindex, - dindex: var_dindex, - icon: var_icon, - useInternal: var_useInternal, - birth: var_birth, - folder: var_folder, - position: var_position, - hidden: var_hidden, - saved: var_saved, - enabled: var_enabled, - internal: var_internal, - hw: var_hw, - height: var_height, - time: var_time, - balance: var_balance); + coin: var_coin, + id: var_id, + name: var_name, + seed: var_seed, + passphrase: var_passphrase, + aindex: var_aindex, + dindex: var_dindex, + icon: var_icon, + useInternal: var_useInternal, + birth: var_birth, + folder: var_folder, + position: var_position, + hidden: var_hidden, + saved: var_saved, + enabled: var_enabled, + internal: var_internal, + hw: var_hw, + height: var_height, + time: var_time, + balance: var_balance, + ); } @protected @@ -10841,14 +12571,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_hidden = sse_decode_opt_box_autoadd_bool(deserializer); var var_enabled = sse_decode_opt_box_autoadd_bool(deserializer); return AccountUpdate( - coin: var_coin, - id: var_id, - name: var_name, - icon: var_icon, - birth: var_birth, - folder: var_folder, - hidden: var_hidden, - enabled: var_enabled); + coin: var_coin, + id: var_id, + name: var_name, + icon: var_icon, + birth: var_birth, + folder: var_folder, + hidden: var_hidden, + enabled: var_enabled, + ); } @protected @@ -10860,11 +12591,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_ua = sse_decode_opt_String(deserializer); var var_diversifierIndex = sse_decode_u_32(deserializer); return Addresses( - taddr: var_taddr, - saddr: var_saddr, - oaddr: var_oaddr, - ua: var_ua, - diversifierIndex: var_diversifierIndex); + taddr: var_taddr, + saddr: var_saddr, + oaddr: var_oaddr, + ua: var_ua, + diversifierIndex: var_diversifierIndex, + ); } @protected @@ -10875,7 +12607,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_account_update(deserializer)); } @@ -10906,7 +12639,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected FrostParams sse_decode_box_autoadd_frost_params( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_frost_params(deserializer)); } @@ -10937,21 +12671,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_payment_options(deserializer)); } @protected PcztPackage sse_decode_box_autoadd_pczt_package( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_pczt_package(deserializer)); } @protected RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_raptor_q_params(deserializer)); } @@ -10964,7 +12701,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_signing_event(deserializer)); } @@ -10989,22 +12727,25 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteDisplay - sse_decode_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer) { + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_voting_completed_vote_display(deserializer)); } @protected VotingConfig sse_decode_box_autoadd_voting_config( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_voting_config(deserializer)); } @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs return (sse_decode_voting_pir_layout(deserializer)); } @@ -11029,13 +12770,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_transport = sse_decode_u_8(deserializer); var var_proxy = sse_decode_String(deserializer); return Coin.raw( - coin: var_coin, - account: var_account, - dbFilepath: var_dbFilepath, - url: var_url, - serverType: var_serverType, - transport: var_transport, - proxy: var_proxy); + coin: var_coin, + account: var_account, + dbFilepath: var_dbFilepath, + url: var_url, + serverType: var_serverType, + transport: var_transport, + proxy: var_proxy, + ); } @protected @@ -11046,7 +12788,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_addresses = sse_decode_list_String(deserializer); var var_notes = sse_decode_String(deserializer); return Contact( - id: var_id, name: var_name, addresses: var_addresses, notes: var_notes); + id: var_id, + name: var_name, + addresses: var_addresses, + notes: var_notes, + ); } @protected @@ -11055,7 +12801,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_contact = sse_decode_contact(deserializer); var var_matchedAddress = sse_decode_String(deserializer); return ContactMatch( - contact: var_contact, matchedAddress: var_matchedAddress); + contact: var_contact, + matchedAddress: var_matchedAddress, + ); } @protected @@ -11109,10 +12857,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_fromCurrency = sse_decode_String(deserializer); var var_toCurrency = sse_decode_String(deserializer); return ExchangeRate( - fromPrice: var_fromPrice, - toPrice: var_toPrice, - fromCurrency: var_fromCurrency, - toCurrency: var_toCurrency); + fromPrice: var_fromPrice, + toPrice: var_toPrice, + fromCurrency: var_fromCurrency, + toCurrency: var_toCurrency, + ); } @protected @@ -11145,9 +12894,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_coordinator = sse_decode_u_8(deserializer); var var_fundingAccount = sse_decode_u_32(deserializer); return FrostSignParams( - account: var_account, - coordinator: var_coordinator, - fundingAccount: var_fundingAccount); + account: var_account, + coordinator: var_coordinator, + fundingAccount: var_fundingAccount, + ); } @protected @@ -11218,7 +12968,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<ContactMatch> sse_decode_list_contact_match( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11231,7 +12982,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<DbAccountPreview> sse_decode_list_db_account_preview( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11256,7 +13008,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<Uint8List> sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11329,7 +13082,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<MempoolAmount> sse_decode_list_mempool_amount( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11420,7 +13174,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11433,7 +13188,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11446,7 +13202,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<RestoredAccount> sse_decode_list_restored_account( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11459,7 +13216,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<TAddressTxCount> sse_decode_list_t_address_tx_count( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11556,7 +13314,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingBallotIntent> sse_decode_list_voting_ballot_intent( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11569,7 +13328,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingCompletedVoteChoice> sse_decode_list_voting_completed_vote_choice( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11582,7 +13342,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingConfigRound> sse_decode_list_voting_config_round( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11595,7 +13356,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingDelegationRecovery> sse_decode_list_voting_delegation_recovery( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11608,7 +13370,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingDelegationStatus> sse_decode_list_voting_delegation_status( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11621,7 +13384,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingEncryptedShare> sse_decode_list_voting_encrypted_share( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11634,7 +13398,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingNextStep> sse_decode_list_voting_next_step( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11647,7 +13412,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingRoundInfo> sse_decode_list_voting_round_info( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11660,7 +13426,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingRoundSession> sse_decode_list_voting_round_session( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11673,7 +13440,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11686,8 +13454,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingShareDelegationRecord> - sse_decode_list_voting_share_delegation_record( - SseDeserializer deserializer) { + sse_decode_list_voting_share_delegation_record(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11700,7 +13467,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingSharePayload> sse_decode_list_voting_share_payload( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11713,7 +13481,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingSharePlanItem> sse_decode_list_voting_share_plan_item( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11726,8 +13495,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingShareSubmissionPayload> - sse_decode_list_voting_share_submission_payload( - SseDeserializer deserializer) { + sse_decode_list_voting_share_submission_payload( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11740,7 +13510,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11753,8 +13524,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingSignedVoteCommitment> - sse_decode_list_voting_signed_vote_commitment( - SseDeserializer deserializer) { + sse_decode_list_voting_signed_vote_commitment(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11767,7 +13537,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected List<VotingVoteRecovery> sse_decode_list_voting_vote_recovery( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var len_ = sse_decode_i_32(deserializer); @@ -11810,13 +13581,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_version = sse_decode_String(deserializer); var var_ping = sse_decode_u_32(deserializer); return LWDInfo( - url: var_url, - isTor: var_isTor, - height: var_height, - status: var_status, - uptime: var_uptime, - version: var_version, - ping: var_ping); + url: var_url, + isTor: var_isTor, + height: var_height, + status: var_status, + uptime: var_uptime, + version: var_version, + ping: var_ping, + ); } @protected @@ -11833,16 +13605,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_memo = sse_decode_opt_String(deserializer); var var_isUserMemo = sse_decode_bool(deserializer); return Memo( - id: var_id, - idTx: var_idTx, - idNote: var_idNote, - pool: var_pool, - height: var_height, - vout: var_vout, - time: var_time, - memoBytes: var_memoBytes, - memo: var_memo, - isUserMemo: var_isUserMemo); + id: var_id, + idTx: var_idTx, + idNote: var_idNote, + pool: var_pool, + height: var_height, + vout: var_vout, + time: var_time, + memoBytes: var_memoBytes, + memo: var_memo, + isUserMemo: var_isUserMemo, + ); } @protected @@ -11876,7 +13649,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_name = sse_decode_String(deserializer); var var_value = sse_decode_i_64(deserializer); return MempoolAmount( - account: var_account, name: var_name, value: var_value); + account: var_account, + name: var_name, + value: var_value, + ); } @protected @@ -11909,15 +13685,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_address = sse_decode_opt_String(deserializer); var var_memo = sse_decode_opt_String(deserializer); return MempoolNote( - account: var_account, - name: var_name, - value: var_value, - pool: var_pool, - scope: var_scope, - diversifier: var_diversifier, - diversifierIndex: var_diversifierIndex, - address: var_address, - memo: var_memo); + account: var_account, + name: var_name, + value: var_value, + pool: var_pool, + scope: var_scope, + diversifier: var_diversifier, + diversifierIndex: var_diversifierIndex, + address: var_address, + memo: var_memo, + ); } @protected @@ -11928,7 +13705,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_notes = sse_decode_list_mempool_note(deserializer); var var_size = sse_decode_u_32(deserializer); return MempoolTx( - txid: var_txid, amounts: var_amounts, notes: var_notes, size: var_size); + txid: var_txid, + amounts: var_amounts, + notes: var_notes, + size: var_size, + ); } @protected @@ -11969,16 +13750,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_nextAction = sse_decode_String(deserializer); var var_workSummary = sse_decode_String(deserializer); return MigrationStatus( - phase: var_phase, - splitFees: var_splitFees, - migrateFees: var_migrateFees, - totalFees: var_totalFees, - sdNotesCount: var_sdNotesCount, - nonSdNotesCount: var_nonSdNotesCount, - ironwoodSdCount: var_ironwoodSdCount, - progress: var_progress, - nextAction: var_nextAction, - workSummary: var_workSummary); + phase: var_phase, + splitFees: var_splitFees, + migrateFees: var_migrateFees, + totalFees: var_totalFees, + sdNotesCount: var_sdNotesCount, + nonSdNotesCount: var_nonSdNotesCount, + ironwoodSdCount: var_ironwoodSdCount, + progress: var_progress, + nextAction: var_nextAction, + workSummary: var_workSummary, + ); } @protected @@ -11998,29 +13780,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_internal = sse_decode_bool(deserializer); var var_hw = sse_decode_u_8(deserializer); return NewAccount( - icon: var_icon, - name: var_name, - restore: var_restore, - key: var_key, - passphrase: var_passphrase, - fingerprint: var_fingerprint, - aindex: var_aindex, - birth: var_birth, - folder: var_folder, - pools: var_pools, - useInternal: var_useInternal, - internal: var_internal, - hw: var_hw); + icon: var_icon, + name: var_name, + restore: var_restore, + key: var_key, + passphrase: var_passphrase, + fingerprint: var_fingerprint, + aindex: var_aindex, + birth: var_birth, + folder: var_folder, + pools: var_pools, + useInternal: var_useInternal, + internal: var_internal, + hw: var_hw, + ); } @protected OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_recipients = sse_decode_list_recipient(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); return OpenAliasResolution( - recipients: var_recipients, dnssecStatus: var_dnssecStatus); + recipients: var_recipients, + dnssecStatus: var_dnssecStatus, + ); } @protected @@ -12058,7 +13844,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { @@ -12136,13 +13923,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingCompletedVoteDisplay? - sse_decode_opt_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer) { + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { return (sse_decode_box_autoadd_voting_completed_vote_display( - deserializer)); + deserializer, + )); } else { return null; } @@ -12150,7 +13939,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingConfig? sse_decode_opt_box_autoadd_voting_config( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { @@ -12162,7 +13952,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs if (sse_decode_bool(deserializer)) { @@ -12213,10 +14004,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_smartTransparent = sse_decode_bool(deserializer); var var_category = sse_decode_opt_box_autoadd_u_32(deserializer); return PaymentOptions( - srcPools: var_srcPools, - recipientPaysFee: var_recipientPaysFee, - smartTransparent: var_smartTransparent, - category: var_category); + srcPools: var_srcPools, + recipientPaysFee: var_recipientPaysFee, + smartTransparent: var_smartTransparent, + category: var_category, + ); } @protected @@ -12233,16 +14025,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_category = sse_decode_opt_box_autoadd_u_32(deserializer); var var_isIssuance = sse_decode_bool(deserializer); return PcztPackage( - pczt: var_pczt, - nSpends: var_nSpends, - saplingIndices: var_saplingIndices, - orchardIndices: var_orchardIndices, - ironwoodIndices: var_ironwoodIndices, - canSign: var_canSign, - canBroadcast: var_canBroadcast, - price: var_price, - category: var_category, - isIssuance: var_isIssuance); + pczt: var_pczt, + nSpends: var_nSpends, + saplingIndices: var_saplingIndices, + orchardIndices: var_orchardIndices, + ironwoodIndices: var_ironwoodIndices, + canSign: var_canSign, + canBroadcast: var_canBroadcast, + price: var_price, + category: var_category, + isIssuance: var_isIssuance, + ); } @protected @@ -12257,14 +14050,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_types = sse_decode_list_String(deserializer); var var_memoPrefixes = sse_decode_list_String(deserializer); return PluginInfo( - id: var_id, - name: var_name, - version: var_version, - author: var_author, - description: var_description, - enabled: var_enabled, - types: var_types, - memoPrefixes: var_memoPrefixes); + id: var_id, + name: var_name, + version: var_version, + author: var_author, + description: var_description, + enabled: var_enabled, + types: var_types, + memoPrefixes: var_memoPrefixes, + ); } @protected @@ -12281,17 +14075,23 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_ecLevel = sse_decode_u_8(deserializer); var var_repair = sse_decode_u_32(deserializer); return RaptorQParams( - version: var_version, ecLevel: var_ecLevel, repair: var_repair); + version: var_version, + ecLevel: var_ecLevel, + repair: var_repair, + ); } @protected RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_records = sse_decode_list_String(deserializer); var var_dnssecStatus = sse_decode_String(deserializer); return RawOpenAliasResolution( - records: var_records, dnssecStatus: var_dnssecStatus); + records: var_records, + dnssecStatus: var_dnssecStatus, + ); } @protected @@ -12315,19 +14115,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_assetBase = sse_decode_list_prim_u_8_strict(deserializer); var var_assetName = sse_decode_opt_String(deserializer); return Recipient( - address: var_address, - amount: var_amount, - pools: var_pools, - userMemo: var_userMemo, - memoBytes: var_memoBytes, - price: var_price, - assetBase: var_assetBase, - assetName: var_assetName); + address: var_address, + amount: var_amount, + pools: var_pools, + userMemo: var_userMemo, + memoBytes: var_memoBytes, + price: var_price, + assetBase: var_assetBase, + assetName: var_assetName, + ); } @protected (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_field0 = sse_decode_String(deserializer); var var_field1 = sse_decode_f_64(deserializer); @@ -12353,17 +14155,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_useInternal = sse_decode_bool(deserializer); var var_birthHeight = sse_decode_u_32(deserializer); return RestoredAccount( - timestamp: var_timestamp, - name: var_name, - seed: var_seed, - aindex: var_aindex, - useInternal: var_useInternal, - birthHeight: var_birthHeight); + timestamp: var_timestamp, + name: var_name, + seed: var_seed, + aindex: var_aindex, + useInternal: var_useInternal, + birthHeight: var_birthHeight, + ); } @protected SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_downloaded = sse_decode_bool(deserializer); return SaplingParamsStatus(downloaded: var_downloaded); @@ -12457,13 +14261,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_txCount = sse_decode_u_32(deserializer); var var_time = sse_decode_u_32(deserializer); return TAddressTxCount( - pool: var_pool, - address: var_address, - scope: var_scope, - dindex: var_dindex, - amount: var_amount, - txCount: var_txCount, - time: var_time); + pool: var_pool, + address: var_address, + scope: var_scope, + dindex: var_dindex, + amount: var_amount, + txCount: var_txCount, + time: var_time, + ); } @protected @@ -12485,21 +14290,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_isUserMemo = sse_decode_bool(deserializer); var var_contactName = sse_decode_opt_String(deserializer); return Tx( - id: var_id, - txid: var_txid, - height: var_height, - time: var_time, - value: var_value, - fee: var_fee, - tpe: var_tpe, - category: var_category, - zsaValue: var_zsaValue, - assetId: var_assetId, - assetDisplay: var_assetDisplay, - price: var_price, - memo: var_memo, - isUserMemo: var_isUserMemo, - contactName: var_contactName); + id: var_id, + txid: var_txid, + height: var_height, + time: var_time, + value: var_value, + fee: var_fee, + tpe: var_tpe, + category: var_category, + zsaValue: var_zsaValue, + assetId: var_assetId, + assetDisplay: var_assetDisplay, + price: var_price, + memo: var_memo, + isUserMemo: var_isUserMemo, + contactName: var_contactName, + ); } @protected @@ -12518,18 +14324,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_memos = sse_decode_list_tx_memo(deserializer); var var_userMemo = sse_decode_opt_String(deserializer); return TxAccount( - id: var_id, - account: var_account, - txid: var_txid, - height: var_height, - time: var_time, - price: var_price, - category: var_category, - notes: var_notes, - spends: var_spends, - outputs: var_outputs, - memos: var_memos, - userMemo: var_userMemo); + id: var_id, + account: var_account, + txid: var_txid, + height: var_height, + time: var_time, + price: var_price, + category: var_category, + notes: var_notes, + spends: var_spends, + outputs: var_outputs, + memos: var_memos, + userMemo: var_userMemo, + ); } @protected @@ -12541,11 +14348,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_memo = sse_decode_opt_String(deserializer); var var_memoBytes = sse_decode_list_prim_u_8_strict(deserializer); return TxMemo( - note: var_note, - output: var_output, - pool: var_pool, - memo: var_memo, - memoBytes: var_memoBytes); + note: var_note, + output: var_output, + pool: var_pool, + memo: var_memo, + memoBytes: var_memoBytes, + ); } @protected @@ -12564,18 +14372,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_idAsset = sse_decode_opt_box_autoadd_u_32(deserializer); var var_assetDisplay = sse_decode_String(deserializer); return TxNote( - id: var_id, - pool: var_pool, - height: var_height, - tx: var_tx, - scope: var_scope, - diversifier: var_diversifier, - diversifierIndex: var_diversifierIndex, - value: var_value, - locked: var_locked, - memo: var_memo, - idAsset: var_idAsset, - assetDisplay: var_assetDisplay); + id: var_id, + pool: var_pool, + height: var_height, + tx: var_tx, + scope: var_scope, + diversifier: var_diversifier, + diversifierIndex: var_diversifierIndex, + value: var_value, + locked: var_locked, + memo: var_memo, + idAsset: var_idAsset, + assetDisplay: var_assetDisplay, + ); } @protected @@ -12588,12 +14397,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_address = sse_decode_String(deserializer); var var_contactName = sse_decode_opt_String(deserializer); return TxOutput( - id: var_id, - pool: var_pool, - height: var_height, - value: var_value, - address: var_address, - contactName: var_contactName); + id: var_id, + pool: var_pool, + height: var_height, + value: var_value, + address: var_address, + contactName: var_contactName, + ); } @protected @@ -12606,12 +14416,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_canSign = sse_decode_bool(deserializer); var var_canBroadcast = sse_decode_bool(deserializer); return TxPlan( - height: var_height, - inputs: var_inputs, - outputs: var_outputs, - fee: var_fee, - canSign: var_canSign, - canBroadcast: var_canBroadcast); + height: var_height, + inputs: var_inputs, + outputs: var_outputs, + fee: var_fee, + canSign: var_canSign, + canBroadcast: var_canBroadcast, + ); } @protected @@ -12621,7 +14432,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_amount = sse_decode_opt_box_autoadd_u_64(deserializer); var var_assetName = sse_decode_String(deserializer); return TxPlanIn( - pool: var_pool, amount: var_amount, assetName: var_assetName); + pool: var_pool, + amount: var_amount, + assetName: var_assetName, + ); } @protected @@ -12632,10 +14446,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_address = sse_decode_String(deserializer); var var_assetName = sse_decode_String(deserializer); return TxPlanOut( - pool: var_pool, - amount: var_amount, - address: var_address, - assetName: var_assetName); + pool: var_pool, + amount: var_amount, + address: var_address, + assetName: var_assetName, + ); } @protected @@ -12648,12 +14463,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_idAsset = sse_decode_opt_box_autoadd_u_32(deserializer); var var_assetDisplay = sse_decode_String(deserializer); return TxSpend( - id: var_id, - pool: var_pool, - height: var_height, - value: var_value, - idAsset: var_idAsset, - assetDisplay: var_assetDisplay); + id: var_id, + pool: var_pool, + height: var_height, + value: var_value, + idAsset: var_idAsset, + assetDisplay: var_assetDisplay, + ); } @protected @@ -12700,47 +14516,60 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingBallotIntent sse_decode_voting_ballot_intent( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_proposalId = sse_decode_u_32(deserializer); var var_skipped = sse_decode_bool(deserializer); var var_choice = sse_decode_opt_box_autoadd_u_32(deserializer); return VotingBallotIntent( - proposalId: var_proposalId, skipped: var_skipped, choice: var_choice); + proposalId: var_proposalId, + skipped: var_skipped, + choice: var_choice, + ); } @protected VotingChainResponse sse_decode_voting_chain_response( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_statusCode = sse_decode_u_16(deserializer); var var_body = sse_decode_String(deserializer); var var_retryAfterSecs = sse_decode_opt_box_autoadd_u_64(deserializer); return VotingChainResponse( - statusCode: var_statusCode, - body: var_body, - retryAfterSecs: var_retryAfterSecs); + statusCode: var_statusCode, + body: var_body, + retryAfterSecs: var_retryAfterSecs, + ); } @protected VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_proposalId = sse_decode_u_32(deserializer); var var_choice = sse_decode_opt_box_autoadd_u_32(deserializer); return VotingCompletedVoteChoice( - proposalId: var_proposalId, choice: var_choice); + proposalId: var_proposalId, + choice: var_choice, + ); } @protected VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs - var var_choices = - sse_decode_list_voting_completed_vote_choice(deserializer); + var var_choices = sse_decode_list_voting_completed_vote_choice( + deserializer, + ); var var_votedAt = sse_decode_opt_box_autoadd_u_64(deserializer); return VotingCompletedVoteDisplay( - choices: var_choices, votedAt: var_votedAt); + choices: var_choices, + votedAt: var_votedAt, + ); } @protected @@ -12752,23 +14581,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_switchKind = sse_decode_String(deserializer); var var_voteServers = sse_decode_list_voting_service_endpoint(deserializer); var var_pirServers = sse_decode_list_voting_service_endpoint(deserializer); - var var_pirLayout = - sse_decode_opt_box_autoadd_voting_pir_layout(deserializer); + var var_pirLayout = sse_decode_opt_box_autoadd_voting_pir_layout( + deserializer, + ); var var_rounds = sse_decode_list_voting_config_round(deserializer); return VotingConfig( - source: var_source, - sourceFingerprint: var_sourceFingerprint, - trustedKeyFingerprint: var_trustedKeyFingerprint, - switchKind: var_switchKind, - voteServers: var_voteServers, - pirServers: var_pirServers, - pirLayout: var_pirLayout, - rounds: var_rounds); + source: var_source, + sourceFingerprint: var_sourceFingerprint, + trustedKeyFingerprint: var_trustedKeyFingerprint, + switchKind: var_switchKind, + voteServers: var_voteServers, + pirServers: var_pirServers, + pirLayout: var_pirLayout, + rounds: var_rounds, + ); } @protected VotingConfigRound sse_decode_voting_config_round( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_roundId = sse_decode_String(deserializer); var var_eaPk = sse_decode_list_prim_u_8_strict(deserializer); @@ -12777,27 +14609,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingDelegationBuild sse_decode_voting_delegation_build( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_submission = sse_decode_voting_delegation_submission(deserializer); var var_wireJson = sse_decode_String(deserializer); return VotingDelegationBuild( - submission: var_submission, wireJson: var_wireJson); + submission: var_submission, + wireJson: var_wireJson, + ); } @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_txHash = sse_decode_String(deserializer); var var_vanLeafPosition = sse_decode_u_32(deserializer); return VotingDelegationConfirmation( - txHash: var_txHash, vanLeafPosition: var_vanLeafPosition); + txHash: var_txHash, + vanLeafPosition: var_vanLeafPosition, + ); } @protected VotingDelegationProgress sse_decode_voting_delegation_progress( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var tag_ = sse_decode_i_32(deserializer); @@ -12826,7 +14665,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingDelegationRecovery sse_decode_voting_delegation_recovery( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); var var_phase = sse_decode_String(deserializer); @@ -12834,16 +14674,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_txHash = sse_decode_opt_String(deserializer); var var_vanLeafPosition = sse_decode_opt_box_autoadd_u_32(deserializer); return VotingDelegationRecovery( - bundleIndex: var_bundleIndex, - phase: var_phase, - workflowPhase: var_workflowPhase, - txHash: var_txHash, - vanLeafPosition: var_vanLeafPosition); + bundleIndex: var_bundleIndex, + phase: var_phase, + workflowPhase: var_workflowPhase, + txHash: var_txHash, + vanLeafPosition: var_vanLeafPosition, + ); } @protected VotingDelegationSetup sse_decode_voting_delegation_setup( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_pcztBytes = sse_decode_list_prim_u_8_strict(deserializer); var var_pcztSighash = sse_decode_list_prim_u_8_strict(deserializer); @@ -12852,28 +14694,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_actionBytes = sse_decode_list_prim_u_8_strict(deserializer); var var_tx1Effects = sse_decode_list_prim_u_8_strict(deserializer); return VotingDelegationSetup( - pcztBytes: var_pcztBytes, - pcztSighash: var_pcztSighash, - rk: var_rk, - actionIndex: var_actionIndex, - actionBytes: var_actionBytes, - tx1Effects: var_tx1Effects); + pcztBytes: var_pcztBytes, + pcztSighash: var_pcztSighash, + rk: var_rk, + actionIndex: var_actionIndex, + actionBytes: var_actionBytes, + tx1Effects: var_tx1Effects, + ); } @protected VotingDelegationStatus sse_decode_voting_delegation_status( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); var var_phase = sse_decode_String(deserializer); var var_txHash = sse_decode_opt_String(deserializer); return VotingDelegationStatus( - bundleIndex: var_bundleIndex, phase: var_phase, txHash: var_txHash); + bundleIndex: var_bundleIndex, + phase: var_phase, + txHash: var_txHash, + ); } @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_proof = sse_decode_list_prim_u_8_strict(deserializer); var var_rk = sse_decode_list_prim_u_8_strict(deserializer); @@ -12887,28 +14735,33 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_sighash = sse_decode_list_prim_u_8_strict(deserializer); var var_tx1Effects = sse_decode_list_prim_u_8_strict(deserializer); return VotingDelegationSubmission( - proof: var_proof, - rk: var_rk, - nfSigned: var_nfSigned, - cmxNew: var_cmxNew, - govComm: var_govComm, - govNullifiers: var_govNullifiers, - alpha: var_alpha, - voteRoundId: var_voteRoundId, - spendAuthSig: var_spendAuthSig, - sighash: var_sighash, - tx1Effects: var_tx1Effects); + proof: var_proof, + rk: var_rk, + nfSigned: var_nfSigned, + cmxNew: var_cmxNew, + govComm: var_govComm, + govNullifiers: var_govNullifiers, + alpha: var_alpha, + voteRoundId: var_voteRoundId, + spendAuthSig: var_spendAuthSig, + sighash: var_sighash, + tx1Effects: var_tx1Effects, + ); } @protected VotingEncryptedShare sse_decode_voting_encrypted_share( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_c1 = sse_decode_list_prim_u_8_strict(deserializer); var var_c2 = sse_decode_list_prim_u_8_strict(deserializer); var var_shareIndex = sse_decode_u_32(deserializer); return VotingEncryptedShare( - c1: var_c1, c2: var_c2, shareIndex: var_shareIndex); + c1: var_c1, + c2: var_c2, + shareIndex: var_shareIndex, + ); } @protected @@ -12920,11 +14773,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_choice = sse_decode_u_32(deserializer); var var_shareIndex = sse_decode_u_32(deserializer); return VotingNextStep( - kind: var_kind, - bundleIndex: var_bundleIndex, - proposalId: var_proposalId, - choice: var_choice, - shareIndex: var_shareIndex); + kind: var_kind, + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + choice: var_choice, + shareIndex: var_shareIndex, + ); } @protected @@ -12935,15 +14789,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_tier1Layers = sse_decode_u_32(deserializer); var var_polyLen = sse_decode_u_32(deserializer); return VotingPirLayout( - pirDepth: var_pirDepth, - tier0Layers: var_tier0Layers, - tier1Layers: var_tier1Layers, - polyLen: var_polyLen); + pirDepth: var_pirDepth, + tier0Layers: var_tier0Layers, + tier1Layers: var_tier1Layers, + polyLen: var_polyLen, + ); } @protected VotingPreparedInfo sse_decode_voting_prepared_info( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_roundId = sse_decode_String(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); @@ -12951,11 +14807,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_delegatedWeightZatoshi = sse_decode_u_64(deserializer); var var_roundName = sse_decode_String(deserializer); return VotingPreparedInfo( - roundId: var_roundId, - bundleIndex: var_bundleIndex, - eligibleWeightZatoshi: var_eligibleWeightZatoshi, - delegatedWeightZatoshi: var_delegatedWeightZatoshi, - roundName: var_roundName); + roundId: var_roundId, + bundleIndex: var_bundleIndex, + eligibleWeightZatoshi: var_eligibleWeightZatoshi, + delegatedWeightZatoshi: var_delegatedWeightZatoshi, + roundName: var_roundName, + ); } @protected @@ -12965,18 +14822,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_network = sse_decode_String(deserializer); var var_snapshotHeight = sse_decode_u_64(deserializer); var var_hotkeyAddress = sse_decode_opt_String(deserializer); - var var_eligibleWeightZatoshi = - sse_decode_opt_box_autoadd_u_64(deserializer); + var var_eligibleWeightZatoshi = sse_decode_opt_box_autoadd_u_64( + deserializer, + ); var var_bundleCount = sse_decode_u_32(deserializer); var var_createdAt = sse_decode_u_64(deserializer); return VotingRoundInfo( - roundId: var_roundId, - network: var_network, - snapshotHeight: var_snapshotHeight, - hotkeyAddress: var_hotkeyAddress, - eligibleWeightZatoshi: var_eligibleWeightZatoshi, - bundleCount: var_bundleCount, - createdAt: var_createdAt); + roundId: var_roundId, + network: var_network, + snapshotHeight: var_snapshotHeight, + hotkeyAddress: var_hotkeyAddress, + eligibleWeightZatoshi: var_eligibleWeightZatoshi, + bundleCount: var_bundleCount, + createdAt: var_createdAt, + ); } @protected @@ -12987,8 +14846,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_nextSteps = sse_decode_list_voting_next_step(deserializer); var var_openProposals = sse_decode_list_prim_u_32_strict(deserializer); var var_allDecided = sse_decode_bool(deserializer); - var var_delegationStatuses = - sse_decode_list_voting_delegation_status(deserializer); + var var_delegationStatuses = sse_decode_list_voting_delegation_status( + deserializer, + ); var var_blockingRecovery = sse_decode_bool(deserializer); var var_blockingShareWork = sse_decode_bool(deserializer); var var_hotkeyBound = sse_decode_bool(deserializer); @@ -12999,64 +14859,72 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_needsDraftSetup = sse_decode_bool(deserializer); var var_primaryAction = sse_decode_String(deserializer); return VotingRoundPlan( - roundId: var_roundId, - pendingRecovery: var_pendingRecovery, - nextSteps: var_nextSteps, - openProposals: var_openProposals, - allDecided: var_allDecided, - delegationStatuses: var_delegationStatuses, - blockingRecovery: var_blockingRecovery, - blockingShareWork: var_blockingShareWork, - hotkeyBound: var_hotkeyBound, - completedVoteArtifact: var_completedVoteArtifact, - completedForDisplay: var_completedForDisplay, - completedVoteDisplay: var_completedVoteDisplay, - needsDraftSetup: var_needsDraftSetup, - primaryAction: var_primaryAction); + roundId: var_roundId, + pendingRecovery: var_pendingRecovery, + nextSteps: var_nextSteps, + openProposals: var_openProposals, + allDecided: var_allDecided, + delegationStatuses: var_delegationStatuses, + blockingRecovery: var_blockingRecovery, + blockingShareWork: var_blockingShareWork, + hotkeyBound: var_hotkeyBound, + completedVoteArtifact: var_completedVoteArtifact, + completedForDisplay: var_completedForDisplay, + completedVoteDisplay: var_completedVoteDisplay, + needsDraftSetup: var_needsDraftSetup, + primaryAction: var_primaryAction, + ); } @protected VotingRoundRecovery sse_decode_voting_round_recovery( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_roundId = sse_decode_String(deserializer); var var_bundleCount = sse_decode_u_32(deserializer); - var var_delegation = - sse_decode_list_voting_delegation_recovery(deserializer); + var var_delegation = sse_decode_list_voting_delegation_recovery( + deserializer, + ); var var_votes = sse_decode_list_voting_vote_recovery(deserializer); var var_shares = sse_decode_list_voting_share_workflow(deserializer); - var var_shareDelegations = - sse_decode_list_voting_share_delegation_record(deserializer); + var var_shareDelegations = sse_decode_list_voting_share_delegation_record( + deserializer, + ); var var_unconfirmedShareDelegations = sse_decode_list_voting_share_delegation_record(deserializer); return VotingRoundRecovery( - roundId: var_roundId, - bundleCount: var_bundleCount, - delegation: var_delegation, - votes: var_votes, - shares: var_shares, - shareDelegations: var_shareDelegations, - unconfirmedShareDelegations: var_unconfirmedShareDelegations); + roundId: var_roundId, + bundleCount: var_bundleCount, + delegation: var_delegation, + votes: var_votes, + shares: var_shares, + shareDelegations: var_shareDelegations, + unconfirmedShareDelegations: var_unconfirmedShareDelegations, + ); } @protected VotingRoundSession sse_decode_voting_round_session( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_roundId = sse_decode_String(deserializer); var var_plan = sse_decode_voting_round_plan(deserializer); var var_recovery = sse_decode_voting_round_recovery(deserializer); var var_intents = sse_decode_list_voting_ballot_intent(deserializer); return VotingRoundSession( - roundId: var_roundId, - plan: var_plan, - recovery: var_recovery, - intents: var_intents); + roundId: var_roundId, + plan: var_plan, + recovery: var_recovery, + intents: var_intents, + ); } @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_url = sse_decode_String(deserializer); var var_label = sse_decode_String(deserializer); @@ -13065,7 +14933,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingShareDelegationRecord sse_decode_voting_share_delegation_record( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_roundId = sse_decode_String(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); @@ -13077,20 +14946,22 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_submitAt = sse_decode_u_64(deserializer); var var_createdAt = sse_decode_u_64(deserializer); return VotingShareDelegationRecord( - roundId: var_roundId, - bundleIndex: var_bundleIndex, - proposalId: var_proposalId, - shareIndex: var_shareIndex, - sentToUrls: var_sentToUrls, - nullifier: var_nullifier, - confirmed: var_confirmed, - submitAt: var_submitAt, - createdAt: var_createdAt); + roundId: var_roundId, + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + sentToUrls: var_sentToUrls, + nullifier: var_nullifier, + confirmed: var_confirmed, + submitAt: var_submitAt, + createdAt: var_createdAt, + ); } @protected VotingSharePayload sse_decode_voting_share_payload( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_sharesHash = sse_decode_list_prim_u_8_strict(deserializer); var var_proposalId = sse_decode_u_32(deserializer); @@ -13101,62 +14972,70 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_shareComms = sse_decode_list_list_prim_u_8_strict(deserializer); var var_primaryBlind = sse_decode_list_prim_u_8_strict(deserializer); return VotingSharePayload( - sharesHash: var_sharesHash, - proposalId: var_proposalId, - voteDecision: var_voteDecision, - encShare: var_encShare, - treePosition: var_treePosition, - allEncShares: var_allEncShares, - shareComms: var_shareComms, - primaryBlind: var_primaryBlind); + sharesHash: var_sharesHash, + proposalId: var_proposalId, + voteDecision: var_voteDecision, + encShare: var_encShare, + treePosition: var_treePosition, + allEncShares: var_allEncShares, + shareComms: var_shareComms, + primaryBlind: var_primaryBlind, + ); } @protected VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs var var_summary = sse_decode_voting_share_tracking_summary(deserializer); - var var_nextTrackingDelaySecs = - sse_decode_opt_box_autoadd_u_64(deserializer); + var var_nextTrackingDelaySecs = sse_decode_opt_box_autoadd_u_64( + deserializer, + ); var var_lastMoment = sse_decode_bool(deserializer); var var_submissions = sse_decode_list_voting_share_plan_item(deserializer); return VotingSharePlan( - summary: var_summary, - nextTrackingDelaySecs: var_nextTrackingDelaySecs, - lastMoment: var_lastMoment, - submissions: var_submissions); + summary: var_summary, + nextTrackingDelaySecs: var_nextTrackingDelaySecs, + lastMoment: var_lastMoment, + submissions: var_submissions, + ); } @protected VotingSharePlanItem sse_decode_voting_share_plan_item( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_submitAt = sse_decode_u_64(deserializer); var var_targetCount = sse_decode_u_32(deserializer); var var_targetServers = sse_decode_list_String(deserializer); return VotingSharePlanItem( - submitAt: var_submitAt, - targetCount: var_targetCount, - targetServers: var_targetServers); + submitAt: var_submitAt, + targetCount: var_targetCount, + targetServers: var_targetServers, + ); } @protected VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); var var_proposalId = sse_decode_u_32(deserializer); var var_shareIndex = sse_decode_u_32(deserializer); var var_vcTreePosition = sse_decode_opt_box_autoadd_u_64(deserializer); return VotingShareSubmissionPayload( - bundleIndex: var_bundleIndex, - proposalId: var_proposalId, - shareIndex: var_shareIndex, - vcTreePosition: var_vcTreePosition); + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + vcTreePosition: var_vcTreePosition, + ); } @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_total = sse_decode_u_64(deserializer); var var_confirmed = sse_decode_u_64(deserializer); @@ -13164,38 +15043,43 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_ready = sse_decode_u_64(deserializer); var var_overdue = sse_decode_u_64(deserializer); return VotingShareTrackingSummary( - total: var_total, - confirmed: var_confirmed, - waiting: var_waiting, - ready: var_ready, - overdue: var_overdue); + total: var_total, + confirmed: var_confirmed, + waiting: var_waiting, + ready: var_ready, + overdue: var_overdue, + ); } @protected VotingShareWorkflow sse_decode_voting_share_workflow( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); var var_proposalId = sse_decode_u_32(deserializer); var var_shareIndex = sse_decode_u_32(deserializer); var var_phase = sse_decode_String(deserializer); return VotingShareWorkflow( - bundleIndex: var_bundleIndex, - proposalId: var_proposalId, - shareIndex: var_shareIndex, - phase: var_phase); + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + shareIndex: var_shareIndex, + phase: var_phase, + ); } @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_proposalId = sse_decode_u_32(deserializer); var var_choice = sse_decode_u_32(deserializer); var var_voteRoundId = sse_decode_String(deserializer); var var_vanNullifier = sse_decode_list_prim_u_8_strict(deserializer); - var var_voteAuthorityNoteNew = - sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthorityNoteNew = sse_decode_list_prim_u_8_strict( + deserializer, + ); var var_voteCommitment = sse_decode_list_prim_u_8_strict(deserializer); var var_proof = sse_decode_list_prim_u_8_strict(deserializer); var var_anchorHeight = sse_decode_u_32(deserializer); @@ -13203,28 +15087,31 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_voteAuthSig = sse_decode_list_prim_u_8_strict(deserializer); var var_commitmentBundleJson = sse_decode_String(deserializer); return VotingSignedVoteCommitment( - proposalId: var_proposalId, - choice: var_choice, - voteRoundId: var_voteRoundId, - vanNullifier: var_vanNullifier, - voteAuthorityNoteNew: var_voteAuthorityNoteNew, - voteCommitment: var_voteCommitment, - proof: var_proof, - anchorHeight: var_anchorHeight, - rVpk: var_rVpk, - voteAuthSig: var_voteAuthSig, - commitmentBundleJson: var_commitmentBundleJson); + proposalId: var_proposalId, + choice: var_choice, + voteRoundId: var_voteRoundId, + vanNullifier: var_vanNullifier, + voteAuthorityNoteNew: var_voteAuthorityNoteNew, + voteCommitment: var_voteCommitment, + proof: var_proof, + anchorHeight: var_anchorHeight, + rVpk: var_rVpk, + voteAuthSig: var_voteAuthSig, + commitmentBundleJson: var_commitmentBundleJson, + ); } @protected VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_vcTreePosition = sse_decode_u_64(deserializer); var var_vanLeafPosition = sse_decode_opt_box_autoadd_u_32(deserializer); return VotingTreeVoteConfirmation( - vcTreePosition: var_vcTreePosition, - vanLeafPosition: var_vanLeafPosition); + vcTreePosition: var_vcTreePosition, + vanLeafPosition: var_vanLeafPosition, + ); } @protected @@ -13234,14 +15121,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_position = sse_decode_u_32(deserializer); var var_anchorHeight = sse_decode_u_32(deserializer); return VotingVanWitness( - authPath: var_authPath, - position: var_position, - anchorHeight: var_anchorHeight); + authPath: var_authPath, + position: var_position, + anchorHeight: var_anchorHeight, + ); } @protected VotingVoteCommitStage sse_decode_voting_vote_commit_stage( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var tag_ = sse_decode_i_32(deserializer); @@ -13250,25 +15139,32 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_proposalId = sse_decode_u_32(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); return VotingVoteCommitStage_ProofStarting( - proposalId: var_proposalId, bundleIndex: var_bundleIndex); + proposalId: var_proposalId, + bundleIndex: var_bundleIndex, + ); case 1: var var_proposalId = sse_decode_u_32(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); var var_progress = sse_decode_f_64(deserializer); return VotingVoteCommitStage_ProofProgress( - proposalId: var_proposalId, - bundleIndex: var_bundleIndex, - progress: var_progress); + proposalId: var_proposalId, + bundleIndex: var_bundleIndex, + progress: var_progress, + ); case 2: var var_proposalId = sse_decode_u_32(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); return VotingVoteCommitStage_SharePayloadsBuilding( - proposalId: var_proposalId, bundleIndex: var_bundleIndex); + proposalId: var_proposalId, + bundleIndex: var_bundleIndex, + ); case 3: var var_proposalId = sse_decode_u_32(deserializer); var var_bundleIndex = sse_decode_u_32(deserializer); return VotingVoteCommitStage_Signing( - proposalId: var_proposalId, bundleIndex: var_bundleIndex); + proposalId: var_proposalId, + bundleIndex: var_bundleIndex, + ); default: throw UnimplementedError(''); } @@ -13276,41 +15172,51 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected VotingVoteCommitments sse_decode_voting_vote_commitments( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); - var var_commitments = - sse_decode_list_voting_signed_vote_commitment(deserializer); + var var_commitments = sse_decode_list_voting_signed_vote_commitment( + deserializer, + ); return VotingVoteCommitments( - bundleIndex: var_bundleIndex, commitments: var_commitments); + bundleIndex: var_bundleIndex, + commitments: var_commitments, + ); } @protected VotingVoteConfirmation sse_decode_voting_vote_confirmation( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_txHash = sse_decode_String(deserializer); var var_vanLeafPosition = sse_decode_u_32(deserializer); var var_vcTreePosition = sse_decode_u_64(deserializer); return VotingVoteConfirmation( - txHash: var_txHash, - vanLeafPosition: var_vanLeafPosition, - vcTreePosition: var_vcTreePosition); + txHash: var_txHash, + vanLeafPosition: var_vanLeafPosition, + vcTreePosition: var_vcTreePosition, + ); } @protected VotingVotePayloads sse_decode_voting_vote_payloads( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_submission = sse_decode_voting_vote_submission(deserializer); var var_sharePayloads = sse_decode_list_voting_share_payload(deserializer); return VotingVotePayloads( - submission: var_submission, sharePayloads: var_sharePayloads); + submission: var_submission, + sharePayloads: var_sharePayloads, + ); } @protected VotingVoteRecovery sse_decode_voting_vote_recovery( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_bundleIndex = sse_decode_u_32(deserializer); var var_proposalId = sse_decode_u_32(deserializer); @@ -13321,40 +15227,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_vcTreePosition = sse_decode_opt_box_autoadd_u_64(deserializer); var var_hasCommitmentBundle = sse_decode_bool(deserializer); return VotingVoteRecovery( - bundleIndex: var_bundleIndex, - proposalId: var_proposalId, - choice: var_choice, - phase: var_phase, - workflowPhase: var_workflowPhase, - txHash: var_txHash, - vcTreePosition: var_vcTreePosition, - hasCommitmentBundle: var_hasCommitmentBundle); + bundleIndex: var_bundleIndex, + proposalId: var_proposalId, + choice: var_choice, + phase: var_phase, + workflowPhase: var_workflowPhase, + txHash: var_txHash, + vcTreePosition: var_vcTreePosition, + hasCommitmentBundle: var_hasCommitmentBundle, + ); } @protected VotingVoteSubmission sse_decode_voting_vote_submission( - SseDeserializer deserializer) { + SseDeserializer deserializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs var var_voteRoundId = sse_decode_String(deserializer); var var_proposalId = sse_decode_u_32(deserializer); var var_vanNullifier = sse_decode_list_prim_u_8_strict(deserializer); - var var_voteAuthorityNoteNew = - sse_decode_list_prim_u_8_strict(deserializer); + var var_voteAuthorityNoteNew = sse_decode_list_prim_u_8_strict( + deserializer, + ); var var_voteCommitment = sse_decode_list_prim_u_8_strict(deserializer); var var_proof = sse_decode_list_prim_u_8_strict(deserializer); var var_rVpk = sse_decode_list_prim_u_8_strict(deserializer); var var_voteAuthSig = sse_decode_list_prim_u_8_strict(deserializer); var var_anchorHeight = sse_decode_u_32(deserializer); return VotingVoteSubmission( - voteRoundId: var_voteRoundId, - proposalId: var_proposalId, - vanNullifier: var_vanNullifier, - voteAuthorityNoteNew: var_voteAuthorityNoteNew, - voteCommitment: var_voteCommitment, - proof: var_proof, - rVpk: var_rVpk, - voteAuthSig: var_voteAuthSig, - anchorHeight: var_anchorHeight); + voteRoundId: var_voteRoundId, + proposalId: var_proposalId, + vanNullifier: var_vanNullifier, + voteAuthorityNoteNew: var_voteAuthorityNoteNew, + voteCommitment: var_voteCommitment, + proof: var_proof, + rVpk: var_rVpk, + voteAuthSig: var_voteAuthSig, + anchorHeight: var_anchorHeight, + ); } @protected @@ -13369,170 +15279,245 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { var var_firstSeenHeight = sse_decode_u_32(deserializer); var var_balance = sse_decode_u_64(deserializer); return ZsaHolding( - idAsset: var_idAsset, - assetDescHash: var_assetDescHash, - assetName: var_assetName, - ik: var_ik, - assetBase: var_assetBase, - finalized: var_finalized, - firstSeenHeight: var_firstSeenHeight, - balance: var_balance); + idAsset: var_idAsset, + assetDescHash: var_assetDescHash, + assetName: var_assetName, + ik: var_ik, + assetBase: var_assetBase, + finalized: var_finalized, + firstSeenHeight: var_firstSeenHeight, + balance: var_balance, + ); } @protected void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer) { + AnyhowException self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.message, serializer); } @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: true), serializer); + (self as DartVaultImpl).frbInternalSseEncode(move: true), + serializer, + ); } @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: true), serializer); + (self as MempoolImpl).frbInternalSseEncode(move: true), + serializer, + ); } @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: true), - serializer); + (self as NoteMigrationImpl).frbInternalSseEncode(move: true), + serializer, + ); } @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: true), - serializer); + (self as TransparentScannerImpl).frbInternalSseEncode(move: true), + serializer, + ); } @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: false), serializer); + (self as MempoolImpl).frbInternalSseEncode(move: false), + serializer, + ); } @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: false), - serializer); + (self as TransparentScannerImpl).frbInternalSseEncode(move: false), + serializer, + ); } @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: false), serializer); + (self as DartVaultImpl).frbInternalSseEncode(move: false), + serializer, + ); } @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: false), - serializer); + (self as NoteMigrationImpl).frbInternalSseEncode(move: false), + serializer, + ); } @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: false), - serializer); + (self as TransparentScannerImpl).frbInternalSseEncode(move: false), + serializer, + ); + } + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + FutureOr<Uint8List> Function(Uint8List) self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_DartOpaque( + encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + self, + ), + serializer, + ); } @protected void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr<void> Function(Uint8List) self, SseSerializer serializer) { + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr<void> Function(Uint8List) self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_DartOpaque( - encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - self), - serializer); + encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + self, + ), + serializer, + ); } @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_isize( - PlatformPointerUtil.ptrToPlatformInt64(encodeDartOpaque( - self, portManager.dartHandlerPort, generalizedFrbRustBinding)), - serializer); + PlatformPointerUtil.ptrToPlatformInt64( + encodeDartOpaque( + self, + portManager.dartHandlerPort, + generalizedFrbRustBinding, + ), + ), + serializer, + ); } @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer) { + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as DartVaultImpl).frbInternalSseEncode(move: null), serializer); + (self as DartVaultImpl).frbInternalSseEncode(move: null), + serializer, + ); } @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer) { + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as MempoolImpl).frbInternalSseEncode(move: null), serializer); + (self as MempoolImpl).frbInternalSseEncode(move: null), + serializer, + ); } @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer) { + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as NoteMigrationImpl).frbInternalSseEncode(move: null), - serializer); + (self as NoteMigrationImpl).frbInternalSseEncode(move: null), + serializer, + ); } @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer) { + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_usize( - (self as TransparentScannerImpl).frbInternalSseEncode(move: null), - serializer); + (self as TransparentScannerImpl).frbInternalSseEncode(move: null), + serializer, + ); } @protected void sse_encode_StreamSink_String_Sse( - RustStreamSink<String> self, SseSerializer serializer) { + RustStreamSink<String> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13547,7 +15532,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink<DKGStatus> self, SseSerializer serializer) { + RustStreamSink<DKGStatus> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13562,7 +15549,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_log_message_Sse( - RustStreamSink<LogMessage> self, SseSerializer serializer) { + RustStreamSink<LogMessage> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13577,7 +15566,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink<MempoolMsg> self, SseSerializer serializer) { + RustStreamSink<MempoolMsg> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13592,7 +15583,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink<MigrationStatus> self, SseSerializer serializer) { + RustStreamSink<MigrationStatus> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13607,7 +15600,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink<SigningEvent> self, SseSerializer serializer) { + RustStreamSink<SigningEvent> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13622,7 +15617,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink<SigningStatus> self, SseSerializer serializer) { + RustStreamSink<SigningStatus> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13637,7 +15634,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink<SyncProgress> self, SseSerializer serializer) { + RustStreamSink<SyncProgress> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13652,7 +15651,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_voting_delegation_progress_Sse( - RustStreamSink<VotingDelegationProgress> self, SseSerializer serializer) { + RustStreamSink<VotingDelegationProgress> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13667,7 +15668,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_StreamSink_voting_vote_commit_stage_Sse( - RustStreamSink<VotingVoteCommitStage> self, SseSerializer serializer) { + RustStreamSink<VotingVoteCommitStage> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( @@ -13742,7 +15745,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer) { + AccountUpdate self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_account_update(self, serializer); } @@ -13755,7 +15760,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_category( - Category self, SseSerializer serializer) { + Category self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_category(self, serializer); } @@ -13774,7 +15781,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer) { + FrostParams self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_frost_params(self, serializer); } @@ -13787,42 +15796,54 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer) { + PlatformInt64 self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_64(self, serializer); } @protected void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer) { + MempoolTx self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_mempool_tx(self, serializer); } @protected void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer) { + NewAccount self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_new_account(self, serializer); } @protected void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer) { + PaymentOptions self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_payment_options(self, serializer); } @protected void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer) { + PcztPackage self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_pczt_package(self, serializer); } @protected void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer) { + RaptorQParams self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_raptor_q_params(self, serializer); } @@ -13835,7 +15856,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer) { + SigningEvent self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_signing_event(self, serializer); } @@ -13860,21 +15883,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer) { + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_completed_vote_display(self, serializer); } @protected void sse_encode_box_autoadd_voting_config( - VotingConfig self, SseSerializer serializer) { + VotingConfig self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_config(self, serializer); } @protected void sse_encode_box_autoadd_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer) { + VotingPirLayout self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_pir_layout(self, serializer); } @@ -13917,7 +15946,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer) { + DbAccountPreview self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.id, serializer); sse_encode_String(self.name, serializer); @@ -13986,7 +16017,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer) { + FrostSignParams self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.account, serializer); sse_encode_u_8(self.coordinator, serializer); @@ -14049,7 +16082,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_contact_match( - List<ContactMatch> self, SseSerializer serializer) { + List<ContactMatch> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14059,7 +16094,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_db_account_preview( - List<DbAccountPreview> self, SseSerializer serializer) { + List<DbAccountPreview> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14078,7 +16115,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_list_prim_u_8_strict( - List<Uint8List> self, SseSerializer serializer) { + List<Uint8List> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14106,7 +16145,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_memo_cell( - List<MemoCell> self, SseSerializer serializer) { + List<MemoCell> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14125,7 +16166,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_memo_section( - List<MemoSection> self, SseSerializer serializer) { + List<MemoSection> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14135,7 +16178,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_mempool_amount( - List<MempoolAmount> self, SseSerializer serializer) { + List<MempoolAmount> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14145,7 +16190,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_mempool_note( - List<MempoolNote> self, SseSerializer serializer) { + List<MempoolNote> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14155,7 +16202,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_plugin_info( - List<PluginInfo> self, SseSerializer serializer) { + List<PluginInfo> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14165,16 +16214,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_prim_u_32_loose( - List<int> self, SseSerializer serializer) { + List<int> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer - .putUint32List(self is Uint32List ? self : Uint32List.fromList(self)); + serializer.buffer.putUint32List( + self is Uint32List ? self : Uint32List.fromList(self), + ); } @protected void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer) { + Uint32List self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint32List(self); @@ -14182,7 +16236,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer) { + Uint64List self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); @@ -14190,16 +16246,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_prim_u_8_loose( - List<int> self, SseSerializer serializer) { + List<int> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); - serializer.buffer - .putUint8List(self is Uint8List ? self : Uint8List.fromList(self)); + serializer.buffer.putUint8List( + self is Uint8List ? self : Uint8List.fromList(self), + ); } @protected void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer) { + Uint8List self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint8List(self); @@ -14207,7 +16268,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer) { + Uint64List self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); serializer.buffer.putUint64List(self); @@ -14215,7 +16278,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_recipient( - List<Recipient> self, SseSerializer serializer) { + List<Recipient> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14225,7 +16290,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer) { + List<(String, double, bool)> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14235,7 +16302,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer) { + List<(int, double)> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14245,7 +16314,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_restored_account( - List<RestoredAccount> self, SseSerializer serializer) { + List<RestoredAccount> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14255,7 +16326,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_t_address_tx_count( - List<TAddressTxCount> self, SseSerializer serializer) { + List<TAddressTxCount> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14292,7 +16365,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_tx_output( - List<TxOutput> self, SseSerializer serializer) { + List<TxOutput> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14302,7 +16377,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_tx_plan_in( - List<TxPlanIn> self, SseSerializer serializer) { + List<TxPlanIn> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14312,7 +16389,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_tx_plan_out( - List<TxPlanOut> self, SseSerializer serializer) { + List<TxPlanOut> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14331,7 +16410,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_ballot_intent( - List<VotingBallotIntent> self, SseSerializer serializer) { + List<VotingBallotIntent> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14341,7 +16422,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_completed_vote_choice( - List<VotingCompletedVoteChoice> self, SseSerializer serializer) { + List<VotingCompletedVoteChoice> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14351,7 +16434,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_config_round( - List<VotingConfigRound> self, SseSerializer serializer) { + List<VotingConfigRound> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14361,7 +16446,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_delegation_recovery( - List<VotingDelegationRecovery> self, SseSerializer serializer) { + List<VotingDelegationRecovery> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14371,7 +16458,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_delegation_status( - List<VotingDelegationStatus> self, SseSerializer serializer) { + List<VotingDelegationStatus> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14381,7 +16470,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_encrypted_share( - List<VotingEncryptedShare> self, SseSerializer serializer) { + List<VotingEncryptedShare> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14391,7 +16482,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_next_step( - List<VotingNextStep> self, SseSerializer serializer) { + List<VotingNextStep> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14401,7 +16494,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_round_info( - List<VotingRoundInfo> self, SseSerializer serializer) { + List<VotingRoundInfo> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14411,7 +16506,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_round_session( - List<VotingRoundSession> self, SseSerializer serializer) { + List<VotingRoundSession> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14421,7 +16518,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_service_endpoint( - List<VotingServiceEndpoint> self, SseSerializer serializer) { + List<VotingServiceEndpoint> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14431,7 +16530,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_share_delegation_record( - List<VotingShareDelegationRecord> self, SseSerializer serializer) { + List<VotingShareDelegationRecord> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14441,7 +16542,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_share_payload( - List<VotingSharePayload> self, SseSerializer serializer) { + List<VotingSharePayload> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14451,7 +16554,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_share_plan_item( - List<VotingSharePlanItem> self, SseSerializer serializer) { + List<VotingSharePlanItem> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14461,7 +16566,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_share_submission_payload( - List<VotingShareSubmissionPayload> self, SseSerializer serializer) { + List<VotingShareSubmissionPayload> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14471,7 +16578,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_share_workflow( - List<VotingShareWorkflow> self, SseSerializer serializer) { + List<VotingShareWorkflow> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14481,7 +16590,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_signed_vote_commitment( - List<VotingSignedVoteCommitment> self, SseSerializer serializer) { + List<VotingSignedVoteCommitment> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14491,7 +16602,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_voting_vote_recovery( - List<VotingVoteRecovery> self, SseSerializer serializer) { + List<VotingVoteRecovery> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14501,7 +16614,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_list_zsa_holding( - List<ZsaHolding> self, SseSerializer serializer) { + List<ZsaHolding> self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_i_32(self.length, serializer); for (final item in self) { @@ -14611,7 +16726,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer) { + MigrationEvent self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs switch (self) { case MigrationEvent_SplitComplete(fee: final fee): @@ -14632,7 +16749,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer) { + MigrationStatus self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.phase, serializer); sse_encode_u_64(self.splitFees, serializer); @@ -14666,7 +16785,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer) { + OpenAliasResolution self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_recipient(self.recipients, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -14704,7 +16825,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer) { + FrostParams? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14725,7 +16848,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer) { + PlatformInt64? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14776,7 +16901,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay? self, SseSerializer serializer) { + VotingCompletedVoteDisplay? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14787,7 +16914,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_box_autoadd_voting_config( - VotingConfig? self, SseSerializer serializer) { + VotingConfig? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14798,7 +16927,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_box_autoadd_voting_pir_layout( - VotingPirLayout? self, SseSerializer serializer) { + VotingPirLayout? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14809,7 +16940,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_list_String( - List<String>? self, SseSerializer serializer) { + List<String>? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14820,7 +16953,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer) { + Uint8List? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14831,7 +16966,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_opt_list_recipient( - List<Recipient>? self, SseSerializer serializer) { + List<Recipient>? self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self != null, serializer); @@ -14842,7 +16979,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer) { + PaymentOptions self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.srcPools, serializer); sse_encode_bool(self.recipientPaysFee, serializer); @@ -14886,7 +17025,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_raptor_q_params( - RaptorQParams self, SseSerializer serializer) { + RaptorQParams self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.version, serializer); sse_encode_u_8(self.ecLevel, serializer); @@ -14895,7 +17036,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer) { + RawOpenAliasResolution self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_String(self.records, serializer); sse_encode_String(self.dnssecStatus, serializer); @@ -14924,7 +17067,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer) { + (String, double, bool) self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.$1, serializer); sse_encode_f_64(self.$2, serializer); @@ -14933,7 +17078,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer) { + (int, double) self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.$1, serializer); sse_encode_f_64(self.$2, serializer); @@ -14941,7 +17088,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer) { + RestoredAccount self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.timestamp, serializer); sse_encode_String(self.name, serializer); @@ -14953,7 +17102,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer) { + SaplingParamsStatus self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_bool(self.downloaded, serializer); } @@ -15026,7 +17177,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer) { + TAddressTxCount self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_8(self.pool, serializer); sse_encode_String(self.address, serializer); @@ -15194,7 +17347,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_ballot_intent( - VotingBallotIntent self, SseSerializer serializer) { + VotingBallotIntent self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.proposalId, serializer); sse_encode_bool(self.skipped, serializer); @@ -15203,7 +17358,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_chain_response( - VotingChainResponse self, SseSerializer serializer) { + VotingChainResponse self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_16(self.statusCode, serializer); sse_encode_String(self.body, serializer); @@ -15212,7 +17369,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_completed_vote_choice( - VotingCompletedVoteChoice self, SseSerializer serializer) { + VotingCompletedVoteChoice self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.proposalId, serializer); sse_encode_opt_box_autoadd_u_32(self.choice, serializer); @@ -15220,7 +17379,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer) { + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_voting_completed_vote_choice(self.choices, serializer); sse_encode_opt_box_autoadd_u_64(self.votedAt, serializer); @@ -15241,7 +17402,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_config_round( - VotingConfigRound self, SseSerializer serializer) { + VotingConfigRound self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_list_prim_u_8_strict(self.eaPk, serializer); @@ -15249,7 +17412,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_build( - VotingDelegationBuild self, SseSerializer serializer) { + VotingDelegationBuild self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_delegation_submission(self.submission, serializer); sse_encode_String(self.wireJson, serializer); @@ -15257,7 +17422,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_confirmation( - VotingDelegationConfirmation self, SseSerializer serializer) { + VotingDelegationConfirmation self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.txHash, serializer); sse_encode_u_32(self.vanLeafPosition, serializer); @@ -15265,7 +17432,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_progress( - VotingDelegationProgress self, SseSerializer serializer) { + VotingDelegationProgress self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs switch (self) { case VotingDelegationProgress_SelectingNotes(): @@ -15290,7 +17459,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_recovery( - VotingDelegationRecovery self, SseSerializer serializer) { + VotingDelegationRecovery self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_String(self.phase, serializer); @@ -15301,7 +17472,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_setup( - VotingDelegationSetup self, SseSerializer serializer) { + VotingDelegationSetup self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_prim_u_8_strict(self.pcztBytes, serializer); sse_encode_list_prim_u_8_strict(self.pcztSighash, serializer); @@ -15313,7 +17486,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_status( - VotingDelegationStatus self, SseSerializer serializer) { + VotingDelegationStatus self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_String(self.phase, serializer); @@ -15322,7 +17497,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_delegation_submission( - VotingDelegationSubmission self, SseSerializer serializer) { + VotingDelegationSubmission self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_prim_u_8_strict(self.proof, serializer); sse_encode_list_prim_u_8_strict(self.rk, serializer); @@ -15339,7 +17516,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_encrypted_share( - VotingEncryptedShare self, SseSerializer serializer) { + VotingEncryptedShare self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_prim_u_8_strict(self.c1, serializer); sse_encode_list_prim_u_8_strict(self.c2, serializer); @@ -15348,7 +17527,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_next_step( - VotingNextStep self, SseSerializer serializer) { + VotingNextStep self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.kind, serializer); sse_encode_u_32(self.bundleIndex, serializer); @@ -15359,7 +17540,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer) { + VotingPirLayout self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.pirDepth, serializer); sse_encode_u_32(self.tier0Layers, serializer); @@ -15369,7 +17552,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_prepared_info( - VotingPreparedInfo self, SseSerializer serializer) { + VotingPreparedInfo self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_u_32(self.bundleIndex, serializer); @@ -15380,7 +17565,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_round_info( - VotingRoundInfo self, SseSerializer serializer) { + VotingRoundInfo self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_String(self.network, serializer); @@ -15393,7 +17580,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_round_plan( - VotingRoundPlan self, SseSerializer serializer) { + VotingRoundPlan self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_bool(self.pendingRecovery, serializer); @@ -15401,21 +17590,27 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_prim_u_32_strict(self.openProposals, serializer); sse_encode_bool(self.allDecided, serializer); sse_encode_list_voting_delegation_status( - self.delegationStatuses, serializer); + self.delegationStatuses, + serializer, + ); sse_encode_bool(self.blockingRecovery, serializer); sse_encode_bool(self.blockingShareWork, serializer); sse_encode_bool(self.hotkeyBound, serializer); sse_encode_bool(self.completedVoteArtifact, serializer); sse_encode_bool(self.completedForDisplay, serializer); sse_encode_opt_box_autoadd_voting_completed_vote_display( - self.completedVoteDisplay, serializer); + self.completedVoteDisplay, + serializer, + ); sse_encode_bool(self.needsDraftSetup, serializer); sse_encode_String(self.primaryAction, serializer); } @protected void sse_encode_voting_round_recovery( - VotingRoundRecovery self, SseSerializer serializer) { + VotingRoundRecovery self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_u_32(self.bundleCount, serializer); @@ -15423,14 +17618,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_list_voting_vote_recovery(self.votes, serializer); sse_encode_list_voting_share_workflow(self.shares, serializer); sse_encode_list_voting_share_delegation_record( - self.shareDelegations, serializer); + self.shareDelegations, + serializer, + ); sse_encode_list_voting_share_delegation_record( - self.unconfirmedShareDelegations, serializer); + self.unconfirmedShareDelegations, + serializer, + ); } @protected void sse_encode_voting_round_session( - VotingRoundSession self, SseSerializer serializer) { + VotingRoundSession self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_voting_round_plan(self.plan, serializer); @@ -15440,7 +17641,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_service_endpoint( - VotingServiceEndpoint self, SseSerializer serializer) { + VotingServiceEndpoint self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.url, serializer); sse_encode_String(self.label, serializer); @@ -15448,7 +17651,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_delegation_record( - VotingShareDelegationRecord self, SseSerializer serializer) { + VotingShareDelegationRecord self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.roundId, serializer); sse_encode_u_32(self.bundleIndex, serializer); @@ -15463,7 +17668,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_payload( - VotingSharePayload self, SseSerializer serializer) { + VotingSharePayload self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_prim_u_8_strict(self.sharesHash, serializer); sse_encode_u_32(self.proposalId, serializer); @@ -15477,7 +17684,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_plan( - VotingSharePlan self, SseSerializer serializer) { + VotingSharePlan self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_share_tracking_summary(self.summary, serializer); sse_encode_opt_box_autoadd_u_64(self.nextTrackingDelaySecs, serializer); @@ -15487,7 +17696,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_plan_item( - VotingSharePlanItem self, SseSerializer serializer) { + VotingSharePlanItem self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_64(self.submitAt, serializer); sse_encode_u_32(self.targetCount, serializer); @@ -15496,7 +17707,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_submission_payload( - VotingShareSubmissionPayload self, SseSerializer serializer) { + VotingShareSubmissionPayload self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_u_32(self.proposalId, serializer); @@ -15506,7 +17719,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_tracking_summary( - VotingShareTrackingSummary self, SseSerializer serializer) { + VotingShareTrackingSummary self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_64(self.total, serializer); sse_encode_u_64(self.confirmed, serializer); @@ -15517,7 +17732,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_share_workflow( - VotingShareWorkflow self, SseSerializer serializer) { + VotingShareWorkflow self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_u_32(self.proposalId, serializer); @@ -15527,7 +17744,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_signed_vote_commitment( - VotingSignedVoteCommitment self, SseSerializer serializer) { + VotingSignedVoteCommitment self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.proposalId, serializer); sse_encode_u_32(self.choice, serializer); @@ -15544,7 +17763,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_tree_vote_confirmation( - VotingTreeVoteConfirmation self, SseSerializer serializer) { + VotingTreeVoteConfirmation self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_64(self.vcTreePosition, serializer); sse_encode_opt_box_autoadd_u_32(self.vanLeafPosition, serializer); @@ -15552,7 +17773,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_van_witness( - VotingVanWitness self, SseSerializer serializer) { + VotingVanWitness self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_list_list_prim_u_8_strict(self.authPath, serializer); sse_encode_u_32(self.position, serializer); @@ -15561,36 +17784,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_commit_stage( - VotingVoteCommitStage self, SseSerializer serializer) { + VotingVoteCommitStage self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs switch (self) { case VotingVoteCommitStage_ProofStarting( - proposalId: final proposalId, - bundleIndex: final bundleIndex - ): + proposalId: final proposalId, + bundleIndex: final bundleIndex, + ): sse_encode_i_32(0, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_u_32(bundleIndex, serializer); case VotingVoteCommitStage_ProofProgress( - proposalId: final proposalId, - bundleIndex: final bundleIndex, - progress: final progress - ): + proposalId: final proposalId, + bundleIndex: final bundleIndex, + progress: final progress, + ): sse_encode_i_32(1, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_u_32(bundleIndex, serializer); sse_encode_f_64(progress, serializer); case VotingVoteCommitStage_SharePayloadsBuilding( - proposalId: final proposalId, - bundleIndex: final bundleIndex - ): + proposalId: final proposalId, + bundleIndex: final bundleIndex, + ): sse_encode_i_32(2, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_u_32(bundleIndex, serializer); case VotingVoteCommitStage_Signing( - proposalId: final proposalId, - bundleIndex: final bundleIndex - ): + proposalId: final proposalId, + bundleIndex: final bundleIndex, + ): sse_encode_i_32(3, serializer); sse_encode_u_32(proposalId, serializer); sse_encode_u_32(bundleIndex, serializer); @@ -15599,7 +17824,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_commitments( - VotingVoteCommitments self, SseSerializer serializer) { + VotingVoteCommitments self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_list_voting_signed_vote_commitment(self.commitments, serializer); @@ -15607,7 +17834,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_confirmation( - VotingVoteConfirmation self, SseSerializer serializer) { + VotingVoteConfirmation self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.txHash, serializer); sse_encode_u_32(self.vanLeafPosition, serializer); @@ -15616,7 +17845,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_payloads( - VotingVotePayloads self, SseSerializer serializer) { + VotingVotePayloads self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_voting_vote_submission(self.submission, serializer); sse_encode_list_voting_share_payload(self.sharePayloads, serializer); @@ -15624,7 +17855,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_recovery( - VotingVoteRecovery self, SseSerializer serializer) { + VotingVoteRecovery self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_u_32(self.bundleIndex, serializer); sse_encode_u_32(self.proposalId, serializer); @@ -15638,7 +17871,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @protected void sse_encode_voting_vote_submission( - VotingVoteSubmission self, SseSerializer serializer) { + VotingVoteSubmission self, + SseSerializer serializer, + ) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String(self.voteRoundId, serializer); sse_encode_u_32(self.proposalId, serializer); @@ -15669,11 +17904,11 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { class DartVaultImpl extends RustOpaque implements DartVault { // Not to be used by end users DartVaultImpl.frbInternalDcoDecode(List<dynamic> wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users DartVaultImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( rustArcIncrementStrongCount: @@ -15684,75 +17919,82 @@ class DartVaultImpl extends RustOpaque implements DartVault { RustLib.instance.api.rust_arc_decrement_strong_count_DartVaultPtr, ); - Future<List<RestoredAccount>> recover( - {required List<int> vaultBytes, required String masterPassword}) => - RustLib.instance.api.crateApiVaultDartVaultRecover( - that: this, vaultBytes: vaultBytes, masterPassword: masterPassword); - - Future<List<RestoredAccount>> recoverWithPrf( - {required List<int> vaultBytes, - required String deviceIdStr, - required List<int> prfOutput}) => - RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf( - that: this, - vaultBytes: vaultBytes, - deviceIdStr: deviceIdStr, - prfOutput: prfOutput); - - Future<void> registerDevice( - {required List<int> initBytes, - required String masterPassword, - required String deviceIdStr, - required List<int> prfOutput}) => - RustLib.instance.api.crateApiVaultDartVaultRegisterDevice( - that: this, - initBytes: initBytes, - masterPassword: masterPassword, - deviceIdStr: deviceIdStr, - prfOutput: prfOutput); - - Future<Uint8List> setMasterPassword( - {String? oldPassword, - required String newPassword, - Uint8List? oldBytes}) => - RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword( - that: this, - oldPassword: oldPassword, - newPassword: newPassword, - oldBytes: oldBytes); - - Future<void> storeAccount( - {required int timestamp, - required String name, - required String seed, - required int aindex, - required bool useInternal, - required int birthHeight, - required List<int> pk}) => - RustLib.instance.api.crateApiVaultDartVaultStoreAccount( - that: this, - timestamp: timestamp, - name: name, - seed: seed, - aindex: aindex, - useInternal: useInternal, - birthHeight: birthHeight, - pk: pk); - - Future<void> test() => RustLib.instance.api.crateApiVaultDartVaultTest( - that: this, - ); + Future<List<RestoredAccount>> recover({ + required List<int> vaultBytes, + required String masterPassword, + }) => RustLib.instance.api.crateApiVaultDartVaultRecover( + that: this, + vaultBytes: vaultBytes, + masterPassword: masterPassword, + ); + + Future<List<RestoredAccount>> recoverWithPrf({ + required List<int> vaultBytes, + required String deviceIdStr, + required List<int> prfOutput, + }) => RustLib.instance.api.crateApiVaultDartVaultRecoverWithPrf( + that: this, + vaultBytes: vaultBytes, + deviceIdStr: deviceIdStr, + prfOutput: prfOutput, + ); + + Future<void> registerDevice({ + required List<int> initBytes, + required String masterPassword, + required String deviceIdStr, + required List<int> prfOutput, + }) => RustLib.instance.api.crateApiVaultDartVaultRegisterDevice( + that: this, + initBytes: initBytes, + masterPassword: masterPassword, + deviceIdStr: deviceIdStr, + prfOutput: prfOutput, + ); + + Future<Uint8List> setMasterPassword({ + String? oldPassword, + required String newPassword, + Uint8List? oldBytes, + }) => RustLib.instance.api.crateApiVaultDartVaultSetMasterPassword( + that: this, + oldPassword: oldPassword, + newPassword: newPassword, + oldBytes: oldBytes, + ); + + Future<void> storeAccount({ + required int timestamp, + required String name, + required String seed, + required int aindex, + required bool useInternal, + required int birthHeight, + required List<int> pk, + }) => RustLib.instance.api.crateApiVaultDartVaultStoreAccount( + that: this, + timestamp: timestamp, + name: name, + seed: seed, + aindex: aindex, + useInternal: useInternal, + birthHeight: birthHeight, + pk: pk, + ); + + Future<void> test() => + RustLib.instance.api.crateApiVaultDartVaultTest(that: this); } @sealed class MempoolImpl extends RustOpaque implements Mempool { // Not to be used by end users MempoolImpl.frbInternalDcoDecode(List<dynamic> wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users MempoolImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( rustArcIncrementStrongCount: @@ -15763,9 +18005,8 @@ class MempoolImpl extends RustOpaque implements Mempool { RustLib.instance.api.rust_arc_decrement_strong_count_MempoolPtr, ); - Future<void> cancel() => RustLib.instance.api.crateApiMempoolMempoolCancel( - that: this, - ); + Future<void> cancel() => + RustLib.instance.api.crateApiMempoolMempoolCancel(that: this); Stream<MempoolMsg> run({required Coin c}) => RustLib.instance.api.crateApiMempoolMempoolRun(that: this, c: c); @@ -15775,11 +18016,11 @@ class MempoolImpl extends RustOpaque implements Mempool { class NoteMigrationImpl extends RustOpaque implements NoteMigration { // Not to be used by end users NoteMigrationImpl.frbInternalDcoDecode(List<dynamic> wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users NoteMigrationImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( rustArcIncrementStrongCount: @@ -15791,13 +18032,14 @@ class NoteMigrationImpl extends RustOpaque implements NoteMigration { ); Future<void> cancel() => - RustLib.instance.api.crateApiMigrateNoteMigrationCancel( - that: this, - ); + RustLib.instance.api.crateApiMigrateNoteMigrationCancel(that: this); Stream<MigrationStatus> run({required Coin c, required BigInt meanDelayMs}) => RustLib.instance.api.crateApiMigrateNoteMigrationRun( - that: this, c: c, meanDelayMs: meanDelayMs); + that: this, + c: c, + meanDelayMs: meanDelayMs, + ); /// Supplies a height observed by the shared Dart block-height service. void updateHeight({required int height}) => RustLib.instance.api @@ -15808,12 +18050,13 @@ class NoteMigrationImpl extends RustOpaque implements NoteMigration { class TransparentScannerImpl extends RustOpaque implements TransparentScanner { // Not to be used by end users TransparentScannerImpl.frbInternalDcoDecode(List<dynamic> wire) - : super.frbInternalDcoDecode(wire, _kStaticData); + : super.frbInternalDcoDecode(wire, _kStaticData); // Not to be used by end users TransparentScannerImpl.frbInternalSseDecode( - BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + BigInt ptr, + int externalSizeOnNative, + ) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); static final _kStaticData = RustArcStaticData( rustArcIncrementStrongCount: @@ -15821,16 +18064,22 @@ class TransparentScannerImpl extends RustOpaque implements TransparentScanner { rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_TransparentScanner, rustArcDecrementStrongCountPtr: RustLib - .instance.api.rust_arc_decrement_strong_count_TransparentScannerPtr, + .instance + .api + .rust_arc_decrement_strong_count_TransparentScannerPtr, ); Future<void> cancel() => - RustLib.instance.api.crateApiSweepTransparentScannerCancel( - that: this, - ); - - Stream<String> run( - {required int endHeight, required int gapLimit, required Coin c}) => - RustLib.instance.api.crateApiSweepTransparentScannerRun( - that: this, endHeight: endHeight, gapLimit: gapLimit, c: c); + RustLib.instance.api.crateApiSweepTransparentScannerCancel(that: this); + + Stream<String> run({ + required int endHeight, + required int gapLimit, + required Coin c, + }) => RustLib.instance.api.crateApiSweepTransparentScannerRun( + that: this, + endHeight: endHeight, + gapLimit: gapLimit, + c: c, + ); } diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 124af5f41..baee98ddf 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field @@ -11,6 +11,7 @@ import 'api/frost.dart'; import 'api/init.dart'; import 'api/issuance.dart'; import 'api/key.dart'; +import 'api/ledger.dart'; import 'api/mempool.dart'; import 'api/migrate.dart'; import 'api/network.dart'; @@ -42,95 +43,117 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { required super.portManager, }); - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_DartVaultPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_MempoolPtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; + get rust_arc_decrement_strong_count_TransparentScannerPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); + + @protected + FutureOr<Uint8List> Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); @protected FutureOr<void> Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw); + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw, + ); @protected Object dco_decode_DartOpaque(dynamic raw); @protected DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected RustStreamSink<String> dco_decode_StreamSink_String_Sse(dynamic raw); @@ -146,27 +169,31 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected RustStreamSink<MigrationStatus> dco_decode_StreamSink_migration_status_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SigningEvent> dco_decode_StreamSink_signing_event_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SigningStatus> dco_decode_StreamSink_signing_status_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SyncProgress> dco_decode_StreamSink_sync_progress_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<VotingDelegationProgress> - dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); @protected RustStreamSink<VotingVoteCommitStage> - dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -239,7 +266,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay - dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); @protected VotingConfig dco_decode_box_autoadd_voting_config(dynamic raw); @@ -360,7 +387,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw); + dynamic raw, + ); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -397,22 +425,26 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingCompletedVoteChoice> dco_decode_list_voting_completed_vote_choice( - dynamic raw); + dynamic raw, + ); @protected List<VotingConfigRound> dco_decode_list_voting_config_round(dynamic raw); @protected List<VotingDelegationRecovery> dco_decode_list_voting_delegation_recovery( - dynamic raw); + dynamic raw, + ); @protected List<VotingDelegationStatus> dco_decode_list_voting_delegation_status( - dynamic raw); + dynamic raw, + ); @protected List<VotingEncryptedShare> dco_decode_list_voting_encrypted_share( - dynamic raw); + dynamic raw, + ); @protected List<VotingNextStep> dco_decode_list_voting_next_step(dynamic raw); @@ -425,11 +457,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( - dynamic raw); + dynamic raw, + ); @protected List<VotingShareDelegationRecord> - dco_decode_list_voting_share_delegation_record(dynamic raw); + dco_decode_list_voting_share_delegation_record(dynamic raw); @protected List<VotingSharePayload> dco_decode_list_voting_share_payload(dynamic raw); @@ -439,14 +472,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingShareSubmissionPayload> - dco_decode_list_voting_share_submission_payload(dynamic raw); + dco_decode_list_voting_share_submission_payload(dynamic raw); @protected List<VotingShareWorkflow> dco_decode_list_voting_share_workflow(dynamic raw); @protected List<VotingSignedVoteCommitment> - dco_decode_list_voting_signed_vote_commitment(dynamic raw); + dco_decode_list_voting_signed_vote_commitment(dynamic raw); @protected List<VotingVoteRecovery> dco_decode_list_voting_vote_recovery(dynamic raw); @@ -528,7 +561,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay? - dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); @protected VotingConfig? dco_decode_opt_box_autoadd_voting_config(dynamic raw); @@ -655,11 +688,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( - dynamic raw); + dynamic raw, + ); @protected VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( - dynamic raw); + dynamic raw, + ); @protected VotingConfig dco_decode_voting_config(dynamic raw); @@ -672,7 +707,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( - dynamic raw); + dynamic raw, + ); @protected VotingDelegationProgress dco_decode_voting_delegation_progress(dynamic raw); @@ -688,7 +724,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( - dynamic raw); + dynamic raw, + ); @protected VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); @@ -719,7 +756,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingShareDelegationRecord dco_decode_voting_share_delegation_record( - dynamic raw); + dynamic raw, + ); @protected VotingSharePayload dco_decode_voting_share_payload(dynamic raw); @@ -732,22 +770,26 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( - dynamic raw); + dynamic raw, + ); @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( - dynamic raw); + dynamic raw, + ); @protected VotingShareWorkflow dco_decode_voting_share_workflow(dynamic raw); @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( - dynamic raw); + dynamic raw, + ); @protected VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( - dynamic raw); + dynamic raw, + ); @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); @@ -778,113 +820,136 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected RustStreamSink<String> sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<DKGStatus> sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<LogMessage> sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<MempoolMsg> sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<MigrationStatus> sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SigningEvent> sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SigningStatus> sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SyncProgress> sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<VotingDelegationProgress> - sse_decode_StreamSink_voting_delegation_progress_Sse( - SseDeserializer deserializer); + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer, + ); @protected RustStreamSink<VotingVoteCommitStage> - sse_decode_StreamSink_voting_vote_commit_stage_Sse( - SseDeserializer deserializer); + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer, + ); @protected String sse_decode_String(SseDeserializer deserializer); @@ -903,7 +968,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -934,21 +1000,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -961,16 +1030,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay - sse_decode_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer); + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ); @protected VotingConfig sse_decode_box_autoadd_voting_config( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Category sse_decode_category(SseDeserializer deserializer); @@ -1028,18 +1100,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<ContactMatch> sse_decode_list_contact_match( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<DbAccountPreview> sse_decode_list_db_account_preview( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<Folder> sse_decode_list_folder(SseDeserializer deserializer); @protected List<Uint8List> sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<LWDInfo> sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -1058,7 +1133,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<MempoolAmount> sse_decode_list_mempool_amount( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<MempoolNote> sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -1089,19 +1165,23 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<RestoredAccount> sse_decode_list_restored_account( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<TAddressTxCount> sse_decode_list_t_address_tx_count( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<Tx> sse_decode_list_tx(SseDeserializer deserializer); @@ -1126,74 +1206,85 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingBallotIntent> sse_decode_list_voting_ballot_intent( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingCompletedVoteChoice> sse_decode_list_voting_completed_vote_choice( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingConfigRound> sse_decode_list_voting_config_round( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingDelegationRecovery> sse_decode_list_voting_delegation_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingDelegationStatus> sse_decode_list_voting_delegation_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingEncryptedShare> sse_decode_list_voting_encrypted_share( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingNextStep> sse_decode_list_voting_next_step( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingRoundInfo> sse_decode_list_voting_round_info( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingRoundSession> sse_decode_list_voting_round_session( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingShareDelegationRecord> - sse_decode_list_voting_share_delegation_record( - SseDeserializer deserializer); + sse_decode_list_voting_share_delegation_record(SseDeserializer deserializer); @protected List<VotingSharePayload> sse_decode_list_voting_share_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingSharePlanItem> sse_decode_list_voting_share_plan_item( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingShareSubmissionPayload> - sse_decode_list_voting_share_submission_payload( - SseDeserializer deserializer); + sse_decode_list_voting_share_submission_payload(SseDeserializer deserializer); @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingSignedVoteCommitment> - sse_decode_list_voting_signed_vote_commitment( - SseDeserializer deserializer); + sse_decode_list_voting_signed_vote_commitment(SseDeserializer deserializer); @protected List<VotingVoteRecovery> sse_decode_list_voting_vote_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<ZsaHolding> sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1239,7 +1330,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -1252,7 +1344,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -1274,16 +1367,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay? - sse_decode_opt_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer); + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ); @protected VotingConfig? sse_decode_opt_box_autoadd_voting_config( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<String>? sse_decode_opt_list_String(SseDeserializer deserializer); @@ -1311,7 +1407,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -1321,7 +1418,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -1331,7 +1429,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -1401,58 +1500,71 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingBallotIntent sse_decode_voting_ballot_intent( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingChainResponse sse_decode_voting_chain_response( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingConfig sse_decode_voting_config(SseDeserializer deserializer); @protected VotingConfigRound sse_decode_voting_config_round( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationBuild sse_decode_voting_delegation_build( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationProgress sse_decode_voting_delegation_progress( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationRecovery sse_decode_voting_delegation_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationSetup sse_decode_voting_delegation_setup( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationStatus sse_decode_voting_delegation_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingEncryptedShare sse_decode_voting_encrypted_share( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingNextStep sse_decode_voting_next_step(SseDeserializer deserializer); @@ -1462,7 +1574,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingPreparedInfo sse_decode_voting_prepared_info( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingRoundInfo sse_decode_voting_round_info(SseDeserializer deserializer); @@ -1472,197 +1585,271 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingRoundRecovery sse_decode_voting_round_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingRoundSession sse_decode_voting_round_session( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareDelegationRecord sse_decode_voting_share_delegation_record( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSharePayload sse_decode_voting_share_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer); @protected VotingSharePlanItem sse_decode_voting_share_plan_item( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareWorkflow sse_decode_voting_share_workflow( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); @protected VotingVoteCommitStage sse_decode_voting_vote_commit_stage( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteCommitments sse_decode_voting_vote_commitments( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteConfirmation sse_decode_voting_vote_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVotePayloads sse_decode_voting_vote_payloads( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteRecovery sse_decode_voting_vote_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteSubmission sse_decode_voting_vote_submission( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer); + AnyhowException self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + FutureOr<Uint8List> Function(Uint8List) self, + SseSerializer serializer, + ); @protected void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr<void> Function(Uint8List) self, SseSerializer serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr<void> Function(Uint8List) self, + SseSerializer serializer, + ); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_String_Sse( - RustStreamSink<String> self, SseSerializer serializer); + RustStreamSink<String> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink<DKGStatus> self, SseSerializer serializer); + RustStreamSink<DKGStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_log_message_Sse( - RustStreamSink<LogMessage> self, SseSerializer serializer); + RustStreamSink<LogMessage> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink<MempoolMsg> self, SseSerializer serializer); + RustStreamSink<MempoolMsg> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink<MigrationStatus> self, SseSerializer serializer); + RustStreamSink<MigrationStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink<SigningEvent> self, SseSerializer serializer); + RustStreamSink<SigningEvent> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink<SigningStatus> self, SseSerializer serializer); + RustStreamSink<SigningStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink<SyncProgress> self, SseSerializer serializer); + RustStreamSink<SyncProgress> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_voting_delegation_progress_Sse( - RustStreamSink<VotingDelegationProgress> self, SseSerializer serializer); + RustStreamSink<VotingDelegationProgress> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_voting_vote_commit_stage_Sse( - RustStreamSink<VotingVoteCommitStage> self, SseSerializer serializer); + RustStreamSink<VotingVoteCommitStage> self, + SseSerializer serializer, + ); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1681,7 +1868,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer); + AccountUpdate self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1697,41 +1886,57 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer); + FrostParams self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer); + PlatformInt64 self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer); + MempoolTx self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer); + NewAccount self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer); + PaymentOptions self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer); + PcztPackage self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer); + RaptorQParams self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer); + SigningEvent self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1744,15 +1949,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer); + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_voting_config( - VotingConfig self, SseSerializer serializer); + VotingConfig self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer); + VotingPirLayout self, + SseSerializer serializer, + ); @protected void sse_encode_category(Category self, SseSerializer serializer); @@ -1768,7 +1979,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer); + DbAccountPreview self, + SseSerializer serializer, + ); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1787,7 +2000,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer); + FrostSignParams self, + SseSerializer serializer, + ); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1812,18 +2027,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_contact_match( - List<ContactMatch> self, SseSerializer serializer); + List<ContactMatch> self, + SseSerializer serializer, + ); @protected void sse_encode_list_db_account_preview( - List<DbAccountPreview> self, SseSerializer serializer); + List<DbAccountPreview> self, + SseSerializer serializer, + ); @protected void sse_encode_list_folder(List<Folder> self, SseSerializer serializer); @protected void sse_encode_list_list_prim_u_8_strict( - List<Uint8List> self, SseSerializer serializer); + List<Uint8List> self, + SseSerializer serializer, + ); @protected void sse_encode_list_lwd_info(List<LWDInfo> self, SseSerializer serializer); @@ -1839,62 +2060,90 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_memo_section( - List<MemoSection> self, SseSerializer serializer); + List<MemoSection> self, + SseSerializer serializer, + ); @protected void sse_encode_list_mempool_amount( - List<MempoolAmount> self, SseSerializer serializer); + List<MempoolAmount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_mempool_note( - List<MempoolNote> self, SseSerializer serializer); + List<MempoolNote> self, + SseSerializer serializer, + ); @protected void sse_encode_list_plugin_info( - List<PluginInfo> self, SseSerializer serializer); + List<PluginInfo> self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_32_loose( - List<int> self, SseSerializer serializer); + List<int> self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer); + Uint32List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer); + Uint64List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer); + Uint8List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer); + Uint64List self, + SseSerializer serializer, + ); @protected void sse_encode_list_recipient( - List<Recipient> self, SseSerializer serializer); + List<Recipient> self, + SseSerializer serializer, + ); @protected void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer); + List<(String, double, bool)> self, + SseSerializer serializer, + ); @protected void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer); + List<(int, double)> self, + SseSerializer serializer, + ); @protected void sse_encode_list_restored_account( - List<RestoredAccount> self, SseSerializer serializer); + List<RestoredAccount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_t_address_tx_count( - List<TAddressTxCount> self, SseSerializer serializer); + List<TAddressTxCount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx(List<Tx> self, SseSerializer serializer); @@ -1910,86 +2159,126 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_tx_plan_in( - List<TxPlanIn> self, SseSerializer serializer); + List<TxPlanIn> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx_plan_out( - List<TxPlanOut> self, SseSerializer serializer); + List<TxPlanOut> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx_spend(List<TxSpend> self, SseSerializer serializer); @protected void sse_encode_list_voting_ballot_intent( - List<VotingBallotIntent> self, SseSerializer serializer); + List<VotingBallotIntent> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_completed_vote_choice( - List<VotingCompletedVoteChoice> self, SseSerializer serializer); + List<VotingCompletedVoteChoice> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_config_round( - List<VotingConfigRound> self, SseSerializer serializer); + List<VotingConfigRound> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_delegation_recovery( - List<VotingDelegationRecovery> self, SseSerializer serializer); + List<VotingDelegationRecovery> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_delegation_status( - List<VotingDelegationStatus> self, SseSerializer serializer); + List<VotingDelegationStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_encrypted_share( - List<VotingEncryptedShare> self, SseSerializer serializer); + List<VotingEncryptedShare> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_next_step( - List<VotingNextStep> self, SseSerializer serializer); + List<VotingNextStep> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_round_info( - List<VotingRoundInfo> self, SseSerializer serializer); + List<VotingRoundInfo> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_round_session( - List<VotingRoundSession> self, SseSerializer serializer); + List<VotingRoundSession> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_service_endpoint( - List<VotingServiceEndpoint> self, SseSerializer serializer); + List<VotingServiceEndpoint> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_delegation_record( - List<VotingShareDelegationRecord> self, SseSerializer serializer); + List<VotingShareDelegationRecord> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_payload( - List<VotingSharePayload> self, SseSerializer serializer); + List<VotingSharePayload> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_plan_item( - List<VotingSharePlanItem> self, SseSerializer serializer); + List<VotingSharePlanItem> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_submission_payload( - List<VotingShareSubmissionPayload> self, SseSerializer serializer); + List<VotingShareSubmissionPayload> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_workflow( - List<VotingShareWorkflow> self, SseSerializer serializer); + List<VotingShareWorkflow> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_signed_vote_commitment( - List<VotingSignedVoteCommitment> self, SseSerializer serializer); + List<VotingSignedVoteCommitment> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_vote_recovery( - List<VotingVoteRecovery> self, SseSerializer serializer); + List<VotingVoteRecovery> self, + SseSerializer serializer, + ); @protected void sse_encode_list_zsa_holding( - List<ZsaHolding> self, SseSerializer serializer); + List<ZsaHolding> self, + SseSerializer serializer, + ); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -2023,18 +2312,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer); + MigrationEvent self, + SseSerializer serializer, + ); @protected void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer); + MigrationStatus self, + SseSerializer serializer, + ); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer); + OpenAliasResolution self, + SseSerializer serializer, + ); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -2047,14 +2342,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer); + FrostParams? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer); + PlatformInt64? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -2070,30 +2369,42 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_opt_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay? self, SseSerializer serializer); + VotingCompletedVoteDisplay? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_voting_config( - VotingConfig? self, SseSerializer serializer); + VotingConfig? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_voting_pir_layout( - VotingPirLayout? self, SseSerializer serializer); + VotingPirLayout? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_list_String(List<String>? self, SseSerializer serializer); @protected void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer); + Uint8List? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_list_recipient( - List<Recipient>? self, SseSerializer serializer); + List<Recipient>? self, + SseSerializer serializer, + ); @protected void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer); + PaymentOptions self, + SseSerializer serializer, + ); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -2109,7 +2420,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer); + RawOpenAliasResolution self, + SseSerializer serializer, + ); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -2119,19 +2432,27 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer); + (String, double, bool) self, + SseSerializer serializer, + ); @protected void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer); + (int, double) self, + SseSerializer serializer, + ); @protected void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer); + RestoredAccount self, + SseSerializer serializer, + ); @protected void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer); + SaplingParamsStatus self, + SseSerializer serializer, + ); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -2150,7 +2471,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer); + TAddressTxCount self, + SseSerializer serializer, + ); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -2202,154 +2525,228 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_voting_ballot_intent( - VotingBallotIntent self, SseSerializer serializer); + VotingBallotIntent self, + SseSerializer serializer, + ); @protected void sse_encode_voting_chain_response( - VotingChainResponse self, SseSerializer serializer); + VotingChainResponse self, + SseSerializer serializer, + ); @protected void sse_encode_voting_completed_vote_choice( - VotingCompletedVoteChoice self, SseSerializer serializer); + VotingCompletedVoteChoice self, + SseSerializer serializer, + ); @protected void sse_encode_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer); + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ); @protected void sse_encode_voting_config(VotingConfig self, SseSerializer serializer); @protected void sse_encode_voting_config_round( - VotingConfigRound self, SseSerializer serializer); + VotingConfigRound self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_build( - VotingDelegationBuild self, SseSerializer serializer); + VotingDelegationBuild self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_confirmation( - VotingDelegationConfirmation self, SseSerializer serializer); + VotingDelegationConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_progress( - VotingDelegationProgress self, SseSerializer serializer); + VotingDelegationProgress self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_recovery( - VotingDelegationRecovery self, SseSerializer serializer); + VotingDelegationRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_setup( - VotingDelegationSetup self, SseSerializer serializer); + VotingDelegationSetup self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_status( - VotingDelegationStatus self, SseSerializer serializer); + VotingDelegationStatus self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_submission( - VotingDelegationSubmission self, SseSerializer serializer); + VotingDelegationSubmission self, + SseSerializer serializer, + ); @protected void sse_encode_voting_encrypted_share( - VotingEncryptedShare self, SseSerializer serializer); + VotingEncryptedShare self, + SseSerializer serializer, + ); @protected void sse_encode_voting_next_step( - VotingNextStep self, SseSerializer serializer); + VotingNextStep self, + SseSerializer serializer, + ); @protected void sse_encode_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer); + VotingPirLayout self, + SseSerializer serializer, + ); @protected void sse_encode_voting_prepared_info( - VotingPreparedInfo self, SseSerializer serializer); + VotingPreparedInfo self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_info( - VotingRoundInfo self, SseSerializer serializer); + VotingRoundInfo self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_plan( - VotingRoundPlan self, SseSerializer serializer); + VotingRoundPlan self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_recovery( - VotingRoundRecovery self, SseSerializer serializer); + VotingRoundRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_session( - VotingRoundSession self, SseSerializer serializer); + VotingRoundSession self, + SseSerializer serializer, + ); @protected void sse_encode_voting_service_endpoint( - VotingServiceEndpoint self, SseSerializer serializer); + VotingServiceEndpoint self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_delegation_record( - VotingShareDelegationRecord self, SseSerializer serializer); + VotingShareDelegationRecord self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_payload( - VotingSharePayload self, SseSerializer serializer); + VotingSharePayload self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_plan( - VotingSharePlan self, SseSerializer serializer); + VotingSharePlan self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_plan_item( - VotingSharePlanItem self, SseSerializer serializer); + VotingSharePlanItem self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_submission_payload( - VotingShareSubmissionPayload self, SseSerializer serializer); + VotingShareSubmissionPayload self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_tracking_summary( - VotingShareTrackingSummary self, SseSerializer serializer); + VotingShareTrackingSummary self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_workflow( - VotingShareWorkflow self, SseSerializer serializer); + VotingShareWorkflow self, + SseSerializer serializer, + ); @protected void sse_encode_voting_signed_vote_commitment( - VotingSignedVoteCommitment self, SseSerializer serializer); + VotingSignedVoteCommitment self, + SseSerializer serializer, + ); @protected void sse_encode_voting_tree_vote_confirmation( - VotingTreeVoteConfirmation self, SseSerializer serializer); + VotingTreeVoteConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_van_witness( - VotingVanWitness self, SseSerializer serializer); + VotingVanWitness self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_commit_stage( - VotingVoteCommitStage self, SseSerializer serializer); + VotingVoteCommitStage self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_commitments( - VotingVoteCommitments self, SseSerializer serializer); + VotingVoteCommitments self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_confirmation( - VotingVoteConfirmation self, SseSerializer serializer); + VotingVoteConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_payloads( - VotingVotePayloads self, SseSerializer serializer); + VotingVotePayloads self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_recovery( - VotingVoteRecovery self, SseSerializer serializer); + VotingVoteRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_submission( - VotingVoteSubmission self, SseSerializer serializer); + VotingVoteSubmission self, + SseSerializer serializer, + ); @protected void sse_encode_zsa_holding(ZsaHolding self, SseSerializer serializer); @@ -2363,14 +2760,14 @@ class RustLibWire implements BaseWire { /// Holds the symbol lookup function. final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) - _lookup; + _lookup; /// The symbols are looked up in [dynamicLibrary]. RustLibWire(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; + : _lookup = dynamicLibrary.lookup; void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -2380,13 +2777,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault'); + 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault', + ); late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault = _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( @@ -2396,13 +2794,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault'); + 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault', + ); late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault = _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVaultPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -2412,13 +2811,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool'); + 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool', + ); late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool = _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( @@ -2428,13 +2828,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool'); + 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool', + ); late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool = _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempoolPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -2444,13 +2845,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration'); + 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration', + ); late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration = _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( @@ -2460,13 +2862,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration'); + 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration', + ); late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration = _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigrationPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -2476,13 +2879,14 @@ class RustLibWire implements BaseWire { late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner'); + 'frbgen_zkool_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner', + ); late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner = _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( ffi.Pointer<ffi.Void> ptr, ) { return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( @@ -2492,7 +2896,8 @@ class RustLibWire implements BaseWire { late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>( - 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner'); + 'frbgen_zkool_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner', + ); late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner = _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScannerPtr .asFunction<void Function(ffi.Pointer<ffi.Void>)>(); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 02a68e7c4..233dbc5eb 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field @@ -14,6 +14,7 @@ import 'api/frost.dart'; import 'api/init.dart'; import 'api/issuance.dart'; import 'api/key.dart'; +import 'api/ledger.dart'; import 'api/mempool.dart'; import 'api/migrate.dart'; import 'api/network.dart'; @@ -44,95 +45,117 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { required super.portManager, }); - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DartVaultPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_DartVaultPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MempoolPtr => wire + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_MempoolPtr => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_NoteMigrationPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; + get rust_arc_decrement_strong_count_NoteMigrationPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration; CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_TransparentScannerPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; + get rust_arc_decrement_strong_count_TransparentScannerPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner; @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @protected DartVault - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected Mempool - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected NoteMigration - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected Mempool - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected DartVault - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected NoteMigration - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); + + @protected + FutureOr<Uint8List> Function(Uint8List) + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + dynamic raw, + ); @protected FutureOr<void> Function(Uint8List) - dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - dynamic raw); + dco_decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + dynamic raw, + ); @protected Object dco_decode_DartOpaque(dynamic raw); @protected DartVault - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + dynamic raw, + ); @protected Mempool - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + dynamic raw, + ); @protected NoteMigration - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + dynamic raw, + ); @protected TransparentScanner - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - dynamic raw); + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + dynamic raw, + ); @protected RustStreamSink<String> dco_decode_StreamSink_String_Sse(dynamic raw); @@ -148,27 +171,31 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected RustStreamSink<MigrationStatus> dco_decode_StreamSink_migration_status_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SigningEvent> dco_decode_StreamSink_signing_event_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SigningStatus> dco_decode_StreamSink_signing_status_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<SyncProgress> dco_decode_StreamSink_sync_progress_Sse( - dynamic raw); + dynamic raw, + ); @protected RustStreamSink<VotingDelegationProgress> - dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); + dco_decode_StreamSink_voting_delegation_progress_Sse(dynamic raw); @protected RustStreamSink<VotingVoteCommitStage> - dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); + dco_decode_StreamSink_voting_vote_commit_stage_Sse(dynamic raw); @protected String dco_decode_String(dynamic raw); @@ -241,7 +268,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay - dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); + dco_decode_box_autoadd_voting_completed_vote_display(dynamic raw); @protected VotingConfig dco_decode_box_autoadd_voting_config(dynamic raw); @@ -362,7 +389,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<(String, double, bool)> dco_decode_list_record_string_f_64_bool( - dynamic raw); + dynamic raw, + ); @protected List<(int, double)> dco_decode_list_record_u_32_f_64(dynamic raw); @@ -399,22 +427,26 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingCompletedVoteChoice> dco_decode_list_voting_completed_vote_choice( - dynamic raw); + dynamic raw, + ); @protected List<VotingConfigRound> dco_decode_list_voting_config_round(dynamic raw); @protected List<VotingDelegationRecovery> dco_decode_list_voting_delegation_recovery( - dynamic raw); + dynamic raw, + ); @protected List<VotingDelegationStatus> dco_decode_list_voting_delegation_status( - dynamic raw); + dynamic raw, + ); @protected List<VotingEncryptedShare> dco_decode_list_voting_encrypted_share( - dynamic raw); + dynamic raw, + ); @protected List<VotingNextStep> dco_decode_list_voting_next_step(dynamic raw); @@ -427,11 +459,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingServiceEndpoint> dco_decode_list_voting_service_endpoint( - dynamic raw); + dynamic raw, + ); @protected List<VotingShareDelegationRecord> - dco_decode_list_voting_share_delegation_record(dynamic raw); + dco_decode_list_voting_share_delegation_record(dynamic raw); @protected List<VotingSharePayload> dco_decode_list_voting_share_payload(dynamic raw); @@ -441,14 +474,14 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingShareSubmissionPayload> - dco_decode_list_voting_share_submission_payload(dynamic raw); + dco_decode_list_voting_share_submission_payload(dynamic raw); @protected List<VotingShareWorkflow> dco_decode_list_voting_share_workflow(dynamic raw); @protected List<VotingSignedVoteCommitment> - dco_decode_list_voting_signed_vote_commitment(dynamic raw); + dco_decode_list_voting_signed_vote_commitment(dynamic raw); @protected List<VotingVoteRecovery> dco_decode_list_voting_vote_recovery(dynamic raw); @@ -530,7 +563,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay? - dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); + dco_decode_opt_box_autoadd_voting_completed_vote_display(dynamic raw); @protected VotingConfig? dco_decode_opt_box_autoadd_voting_config(dynamic raw); @@ -657,11 +690,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteChoice dco_decode_voting_completed_vote_choice( - dynamic raw); + dynamic raw, + ); @protected VotingCompletedVoteDisplay dco_decode_voting_completed_vote_display( - dynamic raw); + dynamic raw, + ); @protected VotingConfig dco_decode_voting_config(dynamic raw); @@ -674,7 +709,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingDelegationConfirmation dco_decode_voting_delegation_confirmation( - dynamic raw); + dynamic raw, + ); @protected VotingDelegationProgress dco_decode_voting_delegation_progress(dynamic raw); @@ -690,7 +726,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingDelegationSubmission dco_decode_voting_delegation_submission( - dynamic raw); + dynamic raw, + ); @protected VotingEncryptedShare dco_decode_voting_encrypted_share(dynamic raw); @@ -721,7 +758,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingShareDelegationRecord dco_decode_voting_share_delegation_record( - dynamic raw); + dynamic raw, + ); @protected VotingSharePayload dco_decode_voting_share_payload(dynamic raw); @@ -734,22 +772,26 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingShareSubmissionPayload dco_decode_voting_share_submission_payload( - dynamic raw); + dynamic raw, + ); @protected VotingShareTrackingSummary dco_decode_voting_share_tracking_summary( - dynamic raw); + dynamic raw, + ); @protected VotingShareWorkflow dco_decode_voting_share_workflow(dynamic raw); @protected VotingSignedVoteCommitment dco_decode_voting_signed_vote_commitment( - dynamic raw); + dynamic raw, + ); @protected VotingTreeVoteConfirmation dco_decode_voting_tree_vote_confirmation( - dynamic raw); + dynamic raw, + ); @protected VotingVanWitness dco_decode_voting_van_witness(dynamic raw); @@ -780,113 +822,136 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected DartVault - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected DartVault - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @protected DartVault - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + SseDeserializer deserializer, + ); @protected Mempool - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + SseDeserializer deserializer, + ); @protected NoteMigration - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + SseDeserializer deserializer, + ); @protected TransparentScanner - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - SseDeserializer deserializer); + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + SseDeserializer deserializer, + ); @protected RustStreamSink<String> sse_decode_StreamSink_String_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<DKGStatus> sse_decode_StreamSink_dkg_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<LogMessage> sse_decode_StreamSink_log_message_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<MempoolMsg> sse_decode_StreamSink_mempool_msg_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<MigrationStatus> sse_decode_StreamSink_migration_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SigningEvent> sse_decode_StreamSink_signing_event_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SigningStatus> sse_decode_StreamSink_signing_status_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<SyncProgress> sse_decode_StreamSink_sync_progress_Sse( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected RustStreamSink<VotingDelegationProgress> - sse_decode_StreamSink_voting_delegation_progress_Sse( - SseDeserializer deserializer); + sse_decode_StreamSink_voting_delegation_progress_Sse( + SseDeserializer deserializer, + ); @protected RustStreamSink<VotingVoteCommitStage> - sse_decode_StreamSink_voting_vote_commit_stage_Sse( - SseDeserializer deserializer); + sse_decode_StreamSink_voting_vote_commit_stage_Sse( + SseDeserializer deserializer, + ); @protected String sse_decode_String(SseDeserializer deserializer); @@ -905,7 +970,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected AccountUpdate sse_decode_box_autoadd_account_update( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected bool sse_decode_box_autoadd_bool(SseDeserializer deserializer); @@ -936,21 +1002,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected PaymentOptions sse_decode_box_autoadd_payment_options( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected PcztPackage sse_decode_box_autoadd_pczt_package(SseDeserializer deserializer); @protected RaptorQParams sse_decode_box_autoadd_raptor_q_params( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Seed sse_decode_box_autoadd_seed(SseDeserializer deserializer); @protected SigningEvent sse_decode_box_autoadd_signing_event( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); @@ -963,16 +1032,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay - sse_decode_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer); + sse_decode_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ); @protected VotingConfig sse_decode_box_autoadd_voting_config( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingPirLayout sse_decode_box_autoadd_voting_pir_layout( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Category sse_decode_category(SseDeserializer deserializer); @@ -1030,18 +1102,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<ContactMatch> sse_decode_list_contact_match( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<DbAccountPreview> sse_decode_list_db_account_preview( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<Folder> sse_decode_list_folder(SseDeserializer deserializer); @protected List<Uint8List> sse_decode_list_list_prim_u_8_strict( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<LWDInfo> sse_decode_list_lwd_info(SseDeserializer deserializer); @@ -1060,7 +1135,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<MempoolAmount> sse_decode_list_mempool_amount( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<MempoolNote> sse_decode_list_mempool_note(SseDeserializer deserializer); @@ -1091,19 +1167,23 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<(String, double, bool)> sse_decode_list_record_string_f_64_bool( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<(int, double)> sse_decode_list_record_u_32_f_64( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<RestoredAccount> sse_decode_list_restored_account( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<TAddressTxCount> sse_decode_list_t_address_tx_count( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<Tx> sse_decode_list_tx(SseDeserializer deserializer); @@ -1128,74 +1208,85 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected List<VotingBallotIntent> sse_decode_list_voting_ballot_intent( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingCompletedVoteChoice> sse_decode_list_voting_completed_vote_choice( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingConfigRound> sse_decode_list_voting_config_round( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingDelegationRecovery> sse_decode_list_voting_delegation_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingDelegationStatus> sse_decode_list_voting_delegation_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingEncryptedShare> sse_decode_list_voting_encrypted_share( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingNextStep> sse_decode_list_voting_next_step( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingRoundInfo> sse_decode_list_voting_round_info( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingRoundSession> sse_decode_list_voting_round_session( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingServiceEndpoint> sse_decode_list_voting_service_endpoint( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingShareDelegationRecord> - sse_decode_list_voting_share_delegation_record( - SseDeserializer deserializer); + sse_decode_list_voting_share_delegation_record(SseDeserializer deserializer); @protected List<VotingSharePayload> sse_decode_list_voting_share_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingSharePlanItem> sse_decode_list_voting_share_plan_item( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingShareSubmissionPayload> - sse_decode_list_voting_share_submission_payload( - SseDeserializer deserializer); + sse_decode_list_voting_share_submission_payload(SseDeserializer deserializer); @protected List<VotingShareWorkflow> sse_decode_list_voting_share_workflow( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<VotingSignedVoteCommitment> - sse_decode_list_voting_signed_vote_commitment( - SseDeserializer deserializer); + sse_decode_list_voting_signed_vote_commitment(SseDeserializer deserializer); @protected List<VotingVoteRecovery> sse_decode_list_voting_vote_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<ZsaHolding> sse_decode_list_zsa_holding(SseDeserializer deserializer); @@ -1241,7 +1332,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected OpenAliasResolution sse_decode_open_alias_resolution( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -1254,7 +1346,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected FrostParams? sse_decode_opt_box_autoadd_frost_params( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); @@ -1276,16 +1369,19 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingCompletedVoteDisplay? - sse_decode_opt_box_autoadd_voting_completed_vote_display( - SseDeserializer deserializer); + sse_decode_opt_box_autoadd_voting_completed_vote_display( + SseDeserializer deserializer, + ); @protected VotingConfig? sse_decode_opt_box_autoadd_voting_config( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingPirLayout? sse_decode_opt_box_autoadd_voting_pir_layout( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected List<String>? sse_decode_opt_list_String(SseDeserializer deserializer); @@ -1313,7 +1409,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected RawOpenAliasResolution sse_decode_raw_open_alias_resolution( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Receivers sse_decode_receivers(SseDeserializer deserializer); @@ -1323,7 +1420,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected (String, double, bool) sse_decode_record_string_f_64_bool( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected (int, double) sse_decode_record_u_32_f_64(SseDeserializer deserializer); @@ -1333,7 +1431,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected SaplingParamsStatus sse_decode_sapling_params_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected Seed sse_decode_seed(SseDeserializer deserializer); @@ -1403,58 +1502,71 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingBallotIntent sse_decode_voting_ballot_intent( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingChainResponse sse_decode_voting_chain_response( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingCompletedVoteChoice sse_decode_voting_completed_vote_choice( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingCompletedVoteDisplay sse_decode_voting_completed_vote_display( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingConfig sse_decode_voting_config(SseDeserializer deserializer); @protected VotingConfigRound sse_decode_voting_config_round( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationBuild sse_decode_voting_delegation_build( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationConfirmation sse_decode_voting_delegation_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationProgress sse_decode_voting_delegation_progress( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationRecovery sse_decode_voting_delegation_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationSetup sse_decode_voting_delegation_setup( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationStatus sse_decode_voting_delegation_status( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingDelegationSubmission sse_decode_voting_delegation_submission( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingEncryptedShare sse_decode_voting_encrypted_share( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingNextStep sse_decode_voting_next_step(SseDeserializer deserializer); @@ -1464,7 +1576,8 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingPreparedInfo sse_decode_voting_prepared_info( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingRoundInfo sse_decode_voting_round_info(SseDeserializer deserializer); @@ -1474,197 +1587,271 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected VotingRoundRecovery sse_decode_voting_round_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingRoundSession sse_decode_voting_round_session( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingServiceEndpoint sse_decode_voting_service_endpoint( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareDelegationRecord sse_decode_voting_share_delegation_record( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSharePayload sse_decode_voting_share_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSharePlan sse_decode_voting_share_plan(SseDeserializer deserializer); @protected VotingSharePlanItem sse_decode_voting_share_plan_item( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareSubmissionPayload sse_decode_voting_share_submission_payload( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareTrackingSummary sse_decode_voting_share_tracking_summary( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingShareWorkflow sse_decode_voting_share_workflow( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingSignedVoteCommitment sse_decode_voting_signed_vote_commitment( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingTreeVoteConfirmation sse_decode_voting_tree_vote_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVanWitness sse_decode_voting_van_witness(SseDeserializer deserializer); @protected VotingVoteCommitStage sse_decode_voting_vote_commit_stage( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteCommitments sse_decode_voting_vote_commitments( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteConfirmation sse_decode_voting_vote_confirmation( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVotePayloads sse_decode_voting_vote_payloads( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteRecovery sse_decode_voting_vote_recovery( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected VotingVoteSubmission sse_decode_voting_vote_submission( - SseDeserializer deserializer); + SseDeserializer deserializer, + ); @protected ZsaHolding sse_decode_zsa_holding(SseDeserializer deserializer); @protected void sse_encode_AnyhowException( - AnyhowException self, SseSerializer serializer); + AnyhowException self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void - sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( - FutureOr<void> Function(Uint8List) self, SseSerializer serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + FutureOr<Uint8List> Function(Uint8List) self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( + FutureOr<void> Function(Uint8List) self, + SseSerializer serializer, + ); @protected void sse_encode_DartOpaque(Object self, SseSerializer serializer); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - DartVault self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + DartVault self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - Mempool self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + Mempool self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - NoteMigration self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + NoteMigration self, + SseSerializer serializer, + ); @protected void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - TransparentScanner self, SseSerializer serializer); + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + TransparentScanner self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_String_Sse( - RustStreamSink<String> self, SseSerializer serializer); + RustStreamSink<String> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_dkg_status_Sse( - RustStreamSink<DKGStatus> self, SseSerializer serializer); + RustStreamSink<DKGStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_log_message_Sse( - RustStreamSink<LogMessage> self, SseSerializer serializer); + RustStreamSink<LogMessage> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_mempool_msg_Sse( - RustStreamSink<MempoolMsg> self, SseSerializer serializer); + RustStreamSink<MempoolMsg> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_migration_status_Sse( - RustStreamSink<MigrationStatus> self, SseSerializer serializer); + RustStreamSink<MigrationStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_signing_event_Sse( - RustStreamSink<SigningEvent> self, SseSerializer serializer); + RustStreamSink<SigningEvent> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_signing_status_Sse( - RustStreamSink<SigningStatus> self, SseSerializer serializer); + RustStreamSink<SigningStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_sync_progress_Sse( - RustStreamSink<SyncProgress> self, SseSerializer serializer); + RustStreamSink<SyncProgress> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_voting_delegation_progress_Sse( - RustStreamSink<VotingDelegationProgress> self, SseSerializer serializer); + RustStreamSink<VotingDelegationProgress> self, + SseSerializer serializer, + ); @protected void sse_encode_StreamSink_voting_vote_commit_stage_Sse( - RustStreamSink<VotingVoteCommitStage> self, SseSerializer serializer); + RustStreamSink<VotingVoteCommitStage> self, + SseSerializer serializer, + ); @protected void sse_encode_String(String self, SseSerializer serializer); @@ -1683,7 +1870,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_account_update( - AccountUpdate self, SseSerializer serializer); + AccountUpdate self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_bool(bool self, SseSerializer serializer); @@ -1699,41 +1888,57 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_frost_params( - FrostParams self, SseSerializer serializer); + FrostParams self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_i_32(int self, SseSerializer serializer); @protected void sse_encode_box_autoadd_i_64( - PlatformInt64 self, SseSerializer serializer); + PlatformInt64 self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_mempool_tx( - MempoolTx self, SseSerializer serializer); + MempoolTx self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_new_account( - NewAccount self, SseSerializer serializer); + NewAccount self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_payment_options( - PaymentOptions self, SseSerializer serializer); + PaymentOptions self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_pczt_package( - PcztPackage self, SseSerializer serializer); + PcztPackage self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_raptor_q_params( - RaptorQParams self, SseSerializer serializer); + RaptorQParams self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_seed(Seed self, SseSerializer serializer); @protected void sse_encode_box_autoadd_signing_event( - SigningEvent self, SseSerializer serializer); + SigningEvent self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); @@ -1746,15 +1951,21 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer); + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_voting_config( - VotingConfig self, SseSerializer serializer); + VotingConfig self, + SseSerializer serializer, + ); @protected void sse_encode_box_autoadd_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer); + VotingPirLayout self, + SseSerializer serializer, + ); @protected void sse_encode_category(Category self, SseSerializer serializer); @@ -1770,7 +1981,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_db_account_preview( - DbAccountPreview self, SseSerializer serializer); + DbAccountPreview self, + SseSerializer serializer, + ); @protected void sse_encode_dkg_status(DKGStatus self, SseSerializer serializer); @@ -1789,7 +2002,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_frost_sign_params( - FrostSignParams self, SseSerializer serializer); + FrostSignParams self, + SseSerializer serializer, + ); @protected void sse_encode_i_32(int self, SseSerializer serializer); @@ -1814,18 +2029,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_contact_match( - List<ContactMatch> self, SseSerializer serializer); + List<ContactMatch> self, + SseSerializer serializer, + ); @protected void sse_encode_list_db_account_preview( - List<DbAccountPreview> self, SseSerializer serializer); + List<DbAccountPreview> self, + SseSerializer serializer, + ); @protected void sse_encode_list_folder(List<Folder> self, SseSerializer serializer); @protected void sse_encode_list_list_prim_u_8_strict( - List<Uint8List> self, SseSerializer serializer); + List<Uint8List> self, + SseSerializer serializer, + ); @protected void sse_encode_list_lwd_info(List<LWDInfo> self, SseSerializer serializer); @@ -1841,62 +2062,90 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_memo_section( - List<MemoSection> self, SseSerializer serializer); + List<MemoSection> self, + SseSerializer serializer, + ); @protected void sse_encode_list_mempool_amount( - List<MempoolAmount> self, SseSerializer serializer); + List<MempoolAmount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_mempool_note( - List<MempoolNote> self, SseSerializer serializer); + List<MempoolNote> self, + SseSerializer serializer, + ); @protected void sse_encode_list_plugin_info( - List<PluginInfo> self, SseSerializer serializer); + List<PluginInfo> self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_32_loose( - List<int> self, SseSerializer serializer); + List<int> self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_32_strict( - Uint32List self, SseSerializer serializer); + Uint32List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_64_strict( - Uint64List self, SseSerializer serializer); + Uint64List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer); @protected void sse_encode_list_prim_u_8_strict( - Uint8List self, SseSerializer serializer); + Uint8List self, + SseSerializer serializer, + ); @protected void sse_encode_list_prim_usize_strict( - Uint64List self, SseSerializer serializer); + Uint64List self, + SseSerializer serializer, + ); @protected void sse_encode_list_recipient( - List<Recipient> self, SseSerializer serializer); + List<Recipient> self, + SseSerializer serializer, + ); @protected void sse_encode_list_record_string_f_64_bool( - List<(String, double, bool)> self, SseSerializer serializer); + List<(String, double, bool)> self, + SseSerializer serializer, + ); @protected void sse_encode_list_record_u_32_f_64( - List<(int, double)> self, SseSerializer serializer); + List<(int, double)> self, + SseSerializer serializer, + ); @protected void sse_encode_list_restored_account( - List<RestoredAccount> self, SseSerializer serializer); + List<RestoredAccount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_t_address_tx_count( - List<TAddressTxCount> self, SseSerializer serializer); + List<TAddressTxCount> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx(List<Tx> self, SseSerializer serializer); @@ -1912,86 +2161,126 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_list_tx_plan_in( - List<TxPlanIn> self, SseSerializer serializer); + List<TxPlanIn> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx_plan_out( - List<TxPlanOut> self, SseSerializer serializer); + List<TxPlanOut> self, + SseSerializer serializer, + ); @protected void sse_encode_list_tx_spend(List<TxSpend> self, SseSerializer serializer); @protected void sse_encode_list_voting_ballot_intent( - List<VotingBallotIntent> self, SseSerializer serializer); + List<VotingBallotIntent> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_completed_vote_choice( - List<VotingCompletedVoteChoice> self, SseSerializer serializer); + List<VotingCompletedVoteChoice> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_config_round( - List<VotingConfigRound> self, SseSerializer serializer); + List<VotingConfigRound> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_delegation_recovery( - List<VotingDelegationRecovery> self, SseSerializer serializer); + List<VotingDelegationRecovery> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_delegation_status( - List<VotingDelegationStatus> self, SseSerializer serializer); + List<VotingDelegationStatus> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_encrypted_share( - List<VotingEncryptedShare> self, SseSerializer serializer); + List<VotingEncryptedShare> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_next_step( - List<VotingNextStep> self, SseSerializer serializer); + List<VotingNextStep> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_round_info( - List<VotingRoundInfo> self, SseSerializer serializer); + List<VotingRoundInfo> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_round_session( - List<VotingRoundSession> self, SseSerializer serializer); + List<VotingRoundSession> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_service_endpoint( - List<VotingServiceEndpoint> self, SseSerializer serializer); + List<VotingServiceEndpoint> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_delegation_record( - List<VotingShareDelegationRecord> self, SseSerializer serializer); + List<VotingShareDelegationRecord> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_payload( - List<VotingSharePayload> self, SseSerializer serializer); + List<VotingSharePayload> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_plan_item( - List<VotingSharePlanItem> self, SseSerializer serializer); + List<VotingSharePlanItem> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_submission_payload( - List<VotingShareSubmissionPayload> self, SseSerializer serializer); + List<VotingShareSubmissionPayload> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_share_workflow( - List<VotingShareWorkflow> self, SseSerializer serializer); + List<VotingShareWorkflow> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_signed_vote_commitment( - List<VotingSignedVoteCommitment> self, SseSerializer serializer); + List<VotingSignedVoteCommitment> self, + SseSerializer serializer, + ); @protected void sse_encode_list_voting_vote_recovery( - List<VotingVoteRecovery> self, SseSerializer serializer); + List<VotingVoteRecovery> self, + SseSerializer serializer, + ); @protected void sse_encode_list_zsa_holding( - List<ZsaHolding> self, SseSerializer serializer); + List<ZsaHolding> self, + SseSerializer serializer, + ); @protected void sse_encode_log_message(LogMessage self, SseSerializer serializer); @@ -2025,18 +2314,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_migration_event( - MigrationEvent self, SseSerializer serializer); + MigrationEvent self, + SseSerializer serializer, + ); @protected void sse_encode_migration_status( - MigrationStatus self, SseSerializer serializer); + MigrationStatus self, + SseSerializer serializer, + ); @protected void sse_encode_new_account(NewAccount self, SseSerializer serializer); @protected void sse_encode_open_alias_resolution( - OpenAliasResolution self, SseSerializer serializer); + OpenAliasResolution self, + SseSerializer serializer, + ); @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -2049,14 +2344,18 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_opt_box_autoadd_frost_params( - FrostParams? self, SseSerializer serializer); + FrostParams? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); @protected void sse_encode_opt_box_autoadd_i_64( - PlatformInt64? self, SseSerializer serializer); + PlatformInt64? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_seed(Seed? self, SseSerializer serializer); @@ -2072,30 +2371,42 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_opt_box_autoadd_voting_completed_vote_display( - VotingCompletedVoteDisplay? self, SseSerializer serializer); + VotingCompletedVoteDisplay? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_voting_config( - VotingConfig? self, SseSerializer serializer); + VotingConfig? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_box_autoadd_voting_pir_layout( - VotingPirLayout? self, SseSerializer serializer); + VotingPirLayout? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_list_String(List<String>? self, SseSerializer serializer); @protected void sse_encode_opt_list_prim_u_8_strict( - Uint8List? self, SseSerializer serializer); + Uint8List? self, + SseSerializer serializer, + ); @protected void sse_encode_opt_list_recipient( - List<Recipient>? self, SseSerializer serializer); + List<Recipient>? self, + SseSerializer serializer, + ); @protected void sse_encode_payment_options( - PaymentOptions self, SseSerializer serializer); + PaymentOptions self, + SseSerializer serializer, + ); @protected void sse_encode_pczt_package(PcztPackage self, SseSerializer serializer); @@ -2111,7 +2422,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_raw_open_alias_resolution( - RawOpenAliasResolution self, SseSerializer serializer); + RawOpenAliasResolution self, + SseSerializer serializer, + ); @protected void sse_encode_receivers(Receivers self, SseSerializer serializer); @@ -2121,19 +2434,27 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_record_string_f_64_bool( - (String, double, bool) self, SseSerializer serializer); + (String, double, bool) self, + SseSerializer serializer, + ); @protected void sse_encode_record_u_32_f_64( - (int, double) self, SseSerializer serializer); + (int, double) self, + SseSerializer serializer, + ); @protected void sse_encode_restored_account( - RestoredAccount self, SseSerializer serializer); + RestoredAccount self, + SseSerializer serializer, + ); @protected void sse_encode_sapling_params_status( - SaplingParamsStatus self, SseSerializer serializer); + SaplingParamsStatus self, + SseSerializer serializer, + ); @protected void sse_encode_seed(Seed self, SseSerializer serializer); @@ -2152,7 +2473,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_t_address_tx_count( - TAddressTxCount self, SseSerializer serializer); + TAddressTxCount self, + SseSerializer serializer, + ); @protected void sse_encode_tx(Tx self, SseSerializer serializer); @@ -2204,154 +2527,228 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { @protected void sse_encode_voting_ballot_intent( - VotingBallotIntent self, SseSerializer serializer); + VotingBallotIntent self, + SseSerializer serializer, + ); @protected void sse_encode_voting_chain_response( - VotingChainResponse self, SseSerializer serializer); + VotingChainResponse self, + SseSerializer serializer, + ); @protected void sse_encode_voting_completed_vote_choice( - VotingCompletedVoteChoice self, SseSerializer serializer); + VotingCompletedVoteChoice self, + SseSerializer serializer, + ); @protected void sse_encode_voting_completed_vote_display( - VotingCompletedVoteDisplay self, SseSerializer serializer); + VotingCompletedVoteDisplay self, + SseSerializer serializer, + ); @protected void sse_encode_voting_config(VotingConfig self, SseSerializer serializer); @protected void sse_encode_voting_config_round( - VotingConfigRound self, SseSerializer serializer); + VotingConfigRound self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_build( - VotingDelegationBuild self, SseSerializer serializer); + VotingDelegationBuild self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_confirmation( - VotingDelegationConfirmation self, SseSerializer serializer); + VotingDelegationConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_progress( - VotingDelegationProgress self, SseSerializer serializer); + VotingDelegationProgress self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_recovery( - VotingDelegationRecovery self, SseSerializer serializer); + VotingDelegationRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_setup( - VotingDelegationSetup self, SseSerializer serializer); + VotingDelegationSetup self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_status( - VotingDelegationStatus self, SseSerializer serializer); + VotingDelegationStatus self, + SseSerializer serializer, + ); @protected void sse_encode_voting_delegation_submission( - VotingDelegationSubmission self, SseSerializer serializer); + VotingDelegationSubmission self, + SseSerializer serializer, + ); @protected void sse_encode_voting_encrypted_share( - VotingEncryptedShare self, SseSerializer serializer); + VotingEncryptedShare self, + SseSerializer serializer, + ); @protected void sse_encode_voting_next_step( - VotingNextStep self, SseSerializer serializer); + VotingNextStep self, + SseSerializer serializer, + ); @protected void sse_encode_voting_pir_layout( - VotingPirLayout self, SseSerializer serializer); + VotingPirLayout self, + SseSerializer serializer, + ); @protected void sse_encode_voting_prepared_info( - VotingPreparedInfo self, SseSerializer serializer); + VotingPreparedInfo self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_info( - VotingRoundInfo self, SseSerializer serializer); + VotingRoundInfo self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_plan( - VotingRoundPlan self, SseSerializer serializer); + VotingRoundPlan self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_recovery( - VotingRoundRecovery self, SseSerializer serializer); + VotingRoundRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_round_session( - VotingRoundSession self, SseSerializer serializer); + VotingRoundSession self, + SseSerializer serializer, + ); @protected void sse_encode_voting_service_endpoint( - VotingServiceEndpoint self, SseSerializer serializer); + VotingServiceEndpoint self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_delegation_record( - VotingShareDelegationRecord self, SseSerializer serializer); + VotingShareDelegationRecord self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_payload( - VotingSharePayload self, SseSerializer serializer); + VotingSharePayload self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_plan( - VotingSharePlan self, SseSerializer serializer); + VotingSharePlan self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_plan_item( - VotingSharePlanItem self, SseSerializer serializer); + VotingSharePlanItem self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_submission_payload( - VotingShareSubmissionPayload self, SseSerializer serializer); + VotingShareSubmissionPayload self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_tracking_summary( - VotingShareTrackingSummary self, SseSerializer serializer); + VotingShareTrackingSummary self, + SseSerializer serializer, + ); @protected void sse_encode_voting_share_workflow( - VotingShareWorkflow self, SseSerializer serializer); + VotingShareWorkflow self, + SseSerializer serializer, + ); @protected void sse_encode_voting_signed_vote_commitment( - VotingSignedVoteCommitment self, SseSerializer serializer); + VotingSignedVoteCommitment self, + SseSerializer serializer, + ); @protected void sse_encode_voting_tree_vote_confirmation( - VotingTreeVoteConfirmation self, SseSerializer serializer); + VotingTreeVoteConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_van_witness( - VotingVanWitness self, SseSerializer serializer); + VotingVanWitness self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_commit_stage( - VotingVoteCommitStage self, SseSerializer serializer); + VotingVoteCommitStage self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_commitments( - VotingVoteCommitments self, SseSerializer serializer); + VotingVoteCommitments self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_confirmation( - VotingVoteConfirmation self, SseSerializer serializer); + VotingVoteConfirmation self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_payloads( - VotingVotePayloads self, SseSerializer serializer); + VotingVotePayloads self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_recovery( - VotingVoteRecovery self, SseSerializer serializer); + VotingVoteRecovery self, + SseSerializer serializer, + ); @protected void sse_encode_voting_vote_submission( - VotingVoteSubmission self, SseSerializer serializer); + VotingVoteSubmission self, + SseSerializer serializer, + ); @protected void sse_encode_zsa_holding(ZsaHolding self, SseSerializer serializer); @@ -2362,53 +2759,69 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> { class RustLibWire implements BaseWire { RustLibWire.fromExternalLibrary(ExternalLibrary lib); - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr) => - wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr) => - wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - ptr); + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + ptr, + ); + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + ptr, + ); + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + ptr, + ); + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + ptr, + ); } @JS('wasm_bindgen') @@ -2418,34 +2831,42 @@ external RustLibWasmModule get wasmModule; @anonymous extension type RustLibWasmModule._(JSObject _) implements JSObject { external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr); + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr, + ); external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( - int ptr); + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDartVault( + int ptr, + ); external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr); + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr, + ); external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( - int ptr); + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMempool( + int ptr, + ); external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr); + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr, + ); external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( - int ptr); + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerNoteMigration( + int ptr, + ); external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr); + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr, + ); external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( - int ptr); + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerTransparentScanner( + int ptr, + ); } diff --git a/lib/src/rust/io.dart b/lib/src/rust/io.dart index 55bbab0c3..0d15c9d3e 100644 --- a/lib/src/rust/io.dart +++ b/lib/src/rust/io.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import diff --git a/lib/src/rust/lib.dart b/lib/src/rust/lib.dart index 49f31a45f..290d40998 100644 --- a/lib/src/rust/lib.dart +++ b/lib/src/rust/lib.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -14,9 +14,7 @@ class UsizeArray4 extends NonGrowableListView<BigInt> { Uint64List get inner => _inner; final Uint64List _inner; - UsizeArray4(this._inner) - : assert(_inner.length == arraySize), - super(_inner); + UsizeArray4(this._inner) : assert(_inner.length == arraySize), super(_inner); UsizeArray4.init() : this(Uint64List(arraySize)); } diff --git a/lib/src/rust/pay.dart b/lib/src/rust/pay.dart index 84d3d8e93..077c13f10 100644 --- a/lib/src/rust/pay.dart +++ b/lib/src/rust/pay.dart @@ -1,5 +1,5 @@ // This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.11.1. +// @generated by `flutter_rust_bridge`@ 2.12.0. // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import @@ -97,11 +97,7 @@ class TxPlanIn { final BigInt? amount; final String assetName; - const TxPlanIn({ - required this.pool, - this.amount, - required this.assetName, - }); + const TxPlanIn({required this.pool, this.amount, required this.assetName}); @override int get hashCode => pool.hashCode ^ amount.hashCode ^ assetName.hashCode; diff --git a/lib/src/rust/pay/error.dart b/lib/src/rust/pay/error.dart index 343ad1dc2..84a4f4d5f 100644 --- a/lib/src/rust/pay/error.dart +++ b/lib/src/rust/pay/error.dart @@ -13,14 +13,8 @@ sealed class Error with _$Error { const Error._(); const factory Error.invalidPoolMask() = Error_InvalidPoolMask; - const factory Error.notEnoughFunds( - String field0, - ) = Error_NotEnoughFunds; + const factory Error.notEnoughFunds(String field0) = Error_NotEnoughFunds; const factory Error.noSigningKey() = Error_NoSigningKey; - const factory Error.sqlx( - Error field0, - ) = Error_Sqlx; - const factory Error.other( - Error field0, - ) = Error_Other; + const factory Error.sqlx(Error field0) = Error_Sqlx; + const factory Error.other(Error field0) = Error_Other; } diff --git a/pubspec.yaml b/pubspec.yaml index 9abf38a39..172b9be33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: cupertino_icons: ^1.0.8 rlz: path: rust_builder - flutter_rust_bridge: 2.11.1 + flutter_rust_bridge: 2.12.0 logger: ^2.0.2+1 go_router: ^14.8.1 diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 065ff0f4a..65d0d44aa 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -163,7 +163,7 @@ rand = "0.6" vote-commitment-tree = { git = "https://github.com/hhanh00/zcash_voting.git", rev = "049504162f11a09c89d33414d35e747851891d04" } [features] -default = ["flutter", "nym"] +default = ["flutter"] flutter = ["flutter_rust_bridge"] bundled-sapling-params = ["zcash_proofs/bundled-prover"] graphql = ["juniper", "juniper_warp", "juniper_graphql_ws", "dataloader", "warp", "jsonwebtoken", "bigdecimal", "chrono", "figment", "clap"] diff --git a/rust/src/account.rs b/rust/src/account.rs index 7c04af1a2..0f831c2c6 100644 --- a/rust/src/account.rs +++ b/rust/src/account.rs @@ -104,7 +104,13 @@ pub async fn new_account( key = generate_seed()?; } - let pools = na.pools.unwrap_or(ALL_POOLS); + // The Official Ledger app only ever signs transparent and ironwood + // spends, so that is what an account for it tracks unless told otherwise. + let pools = na.pools.unwrap_or(if ledger_kind == HwKind::Official { + POOL_TRANSPARENT | POOL_IRONWOOD + } else { + ALL_POOLS + }); if pools == 0 { anyhow::bail!("an account must support at least one pool"); } @@ -117,9 +123,9 @@ pub async fn new_account( "Official Ledger accounts support transparent and ironwood pools only" ); } - if !key.is_empty() && !is_valid_phrase(&key) { + if !key.is_empty() && !is_valid_phrase(&key) && !is_valid_ufvk(network, &key) { anyhow::bail!( - "Official Ledger accounts accept a seed phrase or no key to import the viewing key from the device" + "Official Ledger accounts accept a seed phrase, a unified viewing key exported by the device, or no key to import the viewing key from the device" ); } } @@ -188,11 +194,18 @@ pub async fn new_account( .await?; } update_dindex(&mut db_tx, account, dindex, true).await?; - } else if ledger_kind == Some(HwKind::Official) && key.is_empty() { - // import the viewing key from the Official Ledger device + } else if ledger_kind == Some(HwKind::Official) && !is_valid_phrase(&key) { + // A watch-only account for the Official Ledger app. The viewing key + // either comes straight from the device here, or was exported earlier + // by a host that owns the device connection (the mobile wallet, where + // the transport is not available from Rust) and is passed as the key. store_account_hw(&mut db_tx, account, HwKind::Official as u8, na.aindex).await?; - let ledger = get_ledger(&mut db_tx, account).await?; - let ufvk = ledger.get_ufvk(network, na.aindex).await?; + let ufvk = if key.is_empty() { + let ledger = get_ledger(&mut db_tx, account).await?; + ledger.get_ufvk(network, na.aindex).await? + } else { + key.clone() + }; let uvk = UnifiedFullViewingKey::decode(network, &ufvk) .map_err(|_| anyhow!("Invalid viewing key from the device"))?; diff --git a/rust/src/api/ledger.rs b/rust/src/api/ledger.rs index a1df2821b..6a036bda6 100644 --- a/rust/src/api/ledger.rs +++ b/rust/src/api/ledger.rs @@ -1,41 +1,103 @@ -use anyhow::Result; -use sapling_crypto::keys::FullViewingKey; -use sqlx::SqliteConnection; -use zcash_transparent::address::TransparentAddress; +//! Ledger access from Flutter. +//! +//! The device connection lives on the Dart side (ledger_flutter_plus over +//! BLE, or USB on Android); Rust drives the Official Zcash app protocol and +//! hands every APDU to the `exchange` callback, which answers with the raw +//! response including the status word, or an empty vector if the transport +//! failed. -use crate::api::{ - coin::{Coin, Network}, - pay::{PcztPackage, SigningEvent}, -}; #[cfg(feature = "flutter")] -use crate::frb_generated::StreamSink; +use anyhow::{anyhow, Result}; +#[cfg(feature = "flutter")] +use flutter_rust_bridge::{frb, DartFnFuture}; +#[cfg(feature = "flutter")] +use zcash_keys::keys::{UnifiedAddressRequest, UnifiedFullViewingKey}; -pub(crate) async fn get_hw_transparent_address( - network: &Network, - aindex: u32, - scope: u32, - dindex: u32, -) -> Result<(Vec<u8>, TransparentAddress)> { -} +#[cfg(feature = "flutter")] +use crate::{ + api::{ + coin::Coin, + pay::{PcztPackage, SigningEvent}, + }, + frb_generated::StreamSink, + ledger::{dart_device::DartDevice, official, official_sign}, + Sink, +}; -pub(crate) async fn get_hw_next_diversifier_address( - network: &Network, - aindex: u32, - dindex: u32, -) -> Result<(u32, String)> { +/// Version of the Zcash app open on the device, e.g. "3.9.3". +/// +/// Fails with the device's status word when another app is open, which is +/// the cheapest way to tell the user to switch apps before asking for keys. +#[cfg(feature = "flutter")] +#[frb] +pub async fn ledger_app_version( + exchange: impl Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync + 'static, +) -> Result<String> { + let device = DartDevice::new(exchange); + let (major, minor, patch) = official::get_app_version(&device).await?; + Ok(format!("{major}.{minor}.{patch}")) } -pub(crate) async fn show_sapling_address( - network: &Network, - connection: &mut SqliteConnection, - account: u32, +/// Unified full viewing key of ZIP-32 account `aindex` on the device +/// (transparent + orchard receivers). The user approves the export on the +/// device screen, so this blocks until they do. +#[cfg(feature = "flutter")] +#[frb] +pub async fn ledger_get_ufvk( + aindex: u32, + c: &Coin, + exchange: impl Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync + 'static, ) -> Result<String> { + let device = DartDevice::new(exchange); + Ok(official::get_ufvk(&device, &c.network(), aindex).await?) } -pub(crate) async fn show_transparent_address( - network: &Network, - connection: &mut SqliteConnection, - account: u32, -) -> Result<String> { +/// Default unified address of a viewing key, for showing which account a +/// device key belongs to before the account exists in the database. +#[cfg(feature = "flutter")] +#[frb(sync)] +pub fn ufvk_default_address(ufvk: String, c: &Coin) -> Result<String> { + let network = c.network(); + let uvk = UnifiedFullViewingKey::decode(&network, &ufvk) + .map_err(|e| anyhow!("invalid unified viewing key: {e}"))?; + let (ua, _) = uvk.default_address(UnifiedAddressRequest::AllAvailableKeys)?; + Ok(ua.encode(&network)) } +/// Signs a transaction plan on the Official Zcash app. +/// +/// Streams `SigningEvent::Progress` while the device reviews and signs, then +/// `SigningEvent::Result` with the proven, finalized package ready for +/// `extract_transaction`. Errors, including a refusal on the device, close +/// the stream with the error. +#[cfg(feature = "flutter")] +#[frb] +pub async fn ledger_sign_transaction( + sink: StreamSink<SigningEvent>, + package: PcztPackage, + c: &Coin, + exchange: impl Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync + 'static, +) -> Result<()> { + let device = DartDevice::new(exchange); + let c = c.clone(); + tokio::spawn(async move { + let result = async { + let mut connection = c.get_connection().await?; + official_sign::sign_transaction( + &c.network(), + &mut connection, + c.account, + &package, + Some(&sink), + &device, + ) + .await + } + .await; + match result { + Ok(pkg) => sink.send(SigningEvent::Result(pkg)).await, + Err(e) => sink.send_error(e).await, + } + }); + Ok(()) +} diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index 80c6ad13d..ad29701c6 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -6,6 +6,7 @@ pub mod frost; pub mod init; pub mod issuance; pub mod key; +pub mod ledger; pub mod mempool; pub mod migrate; pub mod network; diff --git a/rust/src/api/network.rs b/rust/src/api/network.rs index 4b195a2ed..1e211badd 100644 --- a/rust/src/api/network.rs +++ b/rust/src/api/network.rs @@ -109,10 +109,20 @@ pub async fn query_lwd_list(coin: u8) -> Result<Vec<LWDInfo>> { /// True when `url` is a mixnet-native server address /// (`nym://<identity>.<encryption>@<gateway>`). -#[cfg(feature = "nym")] +/// +/// Always exported so the generated bindings do not depend on the `nym` +/// feature; without it no URL is a mixnet address. #[cfg_attr(feature = "flutter", frb(sync))] pub fn is_valid_nym_url(url: String) -> bool { - crate::net::nym_service::parse_nym_url(&url).is_some() + #[cfg(feature = "nym")] + { + crate::net::nym_service::parse_nym_url(&url).is_some() + } + #[cfg(not(feature = "nym"))] + { + let _ = url; + false + } } #[cfg_attr(feature = "flutter", frb(dart_metadata = ("freezed")))] diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index f7f056adb..b638ab6c7 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -353494689; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1355211904; // Section: executor @@ -4704,6 +4704,56 @@ fn wire__crate__api__issuance__issue_asset_impl( }, ) } +fn wire__crate__api__ledger__ledger_app_version_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "ledger_app_version", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_exchange = decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::api::ledger::ledger_app_version(api_exchange).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__api__ledger__ledger_get_ufvk_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "ledger_get_ufvk", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_aindex = <u32>::sse_decode(&mut deserializer); +let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); +let api_exchange = decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::api::ledger::ledger_get_ufvk(api_aindex, &api_c, api_exchange).await?; Ok(output_ok) + })().await) + } }) +} +fn wire__crate__api__ledger__ledger_sign_transaction_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "ledger_sign_transaction", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_sink = <StreamSink<crate::api::pay::SigningEvent,flutter_rust_bridge::for_generated::SseCodec>>::sse_decode(&mut deserializer); +let api_package = <crate::api::pay::PcztPackage>::sse_decode(&mut deserializer); +let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); +let api_exchange = decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::api::ledger::ledger_sign_transaction(api_sink, api_package, &api_c, api_exchange).await?; Ok(output_ok) + })().await) + } }) +} fn wire__crate__api__account__list_accounts_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -4992,6 +5042,42 @@ fn wire__crate__api__account__list_notes_impl( }, ) } +fn wire__crate__api__account__list_owned_addresses_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "list_owned_addresses", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = crate::api::account::list_owned_addresses(&api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__plugin__list_plugins_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5359,6 +5445,189 @@ fn wire__crate__api__pay__parse_payment_uri_impl( }, ) } +fn wire__crate__api__pay__pczt_apply_batch_signatures_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_apply_batch_signatures", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_original = <Vec<u8>>::sse_decode(&mut deserializer); + let api_response = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_apply_batch_signatures( + api_original, + api_response, + )?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__pay__pczt_apply_keystone_signatures_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_apply_keystone_signatures", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_original = <Vec<u8>>::sse_decode(&mut deserializer); + let api_signed = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_apply_keystone_signatures( + api_original, + api_signed, + )?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__pay__pczt_from_keystone_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_from_keystone", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczt = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_from_keystone(api_pczt)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__pay__pczt_to_batch_request_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_to_batch_request", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczts = <Vec<Vec<u8>>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_to_batch_request(api_pczts)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__pay__pczt_to_keystone_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_to_keystone", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczt = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_to_keystone(api_pczt)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} fn wire__crate__api__pay__prepare_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5478,6 +5747,44 @@ fn wire__crate__api__account__print_keys_impl( }, ) } +fn wire__crate__api__pay__prove_and_finalize_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "prove_and_finalize", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczt = <crate::api::pay::PcztPackage>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let output_ok = + crate::api::pay::prove_and_finalize(&api_pczt, &api_c).await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__db__put_prop_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -7025,6 +7332,39 @@ fn wire__crate__api__account__ua_from_ufvk_impl( }, ) } +fn wire__crate__api__ledger__ufvk_default_address_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::SseCodec, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "ufvk_default_address", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_ufvk = <String>::sse_decode(&mut deserializer); + let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::ledger::ufvk_default_address(api_ufvk, &api_c)?; + Ok(output_ok) + })(), + ) + }, + ) +} fn wire__crate__api__account__unlock_all_notes_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -9425,6 +9765,38 @@ fn wire__crate__api__voting__voting_vote_wire_json_impl( // Section: related_funcs +fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + dart_opaque: flutter_rust_bridge::DartOpaque, +) -> impl Fn(Vec<u8>) -> flutter_rust_bridge::DartFnFuture<Vec<u8>> { + use flutter_rust_bridge::IntoDart; + + async fn body(dart_opaque: flutter_rust_bridge::DartOpaque, arg0: Vec<u8>) -> Vec<u8> { + let args = vec![arg0.into_into_dart().into_dart()]; + let message = FLUTTER_RUST_BRIDGE_HANDLER + .dart_fn_invoke(dart_opaque, args) + .await; + + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let action = deserializer.cursor.read_u8().unwrap(); + let ans = match action { + 0 => std::result::Result::Ok(<Vec<u8>>::sse_decode(&mut deserializer)), + 1 => std::result::Result::Err( + <flutter_rust_bridge::for_generated::anyhow::Error>::sse_decode(&mut deserializer), + ), + _ => unreachable!(), + }; + deserializer.end(); + let ans = ans.expect("Dart throws exception but Rust side assume it is not failable"); + ans + } + + move |arg0: Vec<u8>| { + flutter_rust_bridge::for_generated::convert_into_dart_fn_future(body( + dart_opaque.clone(), + arg0, + )) + } +} fn decode_DartFn_Inputs_list_prim_u_8_strict_Output_unit_AnyhowException( dart_opaque: flutter_rust_bridge::DartOpaque, ) -> impl Fn( @@ -12671,275 +13043,302 @@ fn pde_ffi_dispatcher_primary_impl( } 115 => wire__crate__api__zsa__is_zsa_available_impl(port, ptr, rust_vec_len, data_len), 116 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), - 117 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 118 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 120 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 128 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 129 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 117 => wire__crate__api__ledger__ledger_app_version_impl(port, ptr, rust_vec_len, data_len), + 118 => wire__crate__api__ledger__ledger_get_ufvk_impl(port, ptr, rust_vec_len, data_len), + 119 => wire__crate__api__ledger__ledger_sign_transaction_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 120 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 121 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 128 => { + wire__crate__api__account__list_owned_addresses_impl(port, ptr, rust_vec_len, data_len) + } + 129 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 130 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 135 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 136 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 138 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 139 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 140 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 144 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 146 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 147 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 149 => { + 139 => wire__crate__api__pay__pczt_apply_batch_signatures_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 140 => wire__crate__api__pay__pczt_apply_keystone_signatures_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 141 => wire__crate__api__pay__pczt_from_keystone_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__pay__pczt_to_batch_request_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__pay__pczt_to_keystone_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__pay__prove_and_finalize_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 152 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 153 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 154 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 155 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 159 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 150 => wire__crate__api__openalias__resolve_openalias_all_impl( + 160 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 151 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 161 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 152 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 153 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 154 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 155 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 159 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 160 => { + 162 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 163 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 164 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 170 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 161 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 162 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__account__show_ledger_sapling_address_impl( + 171 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 172 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 173 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 164 => wire__crate__api__account__show_ledger_transparent_address_impl( + 174 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 165 => wire__crate__api__account__sign_ledger_transaction_impl( + 175 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 166 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 173 => { + 176 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 177 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 178 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 179 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 181 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 183 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 174 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 175 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 176 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 177 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 179 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 180 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 181 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 182 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 183 => wire__crate__api__transaction__update_historical_prices_impl( + 184 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 185 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 186 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 187 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 190 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 191 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 192 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 193 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 194 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, data_len, ), - 186 => { + 197 => { wire__crate__api__voting__votechain_list_rounds_impl(port, ptr, rust_vec_len, data_len) } - 187 => wire__crate__api__voting__votechain_resubmit_share_impl( + 198 => wire__crate__api__voting__votechain_resubmit_share_impl( port, ptr, rust_vec_len, data_len, ), - 188 => { + 199 => { wire__crate__api__voting__votechain_round_status_impl(port, ptr, rust_vec_len, data_len) } - 189 => { + 200 => { wire__crate__api__voting__votechain_round_tally_impl(port, ptr, rust_vec_len, data_len) } - 190 => { + 201 => { wire__crate__api__voting__votechain_share_status_impl(port, ptr, rust_vec_len, data_len) } - 191 => wire__crate__api__voting__votechain_submit_delegation_impl( + 202 => wire__crate__api__voting__votechain_submit_delegation_impl( port, ptr, rust_vec_len, data_len, ), - 192 => { + 203 => { wire__crate__api__voting__votechain_submit_share_impl(port, ptr, rust_vec_len, data_len) } - 193 => { + 204 => { wire__crate__api__voting__votechain_submit_vote_impl(port, ptr, rust_vec_len, data_len) } - 194 => wire__crate__api__voting__votechain_tx_confirmation_impl( + 205 => wire__crate__api__voting__votechain_tx_confirmation_impl( port, ptr, rust_vec_len, data_len, ), - 195 => { + 206 => { wire__crate__api__voting__voting_ballot_intents_impl(port, ptr, rust_vec_len, data_len) } - 196 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), - 197 => wire__crate__api__voting__voting_commit_with_progress_impl( + 207 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 208 => wire__crate__api__voting__voting_commit_with_progress_impl( port, ptr, rust_vec_len, data_len, ), - 198 => { + 209 => { wire__crate__api__voting__voting_config_cached_impl(port, ptr, rust_vec_len, data_len) } - 199 => wire__crate__api__voting__voting_config_clear_cache_impl( + 210 => wire__crate__api__voting__voting_config_clear_cache_impl( port, ptr, rust_vec_len, data_len, ), - 200 => { + 211 => { wire__crate__api__voting__voting_config_resolve_impl(port, ptr, rust_vec_len, data_len) } - 201 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 202 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( + 212 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 213 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 203 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), - 204 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), - 205 => { + 214 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), + 215 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), + 216 => { wire__crate__api__voting__voting_eligible_weight_impl(port, ptr, rust_vec_len, data_len) } - 206 => { + 217 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 207 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 208 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + 218 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 219 => wire__crate__api__voting__voting_mark_vote_submitted_impl( port, ptr, rust_vec_len, data_len, ), - 209 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 210 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), - 211 => wire__crate__api__voting__voting_record_execution_impl( + 220 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 221 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 222 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 212 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( + 223 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 213 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( + 224 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 214 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), - 215 => { + 225 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 226 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 216 => wire__crate__api__voting__voting_reset_session_state_impl( + 227 => wire__crate__api__voting__voting_reset_session_state_impl( port, ptr, rust_vec_len, data_len, ), - 217 => wire__crate__api__voting__voting_round_params_json_impl( + 228 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 218 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 219 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), - 220 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 229 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 230 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), + 231 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 221 => wire__crate__api__voting__voting_share_add_servers_impl( + 232 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 222 => { + 233 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 223 => { + 234 => { wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) } - 224 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 225 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), - 226 => { + 235 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 236 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 237 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 227 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 238 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 228 => { + 239 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 229 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 230 => { + 240 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 241 => { wire__crate__api__voting__voting_tree_find_leaf_impl(port, ptr, rust_vec_len, data_len) } - 231 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 232 => wire__crate__api__voting__voting_vote_commitment_hex_impl( + 242 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 243 => wire__crate__api__voting__voting_vote_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 233 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( + 244 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 234 => { + 245 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -12977,21 +13376,22 @@ fn pde_ffi_dispatcher_sync_impl( 114 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 134 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 141 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 157 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 158 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 170 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 172 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 138 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 151 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 167 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 168 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 180 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 182 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 178 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 184 => { + 188 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 189 => wire__crate__api__ledger__ufvk_default_address_impl(ptr, rust_vec_len, data_len), + 195 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 185 => { + 196 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), diff --git a/rust/src/ledger/dart_device.rs b/rust/src/ledger/dart_device.rs new file mode 100644 index 000000000..bd719efec --- /dev/null +++ b/rust/src/ledger/dart_device.rs @@ -0,0 +1,116 @@ +// A Ledger reached through the Flutter side. +// +// On mobile the wallet cannot open the device itself: the BLE (and Android +// USB) connection is owned by ledger_flutter_plus on the Dart side. Rust keeps +// driving the Zcash app protocol and hands every APDU to a Dart closure, which +// sends it over the live connection and answers with the raw response, status +// word included. + +use std::sync::Arc; + +use flutter_rust_bridge::DartFnFuture; +use tonic::async_trait; + +use crate::ledger::{ + transport::{APDUAnswer, APDUCommand, Device}, + LedgerError, LedgerResult, +}; + +type Exchange = dyn Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync; + +pub struct DartDevice { + exchange: Arc<Exchange>, +} + +impl DartDevice { + pub fn new( + exchange: impl Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync + 'static, + ) -> Self { + Self { + exchange: Arc::new(exchange), + } + } +} + +#[async_trait] +impl Device for DartDevice { + async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { + let ins = command.ins; + let request = command.to_bytes()?; + tracing::debug!("ledger > ins {ins:#04x} ({} bytes)", request.len()); + let response = (self.exchange)(request).await; + // The Dart side answers an empty vector when the transport itself + // failed (disconnected device, cancelled operation); the reason is + // kept on that side and surfaced with the error. + if response.is_empty() { + return Err(LedgerError::Protocol( + "the Ledger connection was lost while talking to the device".into(), + )); + } + let answer = APDUAnswer::from_bytes(&response)?; + tracing::debug!("ledger < sw {:#06x} ({} bytes)", answer.retcode, answer.data.len()); + Ok(answer) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn device(reply: Vec<u8>) -> DartDevice { + DartDevice::new(move |_request| { + let reply = reply.clone(); + Box::pin(async move { reply }) + }) + } + + fn probe() -> APDUCommand { + APDUCommand { + cla: 0xE0, + ins: 0xC4, + p1: 0, + p2: 0, + data: vec![], + } + } + + #[tokio::test] + async fn reply_is_split_into_data_and_status_word() { + let answer = device(vec![1, 2, 3, 0x90, 0x00]).execute(probe()).await.unwrap(); + assert_eq!(answer.data, vec![1, 2, 3]); + assert_eq!(answer.retcode, 0x9000); + } + + #[tokio::test] + async fn a_bare_status_word_is_a_valid_reply() { + let answer = device(vec![0x69, 0x85]).execute(probe()).await.unwrap(); + assert!(answer.data.is_empty()); + assert_eq!(answer.retcode, 0x6985); + } + + #[tokio::test] + async fn an_empty_reply_means_the_transport_failed() { + let err = device(vec![]).execute(probe()).await.unwrap_err(); + assert!(matches!(err, LedgerError::Protocol(_))); + } + + #[tokio::test] + async fn the_request_is_a_framed_apdu() { + let seen = std::sync::Arc::new(std::sync::Mutex::new(vec![])); + let seen2 = seen.clone(); + let d = DartDevice::new(move |request| { + seen2.lock().unwrap().push(request); + Box::pin(async { vec![0x90, 0x00] }) + }); + d.execute(APDUCommand { + cla: 0xE0, + ins: 0x50, + p1: 0x80, + p2: 0x01, + data: vec![0xAA, 0xBB], + }) + .await + .unwrap(); + assert_eq!(seen.lock().unwrap()[0], vec![0xE0, 0x50, 0x80, 0x01, 2, 0xAA, 0xBB]); + } +} diff --git a/rust/src/ledger/mock.rs b/rust/src/ledger/mock.rs index 87a05d68d..4c4564335 100644 --- a/rust/src/ledger/mock.rs +++ b/rust/src/ledger/mock.rs @@ -9,8 +9,8 @@ use crate::{ }; /// Placeholder device for accounts that cannot perform device operations: -/// software accounts, builds without the `ledger` feature, and the Official -/// Ledger app whose device protocol is not implemented yet. +/// software accounts, and builds without the `ledger` feature (on mobile the +/// device is driven from Flutter through `api::ledger` instead). pub struct StubLedger { kind: HwKind, error: &'static str, @@ -34,7 +34,8 @@ impl StubLedger { pub fn official() -> Self { Self { kind: HwKind::Official, - error: "not implemented yet for the Official Ledger app", + error: "this build cannot talk to the Ledger itself; create the account from \ + a seed phrase, or from the viewing key exported by the device", } } } @@ -81,4 +82,8 @@ impl LedgerApp for StubLedger { ) -> Result<String> { anyhow::bail!("{}", self.error) } + + async fn get_ufvk(&self, _network: &Network, _aindex: u32) -> Result<String> { + anyhow::bail!("{}", self.error) + } } diff --git a/rust/src/ledger/mod.rs b/rust/src/ledger/mod.rs index f1ef22876..4f9d901b0 100644 --- a/rust/src/ledger/mod.rs +++ b/rust/src/ledger/mod.rs @@ -34,15 +34,22 @@ impl HwKind { pub mod mock; +// The Official app protocol and the APDU types build everywhere: on mobile +// the device is reached through `dart_device` (Flutter owns the connection). +// The USB HID transport and the Zondax (Sapling) app are desktop-only. +pub mod official; +pub mod official_sign; +pub mod transport; + +#[cfg(feature = "flutter")] +pub mod dart_device; + cfg_if::cfg_if! { if #[cfg(feature="ledger")] { - pub mod transport; pub mod builder; pub mod fvk; pub mod hashers; pub mod nano; - pub mod official; - pub mod official_sign; #[cfg(test)] mod tests; diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs index 1d42cdb66..058776c70 100644 --- a/rust/src/ledger/official.rs +++ b/rust/src/ledger/official.rs @@ -1,7 +1,9 @@ // Official Ledger App (LedgerHQ/app-zcash, CLA 0xE0) +#[cfg(feature = "ledger")] use anyhow::Result; use byteorder::{WriteBytesExt, BE}; +#[cfg(feature = "ledger")] use tonic::async_trait; use zcash_keys::keys::UnifiedFullViewingKey; use zcash_protocol::consensus::NetworkConstants as _; @@ -9,14 +11,19 @@ use zcash_protocol::consensus::NetworkConstants as _; use crate::{ api::coin::Network, ledger::{ - transport::{connect_ledger, APDUCommand, Device}, - HwKind, LedgerApp, LedgerError, LedgerResult, + transport::{APDUCommand, Device}, + LedgerError, LedgerResult, }, }; +#[cfg(feature = "ledger")] +use crate::ledger::{HwKind, LedgerApp}; +/// The app reached over the desktop USB HID transport. +#[cfg(feature = "ledger")] pub struct OfficialApp {} const CLA: u8 = 0xE0; +const INS_GET_FIRMWARE_VERSION: u8 = 0xC4; const INS_GET_VK: u8 = 0x50; const P1_FIRST: u8 = 0x00; const P1_CONTINUE: u8 = 0x80; @@ -34,6 +41,31 @@ fn append_path(data: &mut Vec<u8>, purpose: u32, coin_type: u32, account: u32) - Ok(()) } +/// Version of the Zcash app open on the device, as (major, minor, patch). +/// +/// GET_FIRMWARE_VERSION is the Bitcoin-app style probe the Official app +/// answers even before any key is touched, so it doubles as the "is the right +/// app open" check: any other app answers with an error status word. +pub async fn get_app_version<D: Device>(ledger: &D) -> LedgerResult<(u8, u8, u8)> { + let res = ledger + .execute(APDUCommand { + cla: CLA, + ins: INS_GET_FIRMWARE_VERSION, + p1: 0, + p2: 0, + data: vec![], + }) + .await?; + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, INS_GET_FIRMWARE_VERSION)); + } + // features, arch, major, minor, patch, ... + if res.data.len() < 5 { + return Err(LedgerError::Protocol("short version response".into())); + } + Ok((res.data[2], res.data[3], res.data[4])) +} + /// Ask the device for the account UFVK (Orchard + transparent receivers). /// The user must approve the export on the device. pub async fn get_ufvk<D: Device>(ledger: &D, network: &Network, aindex: u32) -> LedgerResult<String> { @@ -102,6 +134,7 @@ pub async fn get_ufvk<D: Device>(ledger: &D, network: &Network, aindex: u32) -> Ok(ufvk) } +#[cfg(feature = "ledger")] #[async_trait] impl LedgerApp for OfficialApp { fn kind(&self) -> HwKind { @@ -109,7 +142,105 @@ impl LedgerApp for OfficialApp { } async fn get_ufvk(&self, network: &Network, aindex: u32) -> Result<String> { - let ledger = connect_ledger().await?; + let ledger = crate::ledger::transport::connect_ledger().await?; Ok(get_ufvk(&ledger, network, aindex).await?) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Mutex; + use tonic::async_trait; + use zcash_keys::keys::UnifiedSpendingKey; + use zip32::AccountId; + + use crate::ledger::transport::APDUAnswer; + + /// Replays scripted replies and records the commands it was sent. + struct Scripted { + replies: Mutex<Vec<Vec<u8>>>, + sent: Mutex<Vec<APDUCommand>>, + } + + impl Scripted { + fn new(replies: Vec<Vec<u8>>) -> Self { + Self { + replies: Mutex::new(replies), + sent: Mutex::new(vec![]), + } + } + } + + #[async_trait] + impl Device for Scripted { + async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { + self.sent.lock().unwrap().push(command); + let mut replies = self.replies.lock().unwrap(); + if replies.is_empty() { + return Err(LedgerError::Protocol("script exhausted".into())); + } + APDUAnswer::from_bytes(&replies.remove(0)) + } + } + + fn with_sw(mut data: Vec<u8>, sw: u16) -> Vec<u8> { + data.extend_from_slice(&sw.to_be_bytes()); + data + } + + #[tokio::test] + async fn app_version_is_parsed_from_the_firmware_probe() { + // What app-zcash 3.9.3 answers to GET_FIRMWARE_VERSION. + let device = Scripted::new(vec![hex::decode("38300309030100039000").unwrap()]); + let version = get_app_version(&device).await.unwrap(); + assert_eq!(version, (3, 9, 3)); + let sent = device.sent.lock().unwrap(); + assert_eq!(sent.len(), 1); + assert_eq!((sent[0].cla, sent[0].ins), (CLA, INS_GET_FIRMWARE_VERSION)); + } + + #[tokio::test] + async fn wrong_app_fails_the_version_probe() { + let device = Scripted::new(vec![vec![0x6e, 0x01]]); + let err = get_app_version(&device).await.unwrap_err(); + assert!(matches!(err, LedgerError::Execute(0x6e01, INS_GET_FIRMWARE_VERSION))); + } + + #[tokio::test] + async fn ufvk_is_reassembled_across_continuation_chunks() { + let network = Network::Main; + let seed = [7u8; 32]; + let usk = UnifiedSpendingKey::from_seed(&network, &seed, AccountId::ZERO).unwrap(); + let ufvk = usk.to_unified_full_viewing_key().encode(&network); + let bytes = ufvk.as_bytes(); + + // len (u16 BE) || first slice, then the rest in two more chunks. + let mut first = (bytes.len() as u16).to_be_bytes().to_vec(); + first.extend_from_slice(&bytes[..100]); + let device = Scripted::new(vec![ + with_sw(first, SW_OK), + with_sw(bytes[100..180].to_vec(), SW_OK), + with_sw(bytes[180..].to_vec(), SW_OK), + ]); + + let got = get_ufvk(&device, &network, 0).await.unwrap(); + assert_eq!(got, ufvk); + + let sent = device.sent.lock().unwrap(); + assert_eq!(sent.len(), 3); + // First command carries both derivation paths for account 0. + assert_eq!(sent[0].p1, P1_FIRST); + assert_eq!(sent[0].data.len(), 26); + assert_eq!(&sent[0].data[0..5], &[3, 0x80, 0, 0, 32]); + assert_eq!(&sent[0].data[13..18], &[3, 0x80, 0, 0, 44]); + assert!(sent[1..].iter().all(|c| c.p1 == P1_CONTINUE && c.data.is_empty())); + } + + #[tokio::test] + async fn refusing_the_export_is_reported_as_such() { + let device = Scripted::new(vec![vec![0x69, 0x85]]); + let err = get_ufvk(&device, &Network::Main, 0).await.unwrap_err(); + assert!(matches!(err, LedgerError::Generic(SW_DENY, _))); + } +} diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index bc443944b..b78d3939f 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -684,6 +684,7 @@ where }) } +#[cfg(feature = "ledger")] pub async fn sign_official_transaction<S>( network: Network, sink: &S, diff --git a/rust/src/ledger/transport.rs b/rust/src/ledger/transport.rs index 193408c35..083d223ef 100644 --- a/rust/src/ledger/transport.rs +++ b/rust/src/ledger/transport.rs @@ -1,34 +1,18 @@ -use byteorder::{WriteBytesExt, BE}; -use hidapi::{HidApi, HidDevice}; +// APDU plumbing shared by every Ledger transport. +// +// The protocol code (`official`, `official_sign`, `fvk`, `builder`) only +// depends on the `Device` trait and the APDU types, which compile on every +// target. The USB HID transport below is desktop-only (hidapi) and lives +// behind the `ledger` feature; mobile builds reach the device through +// `dart_device`, where the Flutter side owns the BLE/USB connection. + +use byteorder::WriteBytesExt; use std::io::Write; -use std::sync::LazyLock; -use tokio::{ - runtime::Builder, - sync::{mpsc, oneshot, Mutex}, -}; use tonic::async_trait; -use crate::{ - ledger::{LedgerError, LedgerResult}, - IntoAnyhow, -}; - -pub fn open_ledger(api: &HidApi) -> LedgerResult<HidDevice> { - for devinfo in api.device_list() { - let vendor_id = devinfo.vendor_id(); - // Ledger devices expose two HID interfaces: the APDU one (usage page - // 0xFFA0) and a console one (0xFF00) that accepts writes but never - // answers, which would hang the wallet. - if vendor_id == 0x2C97 && devinfo.usage_page() == 0xFFA0 { - let device = devinfo.open_device(api)?; - let _ = device.set_blocking_mode(true); - return Ok(device); - } - } - Err(LedgerError::NotFound) -} +use crate::ledger::{LedgerError, LedgerResult}; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct APDUCommand { pub cla: u8, pub ins: u8, @@ -39,6 +23,12 @@ pub struct APDUCommand { impl APDUCommand { pub fn to_bytes(&self) -> LedgerResult<Vec<u8>> { + if self.data.len() > 255 { + return Err(LedgerError::Protocol(format!( + "APDU data too long: {} bytes", + self.data.len() + ))); + } let mut buffer = vec![]; buffer.write_u8(self.cla)?; buffer.write_u8(self.ins)?; @@ -50,6 +40,7 @@ impl APDUCommand { } } +#[derive(Debug)] pub struct APDUAnswer { pub data: Vec<u8>, pub retcode: u16, @@ -57,6 +48,11 @@ pub struct APDUAnswer { impl APDUAnswer { pub fn from_bytes(data: &[u8]) -> LedgerResult<Self> { + if data.len() < 2 { + return Err(LedgerError::Protocol( + "APDU response shorter than a status word".into(), + )); + } let retcode = u16::from_be_bytes([data[data.len() - 2], data[data.len() - 1]]); let mut data2 = vec![]; data2.extend_from_slice(&data[0..data.len() - 2]); @@ -67,35 +63,6 @@ impl APDUAnswer { } } -#[cfg(feature = "zemu")] -pub async fn connect_ledger() -> LedgerResult<LedgerDeviceZEMU> { - let ledger = LEDGER_ZEMU.lock().await; - Ok(ledger.clone().unwrap()) -} - -#[cfg(not(feature = "zemu"))] -pub async fn connect_ledger() -> LedgerResult<LedgerDevice> { - { - use std::ops::Deref; - - let ledger = LEDGER.lock().await; - if let Some(ledger) = ledger.deref() { - return Ok(ledger.clone()); - } - }; - let mut ledger = LEDGER.lock().await; - let device = LedgerDevice::new().await?; - *ledger = Some(device.clone()); - Ok(device) -} - -pub type ReponseChannel = oneshot::Sender<LedgerResult<APDUAnswer>>; - -#[derive(Clone)] -pub struct LedgerDevice { - tx: mpsc::Sender<(APDUCommand, ReponseChannel)>, -} - #[async_trait] pub trait Device { async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer>; @@ -150,165 +117,231 @@ pub trait Device { } } -#[async_trait] -impl Device for LedgerDevice { - async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { - self.run(command).await +#[cfg(feature = "ledger")] +pub use hid::*; + +#[cfg(feature = "ledger")] +mod hid { + use super::{APDUAnswer, APDUCommand, Device}; + use byteorder::{WriteBytesExt, BE}; + use hidapi::{HidApi, HidDevice}; + use std::io::Write; + use std::sync::LazyLock; + use tokio::{ + runtime::Builder, + sync::{mpsc, oneshot, Mutex}, + }; + use tonic::async_trait; + + use crate::{ + ledger::{LedgerError, LedgerResult}, + IntoAnyhow, + }; + + pub fn open_ledger(api: &HidApi) -> LedgerResult<HidDevice> { + for devinfo in api.device_list() { + let vendor_id = devinfo.vendor_id(); + // Ledger devices expose two HID interfaces: the APDU one (usage page + // 0xFFA0) and a console one (0xFF00) that accepts writes but never + // answers, which would hang the wallet. + if vendor_id == 0x2C97 && devinfo.usage_page() == 0xFFA0 { + let device = devinfo.open_device(api)?; + let _ = device.set_blocking_mode(true); + return Ok(device); + } + } + Err(LedgerError::NotFound) } -} -impl LedgerDevice { - pub async fn new() -> LedgerResult<Self> { - let tx = Self::start().await?; - Ok(LedgerDevice { tx }) + #[cfg(feature = "zemu")] + pub async fn connect_ledger() -> LedgerResult<LedgerDeviceZEMU> { + let ledger = LEDGER_ZEMU.lock().await; + Ok(ledger.clone().unwrap()) } - pub async fn start() -> LedgerResult<mpsc::Sender<(APDUCommand, ReponseChannel)>> { - let hidapi = HidApi::new()?; - tracing::info!("LedgerDevice::start"); - let device = open_ledger(&hidapi)?; - let (tx, mut rx) = mpsc::channel::<(APDUCommand, ReponseChannel)>(8); - // spawn a single thread worker to make sure that access to the device is serialized - std::thread::spawn(move || { - let r = Builder::new_current_thread().enable_all().build().unwrap(); - r.block_on(async move { - while let Some((command, sender)) = rx.recv().await { - let answer = async { - let c = command.to_bytes()?; - Self::write(&device, &c).await?; - let rep = Self::read(&device).await?; - let answer = APDUAnswer::from_bytes(&rep)?; - Ok::<_, LedgerError>(answer) - } - .await; - let _ = sender.send(answer); - } - }); - }); - Ok(tx) + #[cfg(not(feature = "zemu"))] + pub async fn connect_ledger() -> LedgerResult<LedgerDevice> { + { + use std::ops::Deref; + + let ledger = LEDGER.lock().await; + if let Some(ledger) = ledger.deref() { + return Ok(ledger.clone()); + } + }; + let mut ledger = LEDGER.lock().await; + let device = LedgerDevice::new().await?; + *ledger = Some(device.clone()); + Ok(device) } - pub async fn run(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { - let (tx, rx) = oneshot::channel::<LedgerResult<APDUAnswer>>(); - self.tx.send((command, tx)).await.anyhow()?; - let rep = rx.await.anyhow()?; - rep + pub type ReponseChannel = oneshot::Sender<LedgerResult<APDUAnswer>>; + + #[derive(Clone)] + pub struct LedgerDevice { + tx: mpsc::Sender<(APDUCommand, ReponseChannel)>, } - async fn write(device: &HidDevice, data: &[u8]) -> LedgerResult<()> { - // data is prefixed by its length - let mut prefixed_data = Vec::<u8>::with_capacity(data.len() + 2); - prefixed_data.write_u16::<BE>(data.len() as u16)?; - prefixed_data.write_all(data)?; - - // it is split into chunks of 64 bytes - // the first 5 bytes are the header - // channel (0x0101), tag (0x05), seqno (u16) - - // we have an extra 1 byte when we write - // it is not there when we read - let mut buffer = [0u8; 65]; // 1 byte prefix + 64 byte buffer - buffer[1] = 1; // channel - buffer[2] = 1; // channel - buffer[3] = 5; // tag - - for (idx, chunk) in prefixed_data.chunks(64 - 5).enumerate() { - let seqno = idx as u16; - buffer[4..6].copy_from_slice(&seqno.to_be_bytes()); - buffer[6..6 + chunk.len()].copy_from_slice(chunk); - device.write(&buffer)?; + #[async_trait] + impl Device for LedgerDevice { + async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { + self.run(command).await } - Ok(()) } - async fn read(device: &HidDevice) -> LedgerResult<Vec<u8>> { - let mut seqno = 0; - let mut data_len = 0; - let mut buffer = [0u8; 64]; - let mut data = vec![]; - - loop { - let size = device.read(&mut buffer)?; - // the first chunk has the total length, therefore it must be larger - if size < 5 || (seqno == 0 && size < 7) { - return Err(LedgerError::Protocol("No header".into())); - } - if buffer[0] != 1 || buffer[1] != 1 || buffer[2] != 5 { - return Err(LedgerError::Protocol("Invalid header".into())); - } - let this_seqno = u16::from_be_bytes([buffer[3], buffer[4]]); - if this_seqno != seqno { - return Err(LedgerError::Protocol("Invalid seqno".into())); - } - if seqno == 0 { - data_len = u16::from_be_bytes([buffer[5], buffer[6]]); - data.write_all(&buffer[7..size])?; - } else { - data.write_all(&buffer[5..size])?; + impl LedgerDevice { + pub async fn new() -> LedgerResult<Self> { + let tx = Self::start().await?; + Ok(LedgerDevice { tx }) + } + + pub async fn start() -> LedgerResult<mpsc::Sender<(APDUCommand, ReponseChannel)>> { + let hidapi = HidApi::new()?; + tracing::info!("LedgerDevice::start"); + let device = open_ledger(&hidapi)?; + let (tx, mut rx) = mpsc::channel::<(APDUCommand, ReponseChannel)>(8); + // spawn a single thread worker to make sure that access to the device is serialized + std::thread::spawn(move || { + let r = Builder::new_current_thread().enable_all().build().unwrap(); + r.block_on(async move { + while let Some((command, sender)) = rx.recv().await { + let answer = async { + let c = command.to_bytes()?; + Self::write(&device, &c).await?; + let rep = Self::read(&device).await?; + let answer = APDUAnswer::from_bytes(&rep)?; + Ok::<_, LedgerError>(answer) + } + .await; + let _ = sender.send(answer); + } + }); + }); + Ok(tx) + } + + pub async fn run(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { + let (tx, rx) = oneshot::channel::<LedgerResult<APDUAnswer>>(); + self.tx.send((command, tx)).await.anyhow()?; + let rep = rx.await.anyhow()?; + rep + } + + async fn write(device: &HidDevice, data: &[u8]) -> LedgerResult<()> { + // data is prefixed by its length + let mut prefixed_data = Vec::<u8>::with_capacity(data.len() + 2); + prefixed_data.write_u16::<BE>(data.len() as u16)?; + prefixed_data.write_all(data)?; + + // it is split into chunks of 64 bytes + // the first 5 bytes are the header + // channel (0x0101), tag (0x05), seqno (u16) + + // we have an extra 1 byte when we write + // it is not there when we read + let mut buffer = [0u8; 65]; // 1 byte prefix + 64 byte buffer + buffer[1] = 1; // channel + buffer[2] = 1; // channel + buffer[3] = 5; // tag + + for (idx, chunk) in prefixed_data.chunks(64 - 5).enumerate() { + let seqno = idx as u16; + buffer[4..6].copy_from_slice(&seqno.to_be_bytes()); + buffer[6..6 + chunk.len()].copy_from_slice(chunk); + device.write(&buffer)?; } - seqno += 1; - if data.len() >= data_len as usize { - break; + Ok(()) + } + + async fn read(device: &HidDevice) -> LedgerResult<Vec<u8>> { + let mut seqno = 0; + let mut data_len = 0; + let mut buffer = [0u8; 64]; + let mut data = vec![]; + + loop { + let size = device.read(&mut buffer)?; + // the first chunk has the total length, therefore it must be larger + if size < 5 || (seqno == 0 && size < 7) { + return Err(LedgerError::Protocol("No header".into())); + } + if buffer[0] != 1 || buffer[1] != 1 || buffer[2] != 5 { + return Err(LedgerError::Protocol("Invalid header".into())); + } + let this_seqno = u16::from_be_bytes([buffer[3], buffer[4]]); + if this_seqno != seqno { + return Err(LedgerError::Protocol("Invalid seqno".into())); + } + if seqno == 0 { + data_len = u16::from_be_bytes([buffer[5], buffer[6]]); + data.write_all(&buffer[7..size])?; + } else { + data.write_all(&buffer[5..size])?; + } + seqno += 1; + if data.len() >= data_len as usize { + break; + } } + data.truncate(data_len as usize); + Ok(data) } - data.truncate(data_len as usize); - Ok(data) } -} -pub static LEDGER_ZEMU: LazyLock<tokio::sync::Mutex<Option<LedgerDeviceZEMU>>> = - LazyLock::new(|| { + pub static LEDGER_ZEMU: LazyLock<tokio::sync::Mutex<Option<LedgerDeviceZEMU>>> = + LazyLock::new(|| { + #[cfg(feature = "zemu")] + { + use std::sync::Arc; + + let host = std::env::var("ZEMU_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); + let port: u16 = std::env::var("ZEMU_PORT") + .ok() + .and_then(|p| p.parse().ok()) + .unwrap_or(9999); + let device = ledger_transport_zemu::TransportZemuHttp::new(&host, port); + let ledger = LedgerDeviceZEMU { + device: Arc::new(device), + }; + tokio::sync::Mutex::new(Some(ledger)) + } + #[cfg(not(feature = "zemu"))] + tokio::sync::Mutex::new(Some(LedgerDeviceZEMU {})) + }); + + #[derive(Clone)] + pub struct LedgerDeviceZEMU { #[cfg(feature = "zemu")] - { - use std::sync::Arc; - - let host = std::env::var("ZEMU_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); - let port: u16 = std::env::var("ZEMU_PORT") - .ok() - .and_then(|p| p.parse().ok()) - .unwrap_or(9999); - let device = ledger_transport_zemu::TransportZemuHttp::new(&host, port); - let ledger = LedgerDeviceZEMU { - device: Arc::new(device), - }; - tokio::sync::Mutex::new(Some(ledger)) - } - #[cfg(not(feature = "zemu"))] - tokio::sync::Mutex::new(Some(LedgerDeviceZEMU {})) - }); + pub device: std::sync::Arc<ledger_transport_zemu::TransportZemuHttp>, + } -#[derive(Clone)] -pub struct LedgerDeviceZEMU { - #[cfg(feature = "zemu")] - pub device: std::sync::Arc<ledger_transport_zemu::TransportZemuHttp>, -} + #[async_trait] + impl Device for LedgerDeviceZEMU { + #[cfg(feature = "zemu")] + async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { + use ledger_transport::Exchange; -#[async_trait] -impl Device for LedgerDeviceZEMU { - #[cfg(feature = "zemu")] - async fn execute(&self, command: APDUCommand) -> LedgerResult<APDUAnswer> { - use ledger_transport::Exchange; - - let res = self - .device - .exchange(&ledger_transport::APDUCommand { - cla: command.cla, - ins: command.ins, - p1: command.p1, - p2: command.p2, - data: command.data.clone(), + let res = self + .device + .exchange(&ledger_transport::APDUCommand { + cla: command.cla, + ins: command.ins, + p1: command.p1, + p2: command.p2, + data: command.data.clone(), + }) + .await?; + Ok(APDUAnswer { + data: res.data().to_vec(), + retcode: res.retcode(), }) - .await?; - Ok(APDUAnswer { - data: res.data().to_vec(), - retcode: res.retcode(), - }) - } + } - #[cfg(not(feature = "zemu"))] - async fn execute(&self, _command: APDUCommand) -> LedgerResult<APDUAnswer> { - unimplemented!() + #[cfg(not(feature = "zemu"))] + async fn execute(&self, _command: APDUCommand) -> LedgerResult<APDUAnswer> { + unimplemented!() + } } -} -pub static LEDGER: LazyLock<Mutex<Option<LedgerDevice>>> = LazyLock::new(|| Mutex::new(None)); + pub static LEDGER: LazyLock<Mutex<Option<LedgerDevice>>> = LazyLock::new(|| Mutex::new(None)); +} diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 0b8499c70..375798951 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1587,7 +1587,7 @@ pub async fn sign_transaction( /// Prover and Spend Finalizer so the result can be extracted and broadcast. /// No spending keys are touched, so it is safe for watch-only accounts. pub async fn prove_and_finalize( - network: &crate::api::coin::Network, + _network: &crate::api::coin::Network, package: &PcztPackage, ) -> Result<PcztPackage> { let span = span!(Level::INFO, "transaction"); @@ -1605,17 +1605,14 @@ pub async fn prove_and_finalize( } = package; let pczt = Pczt::parse(pczt).map_err(|e| anyhow!("failed to parse PCZT: {e:?}"))?; - let ironwood_active = network.is_nu_active( - NetworkUpgrade::Nu6_3, - BlockHeight::from_u32(*pczt.global().expiry_height()), - ); - span.in_scope(|| { info!("Adding Proofs to externally signed PCZT"); }); let sapling_prover = get_sapling_prover().await?; - let orchard_pk = get_orchard_pk(network, ironwood_active); + // The proving key follows the branch the PCZT was built for (vanilla + // Orchard, ZSA or Ironwood circuits), not the current network state. + let orchard_pk = get_orchard_pk(*pczt.global().consensus_branch_id())?; let pczt = Prover::new(pczt) .create_sapling_proofs(sapling_prover, sapling_prover) .map_err(|e| anyhow!("sapling proving failed: {e:?}"))? From 5cefa04bb49efddd56fc90e767c5c8f206d633d8 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 12:20:38 -0400 Subject: [PATCH 182/189] cargokit: stop injecting the zcash_unstable=nu7 cfg The flag came with the Cake patch for the ZSA git branch of librustzcash. The crates.io releases this branch builds against reach Ironwood without it, and enabling unstable NU7 code paths in a production wallet build is not something to do by accident. Release builds stay forced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- .../cargokit/build_tool/lib/src/android_environment.dart | 2 +- rust_builder/cargokit/build_tool/lib/src/builder.dart | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rust_builder/cargokit/build_tool/lib/src/android_environment.dart b/rust_builder/cargokit/build_tool/lib/src/android_environment.dart index 264359c1f..15fc9eeda 100644 --- a/rust_builder/cargokit/build_tool/lib/src/android_environment.dart +++ b/rust_builder/cargokit/build_tool/lib/src/android_environment.dart @@ -185,7 +185,7 @@ class AndroidEnvironment { .writeAsStringSync('INPUT(-lgcc)'); } - var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? "--cfg\u001fzcash_unstable=\"nu7\""; + var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? ''; if (rustFlags.isNotEmpty) { rustFlags = '$rustFlags\x1f'; } diff --git a/rust_builder/cargokit/build_tool/lib/src/builder.dart b/rust_builder/cargokit/build_tool/lib/src/builder.dart index a5c63a45f..103ed7d85 100644 --- a/rust_builder/cargokit/build_tool/lib/src/builder.dart +++ b/rust_builder/cargokit/build_tool/lib/src/builder.dart @@ -168,9 +168,7 @@ class RustBuilder { Future<Map<String, String>> _buildEnvironment() async { if (target.android == null) { - return { - "RUSTFLAGS": '--cfg zcash_unstable="nu7"' - }; + return {}; } else { final sdkPath = environment.androidSdkPath; final ndkVersion = environment.androidNdkVersion; From ac32ca1c3ccc2f0eacb8afaf66e71e55317744cc Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 16:27:40 -0400 Subject: [PATCH 183/189] tests: drop the PCZT cross-version probe and encoding dump Both came in with the external-signer work as scratch probes. The encoding dump wrote v1/v2 encodings to /tmp for inspection and no longer compiles against pczt 0.9. The cross-version check parsed a Cupcake PCZT directly and fails (DeserializeBadOption: the fork's Ironwood/ZSA fields are not the crates.io layout), which is exactly the incompatibility the Keystone wire translation and the signatures-only replies were introduced to avoid; those paths are covered by the keystone_wire unit tests with committed fixtures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- rust/tests/cross_version_pczt.rs | 32 ------------------------- rust/tests/v1_encoding_probe.rs | 40 -------------------------------- 2 files changed, 72 deletions(-) delete mode 100644 rust/tests/cross_version_pczt.rs delete mode 100644 rust/tests/v1_encoding_probe.rs diff --git a/rust/tests/cross_version_pczt.rs b/rust/tests/cross_version_pczt.rs deleted file mode 100644 index e5ad3c7b2..000000000 --- a/rust/tests/cross_version_pczt.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Wire-compatibility check between PCZT implementations. -//! -//! This crate pins `pczt 0.7` (MrCyjaneK fork); the Cupcake airgapped signer -//! uses crates.io `pczt 0.9`. Both must read each other's bytes or the -//! airgapped flow cannot work: the signer's output has to parse here for -//! proving and broadcast. -//! -//! The fixture is a real Ironwood (NU6.3, v6) PCZT produced by the signer. - -use pczt::Pczt; - -#[test] -fn parses_a_pczt_serialized_by_the_airgapped_signer() { - let hex_text = include_str!("cupcake_ironwood_pczt.hex"); - let bytes = hex::decode(hex_text.trim()).expect("fixture is valid hex"); - - assert_eq!(&bytes[..4], b"PCZT", "fixture carries the PCZT magic"); - let version = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); - println!("fixture PCZT version: {version}"); - - match Pczt::parse(&bytes) { - Ok(pczt) => { - println!( - "parsed OK: expiry={} orchard_actions={} ironwood_actions={}", - pczt.global().expiry_height(), - pczt.orchard().actions().len(), - pczt.ironwood().actions().len(), - ); - } - Err(e) => panic!("INCOMPATIBLE: pczt 0.7 cannot parse 0.9 output: {e:?}"), - } -} diff --git a/rust/tests/v1_encoding_probe.rs b/rust/tests/v1_encoding_probe.rs deleted file mode 100644 index ab8904830..000000000 --- a/rust/tests/v1_encoding_probe.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Scratch probe: dump v1 and v2 PCZT encodings of an Orchard-anchored PCZT -//! produced by this crate's pinned `pczt` (lrz 0.7), so they can be fed to -//! another pczt version's parser. - -use pczt::roles::creator::Creator; -use zcash_protocol::consensus::BranchId; - -#[test] -fn dump_v1_and_v2_encodings() { - let branch: u32 = BranchId::Nu6.into(); - let mut out = String::new(); - - for (tag, orchard_anchor) in [("ANCHORED", [7u8; 32]), ("EMPTYPOOLS", [0u8; 32])] { - let pczt = Creator::new(branch, 10_000_000, 133, [0u8; 32], orchard_anchor) - .unwrap() - .build(); - - let v2 = pczt.clone().serialize().expect("v2 serialize"); - out.push_str(&format!("{tag}-V2 {}\n", hex::encode(&v2))); - - match pczt::v1::Pczt::try_from(pczt) { - Ok(v1) => out.push_str(&format!("{tag}-V1 {}\n", hex::encode(v1.serialize()))), - Err(e) => out.push_str(&format!("V1_ERR {tag} {:?}\n", e)), - } - } - - // A v6 (NU6.3 / Ironwood) PCZT: can it use the v1 escape hatch at all? - let branch63: u32 = BranchId::Nu6_3.into(); - let p6 = Creator::new(branch63, 10_000_000, 133, [0u8; 32], [7u8; 32]) - .unwrap() - .build(); - match pczt::v1::Pczt::try_from(p6) { - Ok(v1) => out.push_str(&format!("V6-V1 {}\n", hex::encode(v1.serialize()))), - Err(e) => out.push_str(&format!("V1_ERR V6 {:?}\n", e)), - } - - let path = std::env::var("PROBE_OUT").unwrap_or_else(|_| "/tmp/pczt_probe.txt".into()); - std::fs::write(&path, &out).unwrap(); - println!("{out}"); -} From 0c0c9b3b2be56354a0a5d5d908e5caf52070b52c Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 18:57:57 -0400 Subject: [PATCH 184/189] keystone_wire: speak the upgraded pczt encoding to Keystone and Cupcake The move to upstream zkool 6.30.0 changed the pczt this crate pins, and its v2 encoding with it: optional anchors, cv_net, nullifier, rk and cmx; a split-note seed and an asset on every Orchard/Ironwood spend and output; a ZSA note version; a trailing issuance bundle. The wire mirrors still decoded Cake's PCZTs with the old layout, so every airgapped path (Keystone single and batch, Cupcake) would misread or reject a PCZT built today. The tests kept passing only because they replay a fixture recorded before the upgrade. There are now three dialects: `cake` (a new mirror of the pinned encoding, verified byte for byte against a freshly built PCZT), `dst` (Keystone 0.8.0-rc.1, unchanged) and `src_` (the lrz 0.7 fork, which is what the Cupcake signer still parses). Translations go from Cake's dialect to each device and back: - to_keystone / from_keystone, apply_signatures, to_batch_request and apply_batch_sig_result now read and write Cake's dialect; - new to_cupcake / from_cupcake (exposed as pczt_to_cupcake and pczt_from_cupcake), since Cupcake can no longer read Cake's own bytes; - prove_and_finalize accepts a Cupcake-dialect PCZT and translates it. Nothing a device reviews is silently dropped: a spend or output carrying any asset other than ZEC, a split note, a ZSA note version or an issuance bundle is refused. The ZEC asset id the library writes on plain ZEC notes is restored on the way back, and an empty Sapling bundle (present without an anchor in the new encoding, absent in the old) maps between the two. Tests build a real shield PCZT with the pinned library and check it round trips losslessly through both devices, that the Keystone golden bytes (verified against the firmware's parser) still come out of the recorded transaction, that the pinned library parses every translated and merged result, and that a non-ZEC asset is refused. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- lib/src/rust/api/pay.dart | 13 + lib/src/rust/frb_generated.dart | 272 ++++++++------ rust/src/api/pay.rs | 17 + rust/src/frb_generated.rs | 284 +++++++++------ rust/src/keystone_wire.rs | 625 +++++++++++++++++++++++++++----- rust/src/pay/plan.rs | 11 +- 6 files changed, 912 insertions(+), 310 deletions(-) diff --git a/lib/src/rust/api/pay.dart b/lib/src/rust/api/pay.dart index 277516897..328a5521a 100644 --- a/lib/src/rust/api/pay.dart +++ b/lib/src/rust/api/pay.dart @@ -63,6 +63,19 @@ Future<Uint8List> pcztToKeystone({required List<int> pczt}) => Future<Uint8List> pcztFromKeystone({required List<int> pczt}) => RustLib.instance.api.crateApiPayPcztFromKeystone(pczt: pczt); +/// Rewrites a PCZT into the encoding the Cupcake signer reads. +/// +/// Cupcake parses PCZTs with an older `pczt` than this wallet writes; the +/// layouts share a name but not their fields, so send it this rather than the +/// wallet's own bytes. +Future<Uint8List> pcztToCupcake({required List<int> pczt}) => + RustLib.instance.api.crateApiPayPcztToCupcake(pczt: pczt); + +/// Rewrites a PCZT signed by the Cupcake signer back into the encoding this +/// wallet uses. [`prove_and_finalize`] also accepts one directly. +Future<Uint8List> pcztFromCupcake({required List<int> pczt}) => + RustLib.instance.api.crateApiPayPcztFromCupcake(pczt: pczt); + /// Takes a Keystone's signatures into the PCZT this wallet built. /// /// The device redacts prover-only fields, so its reply cannot be proved on its diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index 1294f856e..eb3d996cc 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -92,7 +92,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => 1355211904; + int get rustContentHash => -798327101; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -664,12 +664,16 @@ abstract class RustLibApi extends BaseApi { required List<int> signed, }); + Future<Uint8List> crateApiPayPcztFromCupcake({required List<int> pczt}); + Future<Uint8List> crateApiPayPcztFromKeystone({required List<int> pczt}); Future<Uint8List> crateApiPayPcztToBatchRequest({ required List<Uint8List> pczts, }); + Future<Uint8List> crateApiPayPcztToCupcake({required List<int> pczt}); + Future<Uint8List> crateApiPayPcztToKeystone({required List<int> pczt}); Future<PcztPackage> crateApiPayPrepare({ @@ -5917,7 +5921,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future<Uint8List> crateApiPayPcztFromKeystone({required List<int> pczt}) { + Future<Uint8List> crateApiPayPcztFromCupcake({required List<int> pczt}) { return handler.executeNormal( NormalTask( callFfi: (port_) { @@ -5934,6 +5938,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { decodeSuccessData: sse_decode_list_prim_u_8_strict, decodeErrorData: sse_decode_AnyhowException, ), + constMeta: kCrateApiPayPcztFromCupcakeConstMeta, + argValues: [pczt], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztFromCupcakeConstMeta => + const TaskConstMeta(debugName: "pczt_from_cupcake", argNames: ["pczt"]); + + @override + Future<Uint8List> crateApiPayPcztFromKeystone({required List<int> pczt}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(pczt, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 142, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), constMeta: kCrateApiPayPcztFromKeystoneConstMeta, argValues: [pczt], apiImpl: this, @@ -5956,7 +5988,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 142, + funcId: 143, port: port_, ); }, @@ -5977,6 +6009,34 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["pczts"], ); + @override + Future<Uint8List> crateApiPayPcztToCupcake({required List<int> pczt}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(pczt, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 144, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiPayPcztToCupcakeConstMeta, + argValues: [pczt], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiPayPcztToCupcakeConstMeta => + const TaskConstMeta(debugName: "pczt_to_cupcake", argNames: ["pczt"]); + @override Future<Uint8List> crateApiPayPcztToKeystone({required List<int> pczt}) { return handler.executeNormal( @@ -5987,7 +6047,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 143, + funcId: 145, port: port_, ); }, @@ -6021,7 +6081,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 144, + funcId: 146, port: port_, ); }, @@ -6057,7 +6117,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 145, + funcId: 147, port: port_, ); }, @@ -6089,7 +6149,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 146, + funcId: 148, port: port_, ); }, @@ -6121,7 +6181,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 147, + funcId: 149, port: port_, ); }, @@ -6158,7 +6218,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 148, + funcId: 150, port: port_, ); }, @@ -6188,7 +6248,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 149, + funcId: 151, port: port_, ); }, @@ -6215,7 +6275,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 150, + funcId: 152, port: port_, ); }, @@ -6247,7 +6307,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 151, + funcId: 153, )!; }, codec: SseCodec( @@ -6281,7 +6341,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 152, + funcId: 154, port: port_, ); }, @@ -6316,7 +6376,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 153, + funcId: 155, port: port_, ); }, @@ -6348,7 +6408,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 154, + funcId: 156, port: port_, ); }, @@ -6385,7 +6445,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 155, + funcId: 157, port: port_, ); }, @@ -6422,7 +6482,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 156, + funcId: 158, port: port_, ); }, @@ -6453,7 +6513,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 157, + funcId: 159, port: port_, ); }, @@ -6482,7 +6542,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 158, + funcId: 160, port: port_, ); }, @@ -6514,7 +6574,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 159, + funcId: 161, port: port_, ); }, @@ -6547,7 +6607,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 160, + funcId: 162, port: port_, ); }, @@ -6580,7 +6640,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 161, + funcId: 163, port: port_, ); }, @@ -6617,7 +6677,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 162, + funcId: 164, port: port_, ); }, @@ -6653,7 +6713,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 163, + funcId: 165, port: port_, ); }, @@ -6687,7 +6747,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 164, + funcId: 166, port: port_, ); }, @@ -6723,7 +6783,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 165, + funcId: 167, port: port_, ); }, @@ -6765,7 +6825,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 166, + funcId: 168, port: port_, ); }, @@ -6795,7 +6855,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 167, + funcId: 169, )!; }, codec: SseCodec( @@ -6823,7 +6883,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 168, + funcId: 170, )!; }, codec: SseCodec( @@ -6857,7 +6917,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 169, + funcId: 171, port: port_, ); }, @@ -6894,7 +6954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 170, + funcId: 172, port: port_, ); }, @@ -6931,7 +6991,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 171, + funcId: 173, port: port_, ); }, @@ -6968,7 +7028,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 172, + funcId: 174, port: port_, ); }, @@ -6999,7 +7059,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 173, + funcId: 175, port: port_, ); }, @@ -7032,7 +7092,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 174, + funcId: 176, port: port_, ); }, @@ -7070,7 +7130,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 175, + funcId: 177, port: port_, ); }, @@ -7107,7 +7167,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 176, + funcId: 178, port: port_, ); }, @@ -7137,7 +7197,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 177, + funcId: 179, port: port_, ); }, @@ -7175,7 +7235,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 178, + funcId: 180, port: port_, ); }, @@ -7222,7 +7282,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 179, + funcId: 181, port: port_, ); }, @@ -7273,7 +7333,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 180, + funcId: 182, )!; }, codec: SseCodec( @@ -7300,7 +7360,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 181, + funcId: 183, port: port_, ); }, @@ -7332,7 +7392,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 182, + funcId: 184, )!; }, codec: SseCodec( @@ -7361,7 +7421,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 183, + funcId: 185, port: port_, ); }, @@ -7388,7 +7448,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 184, + funcId: 186, port: port_, ); }, @@ -7415,7 +7475,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 185, + funcId: 187, port: port_, ); }, @@ -7442,7 +7502,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 186, + funcId: 188, port: port_, ); }, @@ -7469,7 +7529,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 187, + funcId: 189, port: port_, ); }, @@ -7503,7 +7563,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 188, + funcId: 190, )!; }, codec: SseCodec( @@ -7536,7 +7596,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 189, + funcId: 191, )!; }, codec: SseCodec( @@ -7566,7 +7626,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 190, + funcId: 192, port: port_, ); }, @@ -7594,7 +7654,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 191, + funcId: 193, port: port_, ); }, @@ -7626,7 +7686,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 192, + funcId: 194, port: port_, ); }, @@ -7667,7 +7727,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 193, + funcId: 195, port: port_, ); }, @@ -7704,7 +7764,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 194, + funcId: 196, port: port_, ); }, @@ -7735,7 +7795,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 195, + funcId: 197, )!; }, codec: SseCodec( @@ -7769,7 +7829,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 196, + funcId: 198, )!; }, codec: SseCodec( @@ -7803,7 +7863,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 197, + funcId: 199, port: port_, ); }, @@ -7840,7 +7900,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 198, + funcId: 200, port: port_, ); }, @@ -7877,7 +7937,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 199, + funcId: 201, port: port_, ); }, @@ -7914,7 +7974,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 200, + funcId: 202, port: port_, ); }, @@ -7953,7 +8013,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 201, + funcId: 203, port: port_, ); }, @@ -7990,7 +8050,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 202, + funcId: 204, port: port_, ); }, @@ -8027,7 +8087,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 203, + funcId: 205, port: port_, ); }, @@ -8064,7 +8124,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 204, + funcId: 206, port: port_, ); }, @@ -8101,7 +8161,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 205, + funcId: 207, port: port_, ); }, @@ -8136,7 +8196,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 206, + funcId: 208, port: port_, ); }, @@ -8177,7 +8237,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 207, + funcId: 209, port: port_, ); }, @@ -8223,7 +8283,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 208, + funcId: 210, port: port_, ); }, @@ -8267,7 +8327,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 209, + funcId: 211, port: port_, ); }, @@ -8298,7 +8358,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 210, + funcId: 212, port: port_, ); }, @@ -8333,7 +8393,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 211, + funcId: 213, port: port_, ); }, @@ -8376,7 +8436,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 212, + funcId: 214, port: port_, ); }, @@ -8420,7 +8480,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 213, + funcId: 215, port: port_, ); }, @@ -8455,7 +8515,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 214, + funcId: 216, port: port_, ); }, @@ -8492,7 +8552,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 215, + funcId: 217, port: port_, ); }, @@ -8527,7 +8587,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 216, + funcId: 218, port: port_, ); }, @@ -8558,7 +8618,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 217, + funcId: 219, port: port_, ); }, @@ -8586,7 +8646,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 218, + funcId: 220, port: port_, ); }, @@ -8624,7 +8684,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 219, + funcId: 221, port: port_, ); }, @@ -8663,7 +8723,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 220, + funcId: 222, port: port_, ); }, @@ -8700,7 +8760,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 221, + funcId: 223, port: port_, ); }, @@ -8744,7 +8804,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 222, + funcId: 224, port: port_, ); }, @@ -8799,7 +8859,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 223, + funcId: 225, port: port_, ); }, @@ -8845,7 +8905,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 224, + funcId: 226, port: port_, ); }, @@ -8894,7 +8954,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 225, + funcId: 227, port: port_, ); }, @@ -8929,7 +8989,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 226, + funcId: 228, port: port_, ); }, @@ -8964,7 +9024,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 227, + funcId: 229, port: port_, ); }, @@ -9007,7 +9067,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 228, + funcId: 230, port: port_, ); }, @@ -9052,7 +9112,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 229, + funcId: 231, port: port_, ); }, @@ -9084,7 +9144,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 230, + funcId: 232, port: port_, ); }, @@ -9127,7 +9187,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 231, + funcId: 233, port: port_, ); }, @@ -9177,7 +9237,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 232, + funcId: 234, port: port_, ); }, @@ -9225,7 +9285,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 233, + funcId: 235, port: port_, ); }, @@ -9260,7 +9320,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 234, + funcId: 236, port: port_, ); }, @@ -9305,7 +9365,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 235, + funcId: 237, port: port_, ); }, @@ -9366,7 +9426,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 236, + funcId: 238, port: port_, ); }, @@ -9427,7 +9487,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 237, + funcId: 239, port: port_, ); }, @@ -9479,7 +9539,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 238, + funcId: 240, port: port_, ); }, @@ -9524,7 +9584,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 239, + funcId: 241, port: port_, ); }, @@ -9577,7 +9637,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 240, + funcId: 242, port: port_, ); }, @@ -9614,7 +9674,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 241, + funcId: 243, port: port_, ); }, @@ -9653,7 +9713,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 242, + funcId: 244, port: port_, ); }, @@ -9692,7 +9752,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 243, + funcId: 245, port: port_, ); }, @@ -9731,7 +9791,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 244, + funcId: 246, port: port_, ); }, @@ -9770,7 +9830,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 245, + funcId: 247, port: port_, ); }, diff --git a/rust/src/api/pay.rs b/rust/src/api/pay.rs index 84785fd47..de85c8137 100644 --- a/rust/src/api/pay.rs +++ b/rust/src/api/pay.rs @@ -128,6 +128,23 @@ pub fn pczt_from_keystone(pczt: Vec<u8>) -> Result<Vec<u8>> { crate::keystone_wire::from_keystone(&pczt).map_err(|e| anyhow::anyhow!(e)) } +/// Rewrites a PCZT into the encoding the Cupcake signer reads. +/// +/// Cupcake parses PCZTs with an older `pczt` than this wallet writes; the +/// layouts share a name but not their fields, so send it this rather than the +/// wallet's own bytes. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_to_cupcake(pczt: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::to_cupcake(&pczt).map_err(|e| anyhow::anyhow!(e)) +} + +/// Rewrites a PCZT signed by the Cupcake signer back into the encoding this +/// wallet uses. [`prove_and_finalize`] also accepts one directly. +#[cfg_attr(feature = "flutter", frb)] +pub fn pczt_from_cupcake(pczt: Vec<u8>) -> Result<Vec<u8>> { + crate::keystone_wire::from_cupcake(&pczt).map_err(|e| anyhow::anyhow!(e)) +} + /// Takes a Keystone's signatures into the PCZT this wallet built. /// /// The device redacts prover-only fields, so its reply cannot be proved on its diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index b638ab6c7..9890c2d43 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1355211904; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -798327101; // Section: executor @@ -5523,6 +5523,41 @@ fn wire__crate__api__pay__pczt_apply_keystone_signatures_impl( }, ) } +fn wire__crate__api__pay__pczt_from_cupcake_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_from_cupcake", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczt = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_from_cupcake(api_pczt)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} fn wire__crate__api__pay__pczt_from_keystone_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -5593,6 +5628,41 @@ fn wire__crate__api__pay__pczt_to_batch_request_impl( }, ) } +fn wire__crate__api__pay__pczt_to_cupcake_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "pczt_to_cupcake", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_pczt = <Vec<u8>>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::pay::pczt_to_cupcake(api_pczt)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} fn wire__crate__api__pay__pczt_to_keystone_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -13088,257 +13158,259 @@ fn pde_ffi_dispatcher_primary_impl( rust_vec_len, data_len, ), - 141 => wire__crate__api__pay__pczt_from_keystone_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__pay__pczt_to_batch_request_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__pay__pczt_to_keystone_impl(port, ptr, rust_vec_len, data_len), - 144 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 146 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 147 => wire__crate__api__pay__prove_and_finalize_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 150 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 153 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 154 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 155 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 159 => { + 141 => wire__crate__api__pay__pczt_from_cupcake_impl(port, ptr, rust_vec_len, data_len), + 142 => wire__crate__api__pay__pczt_from_keystone_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__pay__pczt_to_batch_request_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__pay__pczt_to_cupcake_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__pay__pczt_to_keystone_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__pay__prove_and_finalize_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 151 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 152 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 154 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 155 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 159 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 160 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 161 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 160 => wire__crate__api__openalias__resolve_openalias_all_impl( + 162 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 161 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 163 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 162 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 163 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 164 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 169 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 170 => { + 164 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 165 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 171 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 172 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 171 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 172 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 173 => wire__crate__api__account__show_ledger_sapling_address_impl( + 173 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 174 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 175 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 174 => wire__crate__api__account__show_ledger_transparent_address_impl( + 176 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 175 => wire__crate__api__account__sign_ledger_transaction_impl( + 177 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 176 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 177 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 178 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 179 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 181 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 183 => { + 178 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 179 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 180 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 181 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 183 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 185 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 184 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 185 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 186 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 187 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 190 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 191 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 192 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 193 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 194 => wire__crate__api__transaction__update_historical_prices_impl( + 186 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 187 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 188 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 189 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 192 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 193 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 194 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 195 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 196 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, data_len, ), - 197 => { + 199 => { wire__crate__api__voting__votechain_list_rounds_impl(port, ptr, rust_vec_len, data_len) } - 198 => wire__crate__api__voting__votechain_resubmit_share_impl( + 200 => wire__crate__api__voting__votechain_resubmit_share_impl( port, ptr, rust_vec_len, data_len, ), - 199 => { + 201 => { wire__crate__api__voting__votechain_round_status_impl(port, ptr, rust_vec_len, data_len) } - 200 => { + 202 => { wire__crate__api__voting__votechain_round_tally_impl(port, ptr, rust_vec_len, data_len) } - 201 => { + 203 => { wire__crate__api__voting__votechain_share_status_impl(port, ptr, rust_vec_len, data_len) } - 202 => wire__crate__api__voting__votechain_submit_delegation_impl( + 204 => wire__crate__api__voting__votechain_submit_delegation_impl( port, ptr, rust_vec_len, data_len, ), - 203 => { + 205 => { wire__crate__api__voting__votechain_submit_share_impl(port, ptr, rust_vec_len, data_len) } - 204 => { + 206 => { wire__crate__api__voting__votechain_submit_vote_impl(port, ptr, rust_vec_len, data_len) } - 205 => wire__crate__api__voting__votechain_tx_confirmation_impl( + 207 => wire__crate__api__voting__votechain_tx_confirmation_impl( port, ptr, rust_vec_len, data_len, ), - 206 => { + 208 => { wire__crate__api__voting__voting_ballot_intents_impl(port, ptr, rust_vec_len, data_len) } - 207 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), - 208 => wire__crate__api__voting__voting_commit_with_progress_impl( + 209 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 210 => wire__crate__api__voting__voting_commit_with_progress_impl( port, ptr, rust_vec_len, data_len, ), - 209 => { + 211 => { wire__crate__api__voting__voting_config_cached_impl(port, ptr, rust_vec_len, data_len) } - 210 => wire__crate__api__voting__voting_config_clear_cache_impl( + 212 => wire__crate__api__voting__voting_config_clear_cache_impl( port, ptr, rust_vec_len, data_len, ), - 211 => { + 213 => { wire__crate__api__voting__voting_config_resolve_impl(port, ptr, rust_vec_len, data_len) } - 212 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 213 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( + 214 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 215 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 214 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), - 215 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), - 216 => { + 216 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), + 217 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), + 218 => { wire__crate__api__voting__voting_eligible_weight_impl(port, ptr, rust_vec_len, data_len) } - 217 => { + 219 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 218 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 219 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + 220 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 221 => wire__crate__api__voting__voting_mark_vote_submitted_impl( port, ptr, rust_vec_len, data_len, ), - 220 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 221 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), - 222 => wire__crate__api__voting__voting_record_execution_impl( + 222 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 223 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 224 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 223 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( + 225 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 224 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( + 226 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 225 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), - 226 => { + 227 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 228 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 227 => wire__crate__api__voting__voting_reset_session_state_impl( + 229 => wire__crate__api__voting__voting_reset_session_state_impl( port, ptr, rust_vec_len, data_len, ), - 228 => wire__crate__api__voting__voting_round_params_json_impl( + 230 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 229 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 230 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), - 231 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 231 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 232 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), + 233 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 232 => wire__crate__api__voting__voting_share_add_servers_impl( + 234 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 233 => { + 235 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 234 => { + 236 => { wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) } - 235 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 236 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), - 237 => { + 237 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 238 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 239 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 238 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 240 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 239 => { + 241 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 240 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 241 => { + 242 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 243 => { wire__crate__api__voting__voting_tree_find_leaf_impl(port, ptr, rust_vec_len, data_len) } - 242 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 243 => wire__crate__api__voting__voting_vote_commitment_hex_impl( + 244 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 245 => wire__crate__api__voting__voting_vote_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 244 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( + 246 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 245 => { + 247 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -13377,21 +13449,21 @@ fn pde_ffi_dispatcher_sync_impl( wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } 138 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 151 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 167 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 168 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 180 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 182 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 153 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 169 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 170 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 182 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 184 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 188 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 189 => wire__crate__api__ledger__ufvk_default_address_impl(ptr, rust_vec_len, data_len), - 195 => { + 190 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 191 => wire__crate__api__ledger__ufvk_default_address_impl(ptr, rust_vec_len, data_len), + 197 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 196 => { + 198 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), diff --git a/rust/src/keystone_wire.rs b/rust/src/keystone_wire.rs index b427abd75..5c00d9e8b 100644 --- a/rust/src/keystone_wire.rs +++ b/rust/src/keystone_wire.rs @@ -1,17 +1,22 @@ -//! Wire mirrors of the two PCZT v2 dialects. +//! Wire mirrors of the PCZT v2 dialects Cake has to speak. //! -//! Cake speaks the `lrz` fork of `pczt` 0.7; a Keystone running Cypherpunk -//! firmware speaks 0.8.0-rc.1. Both call their encoding "v2", but six fields -//! differ, so a PCZT written by one is misread by the other -- silently, since -//! nothing is malformed, only misaligned. Translating at the QR boundary keeps -//! Cake on its own dialect while handing the device one it can read. +//! Three encodings all call themselves "v2" and differ only in which fields +//! exist and which are optional: +//! +//! - [`cake`]: the `pczt` this crate pins, which every PCZT the wallet builds +//! is written in; +//! - [`dst`]: `pczt` 0.8.0-rc.1, what a Keystone running Cypherpunk firmware +//! reads; +//! - [`src_`]: the `lrz` fork of `pczt` 0.7, what the Cupcake signer reads +//! (and what Cake itself wrote before its `pczt` upgrade). //! //! postcard is not self-describing: fields are positional and typed by the //! compiled-in schema, so an `Option<T>` writes a tag byte that a bare `T` -//! does not. Cake's `pczt` (lrz 0.7) and Keystone's (0.8.0-rc.1) disagree on -//! exactly six fields, which is enough to shift every following byte. These -//! mirrors exist so the two layouts can be read and written independently of -//! either crate's private types. +//! does not, and one extra field shifts every byte after it. A PCZT written in +//! one dialect is misread by the others -- silently, since nothing is +//! malformed, only misaligned. These mirrors exist so each layout can be read +//! and written independently of any crate's private types, and the +//! translation happens at the QR boundary. use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -85,7 +90,99 @@ pub enum NoteVersion { V3, } -// ---- source dialect: lrz 0.7 ----------------------------------------- +// ---- Cake's dialect: the `pczt` this crate pins ------------------------ +// +// The encoding every PCZT this wallet builds is written in. It is the +// Keystone dialect plus the ZSA fields (a split-note seed and an asset on each +// spend and output, a ZSA note version, a trailing issuance bundle) that plain +// ZEC transactions leave empty. + +pub mod cake { + use super::*; + + #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] + pub enum NoteVersion { + V2, + V3, + V3Zsa, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct OrchardBundle { + pub actions: Vec<Action>, + pub flags: u8, + pub value_sum: (u64, bool), + pub anchor: Option<[u8; 32]>, + pub note_version: NoteVersion, + pub zkproof: Option<Vec<u8>>, + pub bsk: Option<[u8; 32]>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Action { + pub cv_net: Option<[u8; 32]>, + pub spend: Spend, + pub output: Output, + pub rcv: Option<[u8; 32]>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Spend { + #[serde_as(as = "Option<[_; 32]>")] + pub nullifier: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 32]>")] + pub rk: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 64]>")] + pub spend_auth_sig: Option<[u8; 64]>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rho: Option<[u8; 32]>, + pub rseed: Option<[u8; 32]>, + pub rseed_split_note: Option<[u8; 32]>, + #[serde_as(as = "Option<[_; 96]>")] + pub fvk: Option<[u8; 96]>, + pub witness: Option<(u32, [[u8; 32]; 32])>, + pub alpha: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub dummy_sk: Option<[u8; 32]>, + pub proprietary: BTreeMap<String, Vec<u8>>, + pub asset: Option<[u8; 32]>, + } + + #[serde_as] + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Output { + #[serde_as(as = "Option<[_; 32]>")] + pub cmx: Option<[u8; 32]>, + pub ephemeral_key: [u8; 32], + pub enc_ciphertext: super::dst::EncCiphertext, + pub out_ciphertext: Vec<u8>, + #[serde_as(as = "Option<[_; 43]>")] + pub recipient: Option<[u8; 43]>, + pub value: Option<u64>, + pub rseed: Option<[u8; 32]>, + pub ock: Option<[u8; 32]>, + pub zip32_derivation: Option<Zip32Derivation>, + pub user_address: Option<String>, + pub proprietary: BTreeMap<String, Vec<u8>>, + pub asset: Option<[u8; 32]>, + } + + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct Pczt { + pub global: Global, + pub transparent: Option<TransparentBundle>, + pub sapling: Option<super::dst::SaplingBundle>, + pub orchard: Option<OrchardBundle>, + pub ironwood: Option<OrchardBundle>, + #[serde(default)] + pub issue: Option<super::src_::IssueBundle>, + } +} + +// ---- Cupcake dialect: lrz 0.7 (Cake's own before its pczt upgrade) ---- pub mod src_ { use super::*; @@ -179,7 +276,7 @@ pub mod src_ { pub struct IssueBundle {} } -// ---- target dialect: 0.8.0-rc.1 (what Keystone reads) ----------------- +// ---- Keystone dialect: 0.8.0-rc.1 ------------------------------------- pub mod dst { use super::*; @@ -275,32 +372,145 @@ pub mod dst { const MAGIC: [u8; 4] = *b"PCZT"; const V2: u32 = 2; -fn to_dst_orchard(b: src_::OrchardBundle) -> dst::OrchardBundle { - dst::OrchardBundle { +/// The ZEC asset id, which the pinned `pczt` writes on every plain-ZEC spend +/// and output. The device dialects have no asset field. +fn zec_asset() -> [u8; 32] { + orchard::note::AssetBase::zatoshi().to_bytes() +} + +/// Accepts an asset only if it is ZEC (or absent), so dropping it on the way +/// to a device cannot hide a shielded asset transfer from its review. +fn require_zec(asset: Option<[u8; 32]>, what: &str) -> Result<(), String> { + match asset { + None => Ok(()), + Some(a) if a == zec_asset() => Ok(()), + Some(_) => Err(format!("{what} carries a shielded asset this device cannot sign")), + } +} + +fn need(v: Option<[u8; 32]>, what: &str) -> Result<[u8; 32], String> { + v.ok_or_else(|| format!("the PCZT is missing {what}")) +} + +fn cake_note_version(v: cake::NoteVersion) -> Result<NoteVersion, String> { + match v { + cake::NoteVersion::V2 => Ok(NoteVersion::V2), + cake::NoteVersion::V3 => Ok(NoteVersion::V3), + cake::NoteVersion::V3Zsa => Err("shielded asset notes cannot be signed by this device".into()), + } +} + +fn from_note_version(v: NoteVersion) -> cake::NoteVersion { + match v { + NoteVersion::V2 => cake::NoteVersion::V2, + NoteVersion::V3 => cake::NoteVersion::V3, + } +} + +/// Checks the parts of a PCZT no device dialect can carry: split notes, +/// non-ZEC assets are checked per action; this covers the bundle level. +fn check_device_signable(p: &cake::Pczt) -> Result<(), String> { + if p.issue.is_some() { + return Err("asset issuance cannot be signed by this device".into()); + } + if p + .sapling + .as_ref() + .is_some_and(|s| !s.spends.is_empty() || !s.outputs.is_empty()) + { + return Err("Sapling bundles cannot be signed by this device".into()); + } + Ok(()) +} + +fn read_cake(bytes: &[u8], what: &str) -> Result<cake::Pczt, String> { + postcard::from_bytes(split_header(bytes)?).map_err(|e| format!("could not read {what}: {e:?}")) +} + +// ---- Cake <-> Keystone (dst) ------------------------------------------ + +fn cake_to_dst_orchard(b: cake::OrchardBundle) -> Result<dst::OrchardBundle, String> { + Ok(dst::OrchardBundle { actions: b .actions .into_iter() - .map(|a| dst::Action { - cv_net: Some(a.cv_net), - spend: dst::Spend { - nullifier: Some(a.spend.nullifier), - rk: Some(a.spend.rk), + .map(|a| { + if a.spend.rseed_split_note.is_some() { + return Err("split notes cannot be signed by this device".to_string()); + } + require_zec(a.spend.asset, "a spend")?; + require_zec(a.output.asset, "an output")?; + Ok(dst::Action { + cv_net: a.cv_net, + spend: dst::Spend { + nullifier: a.spend.nullifier, + rk: a.spend.rk, + spend_auth_sig: a.spend.spend_auth_sig, + recipient: a.spend.recipient, + value: a.spend.value, + rho: a.spend.rho, + rseed: a.spend.rseed, + fvk: a.spend.fvk, + witness: a.spend.witness, + alpha: a.spend.alpha, + zip32_derivation: a.spend.zip32_derivation, + dummy_sk: a.spend.dummy_sk, + proprietary: a.spend.proprietary, + }, + output: dst::Output { + cmx: a.output.cmx, + ephemeral_key: a.output.ephemeral_key, + enc_ciphertext: a.output.enc_ciphertext, + out_ciphertext: a.output.out_ciphertext, + recipient: a.output.recipient, + value: a.output.value, + rseed: a.output.rseed, + ock: a.output.ock, + zip32_derivation: a.output.zip32_derivation, + user_address: a.output.user_address, + proprietary: a.output.proprietary, + }, + rcv: a.rcv, + }) + }) + .collect::<Result<Vec<_>, String>>()?, + flags: b.flags, + value_sum: b.value_sum, + anchor: b.anchor, + note_version: cake_note_version(b.note_version)?, + zkproof: b.zkproof, + bsk: b.bsk, + }) +} + +fn dst_to_cake_orchard(b: dst::OrchardBundle) -> cake::OrchardBundle { + cake::OrchardBundle { + actions: b + .actions + .into_iter() + .map(|a| cake::Action { + cv_net: a.cv_net, + spend: cake::Spend { + nullifier: a.spend.nullifier, + rk: a.spend.rk, spend_auth_sig: a.spend.spend_auth_sig, recipient: a.spend.recipient, value: a.spend.value, rho: a.spend.rho, rseed: a.spend.rseed, + rseed_split_note: None, fvk: a.spend.fvk, witness: a.spend.witness, alpha: a.spend.alpha, zip32_derivation: a.spend.zip32_derivation, dummy_sk: a.spend.dummy_sk, proprietary: a.spend.proprietary, + asset: Some(zec_asset()), }, - output: dst::Output { - cmx: Some(a.output.cmx), + output: cake::Output { + cmx: a.output.cmx, ephemeral_key: a.output.ephemeral_key, - enc_ciphertext: dst::EncCiphertext::Encrypted(a.output.enc_ciphertext), + enc_ciphertext: a.output.enc_ciphertext, out_ciphertext: a.output.out_ciphertext, recipient: a.output.recipient, value: a.output.value, @@ -309,35 +519,38 @@ fn to_dst_orchard(b: src_::OrchardBundle) -> dst::OrchardBundle { zip32_derivation: a.output.zip32_derivation, user_address: a.output.user_address, proprietary: a.output.proprietary, + asset: Some(zec_asset()), }, rcv: a.rcv, }) .collect(), flags: b.flags, value_sum: b.value_sum, - anchor: Some(b.anchor), - note_version: b.note_version, + anchor: b.anchor, + note_version: from_note_version(b.note_version), zkproof: b.zkproof, bsk: b.bsk, } } -fn to_src_orchard(b: dst::OrchardBundle) -> Result<src_::OrchardBundle, String> { - // The signer only ever fills fields in, so anything absent here means the - // returned PCZT is not one this side can carry back. - fn need(v: Option<[u8; 32]>, what: &str) -> Result<[u8; 32], String> { - v.ok_or_else(|| format!("signed PCZT is missing {what}")) - } +// ---- Cake <-> Cupcake (src_, lrz 0.7) --------------------------------- + +fn cake_to_src_orchard(b: cake::OrchardBundle) -> Result<src_::OrchardBundle, String> { Ok(src_::OrchardBundle { actions: b .actions .into_iter() .map(|a| { + if a.spend.rseed_split_note.is_some() { + return Err("split notes cannot be signed by this device".to_string()); + } + require_zec(a.spend.asset, "a spend")?; + require_zec(a.output.asset, "an output")?; Ok(src_::Action { - cv_net: need(a.cv_net, "action cv_net")?, + cv_net: need(a.cv_net, "an action's cv_net")?, spend: src_::Spend { - nullifier: need(a.spend.nullifier, "spend nullifier")?, - rk: need(a.spend.rk, "spend rk")?, + nullifier: need(a.spend.nullifier, "a spend nullifier")?, + rk: need(a.spend.rk, "a spend rk")?, spend_auth_sig: a.spend.spend_auth_sig, recipient: a.spend.recipient, value: a.spend.value, @@ -351,12 +564,12 @@ fn to_src_orchard(b: dst::OrchardBundle) -> Result<src_::OrchardBundle, String> proprietary: a.spend.proprietary, }, output: src_::Output { - cmx: need(a.output.cmx, "output cmx")?, + cmx: need(a.output.cmx, "an output cmx")?, ephemeral_key: a.output.ephemeral_key, enc_ciphertext: match a.output.enc_ciphertext { dst::EncCiphertext::Encrypted(c) => c, dst::EncCiphertext::MemoPlaintext(_) => { - return Err("signed PCZT left a memo unresolved".into()) + return Err("the PCZT left a memo unencrypted".into()) } }, out_ciphertext: a.output.out_ciphertext, @@ -374,13 +587,63 @@ fn to_src_orchard(b: dst::OrchardBundle) -> Result<src_::OrchardBundle, String> .collect::<Result<Vec<_>, String>>()?, flags: b.flags, value_sum: b.value_sum, - anchor: need(b.anchor, "bundle anchor")?, - note_version: b.note_version, + anchor: need(b.anchor, "a bundle anchor")?, + note_version: cake_note_version(b.note_version)?, zkproof: b.zkproof, bsk: b.bsk, }) } +fn src_to_cake_orchard(b: src_::OrchardBundle) -> cake::OrchardBundle { + cake::OrchardBundle { + actions: b + .actions + .into_iter() + .map(|a| cake::Action { + cv_net: Some(a.cv_net), + spend: cake::Spend { + nullifier: Some(a.spend.nullifier), + rk: Some(a.spend.rk), + spend_auth_sig: a.spend.spend_auth_sig, + recipient: a.spend.recipient, + value: a.spend.value, + rho: a.spend.rho, + rseed: a.spend.rseed, + rseed_split_note: None, + fvk: a.spend.fvk, + witness: a.spend.witness, + alpha: a.spend.alpha, + zip32_derivation: a.spend.zip32_derivation, + dummy_sk: a.spend.dummy_sk, + proprietary: a.spend.proprietary, + asset: Some(zec_asset()), + }, + output: cake::Output { + cmx: Some(a.output.cmx), + ephemeral_key: a.output.ephemeral_key, + enc_ciphertext: dst::EncCiphertext::Encrypted(a.output.enc_ciphertext), + out_ciphertext: a.output.out_ciphertext, + recipient: a.output.recipient, + value: a.output.value, + rseed: a.output.rseed, + ock: a.output.ock, + zip32_derivation: a.output.zip32_derivation, + user_address: a.output.user_address, + proprietary: a.output.proprietary, + asset: Some(zec_asset()), + }, + rcv: a.rcv, + }) + .collect(), + flags: b.flags, + value_sum: b.value_sum, + anchor: Some(b.anchor), + note_version: from_note_version(b.note_version), + zkproof: b.zkproof, + bsk: b.bsk, + } +} + fn split_header(bytes: &[u8]) -> Result<&[u8], String> { if bytes.len() < 8 || bytes[..4] != MAGIC { return Err("not a PCZT".into()); @@ -403,30 +666,25 @@ fn with_header<T: serde::Serialize>(body: &T, hint: usize) -> Result<Vec<u8>, St /// reads, without the framing header. The batch request carries these /// headerless; [`to_keystone`] wraps a single one for the legacy path. fn to_dst_pczt(bytes: &[u8]) -> Result<dst::Pczt, String> { - let src: src_::Pczt = postcard::from_bytes(split_header(bytes)?) - .map_err(|e| format!("could not read this PCZT: {e:?}"))?; - if src - .sapling - .as_ref() - .is_some_and(|s| !s.spends.is_empty() || !s.outputs.is_empty()) - { - return Err("Sapling bundles cannot be signed by this device".into()); - } + let p = read_cake(bytes, "this PCZT")?; + check_device_signable(&p)?; Ok(dst::Pczt { - global: src.global, - transparent: src.transparent, - sapling: src.sapling.map(|s| dst::SaplingBundle { - spends: s.spends, - outputs: s.outputs, - value_sum: s.value_sum, - anchor: Some(s.anchor), - bsk: s.bsk, - }), - orchard: src.orchard.map(to_dst_orchard), - ironwood: src.ironwood.map(to_dst_orchard), + global: p.global, + transparent: p.transparent, + sapling: p.sapling, + orchard: p.orchard.map(cake_to_dst_orchard).transpose()?, + ironwood: p.ironwood.map(cake_to_dst_orchard).transpose()?, }) } +/// Global fields of a PCZT in Cake's dialect. +/// +/// The pinned `pczt` exposes no getters for the fallback lock time, coin type +/// or modifiable flags, which a device header has to carry verbatim. +pub fn read_global(bytes: &[u8]) -> Result<Global, String> { + Ok(read_cake(bytes, "this PCZT")?.global) +} + /// Rewrites a PCZT from Cake's dialect into the one a Keystone reads. pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { with_header(&to_dst_pczt(bytes)?, bytes.len()) @@ -436,23 +694,74 @@ pub fn to_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { pub fn from_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { let signed: dst::Pczt = postcard::from_bytes(split_header(bytes)?) .map_err(|e| format!("could not read the signed PCZT: {e:?}"))?; - let out = src_::Pczt { + let out = cake::Pczt { global: signed.global, transparent: signed.transparent, - sapling: signed + sapling: signed.sapling, + orchard: signed.orchard.map(dst_to_cake_orchard), + ironwood: signed.ironwood.map(dst_to_cake_orchard), + issue: None, + }; + with_header(&out, bytes.len()) +} + +/// Rewrites a PCZT from Cake's dialect into the one the Cupcake signer reads. +pub fn to_cupcake(bytes: &[u8]) -> Result<Vec<u8>, String> { + let p = read_cake(bytes, "this PCZT")?; + check_device_signable(&p)?; + let out = src_::Pczt { + global: p.global, + transparent: p.transparent, + // The pinned `pczt` writes an empty Sapling bundle as present with no + // anchor (and the IO Finalizer's zero binding key); the Cupcake + // dialect writes it as absent. A bundle with no spends or outputs has + // no binding signature and nothing a signature commits to, so the two + // mean the same. + sapling: p .sapling + .filter(|s| { + !(s.spends.is_empty() + && s.outputs.is_empty() + && s.value_sum == 0 + && s.anchor.is_none()) + }) .map(|s| { Ok::<_, String>(src_::SaplingBundle { spends: s.spends, outputs: s.outputs, value_sum: s.value_sum, - anchor: s.anchor.ok_or("signed PCZT is missing sapling anchor")?, + anchor: need(s.anchor, "a Sapling anchor")?, bsk: s.bsk, }) }) .transpose()?, - orchard: signed.orchard.map(to_src_orchard).transpose()?, - ironwood: signed.ironwood.map(to_src_orchard).transpose()?, + orchard: p.orchard.map(cake_to_src_orchard).transpose()?, + ironwood: p.ironwood.map(cake_to_src_orchard).transpose()?, + issue: None, + }; + with_header(&out, bytes.len()) +} + +/// Rewrites a PCZT from the Cupcake signer's dialect (Cake's own before its +/// `pczt` upgrade) into Cake's current one. +pub fn from_cupcake(bytes: &[u8]) -> Result<Vec<u8>, String> { + let p: src_::Pczt = postcard::from_bytes(split_header(bytes)?) + .map_err(|e| format!("could not read the PCZT: {e:?}"))?; + if p.issue.is_some() { + return Err("asset issuance is not supported here".into()); + } + let out = cake::Pczt { + global: p.global, + transparent: p.transparent, + sapling: p.sapling.map(|s| dst::SaplingBundle { + spends: s.spends, + outputs: s.outputs, + value_sum: s.value_sum, + anchor: Some(s.anchor), + bsk: s.bsk, + }), + orchard: p.orchard.map(src_to_cake_orchard), + ironwood: p.ironwood.map(src_to_cake_orchard), issue: None, }; with_header(&out, bytes.len()) @@ -463,16 +772,15 @@ pub fn from_keystone(bytes: &[u8]) -> Result<Vec<u8>, String> { /// A signer returns only what it needed to produce: it redacts prover-only /// fields such as the full viewing key, so its reply cannot be proved on its /// own. Rather than trusting the returned document, keep the original and take -/// just the signatures out of the reply. +/// just the signatures out of the reply. Both arguments are in Cake's dialect +/// (translate a Keystone reply with [`from_keystone`] first). pub fn apply_signatures(original: &[u8], signed: &[u8]) -> Result<Vec<u8>, String> { - let mut orig: src_::Pczt = postcard::from_bytes(split_header(original)?) - .map_err(|e| format!("could not read the original PCZT: {e:?}"))?; - let from_device: src_::Pczt = postcard::from_bytes(split_header(signed)?) - .map_err(|e| format!("could not read the signed PCZT: {e:?}"))?; + let mut orig = read_cake(original, "the original PCZT")?; + let from_device = read_cake(signed, "the signed PCZT")?; fn merge_orchard( - into: &mut Option<src_::OrchardBundle>, - from: &Option<src_::OrchardBundle>, + into: &mut Option<cake::OrchardBundle>, + from: &Option<cake::OrchardBundle>, pool: &str, ) -> Result<usize, String> { match (into.as_mut(), from.as_ref()) { @@ -640,8 +948,7 @@ pub fn apply_batch_sig_result(original: &[u8], response: &[u8]) -> Result<Vec<u8 .next() .ok_or("the device returned no signatures")?; - let mut orig: src_::Pczt = postcard::from_bytes(split_header(original)?) - .map_err(|e| format!("could not read the original PCZT: {e:?}"))?; + let mut orig = read_cake(original, "the original PCZT")?; let mut applied = 0usize; for sig in sigs { @@ -678,47 +985,164 @@ pub fn apply_batch_sig_result(original: &[u8], response: &[u8]) -> Result<Vec<u8 mod tests { use super::*; - /// A real Ironwood PCZT built by Cake, captured off the wire. - const CAKE: &[u8] = include_bytes!("../tests/data/cake_ironwood.pczt"); + /// A shield-shaped PCZT built with the `pczt` this crate pins today: one + /// transparent input sweeping into an Ironwood output, IO-finalized, so + /// the padding actions carry dummy spends with their signatures. Every + /// translation is tested against this rather than only against the + /// recorded fixtures, which predate the current encoding. + pub(crate) fn fresh_shield_pczt() -> Vec<u8> { + use orchard::keys::{FullViewingKey, Scope, SpendingKey}; + use pczt::roles::{creator::Creator, io_finalizer::IoFinalizer}; + use rand_core::OsRng; + use secp256k1::{PublicKey, Secp256k1, SecretKey}; + use zcash_primitives::transaction::{ + builder::{BuildConfig, Builder, BundlePadding}, + fees::zip317::FeeRule, + }; + use zcash_protocol::{ + consensus::{NetworkUpgrade, Parameters}, + value::Zatoshis, + }; + use zcash_transparent::{ + address::TransparentAddress, + builder::{SpendInfo, TransparentInputInfo}, + bundle::{OutPoint, TxOut}, + }; + + let network = crate::api::coin::Network::Main; + let height = network.activation_height(NetworkUpgrade::Nu6_3).unwrap() + 10; + let config = BuildConfig::Standard { + sapling_anchor: None, + orchard_anchor: None, + ironwood_anchor: Some(orchard::Anchor::empty_tree()), + orchard_padding: BundlePadding::DEFAULT, + ironwood_padding: BundlePadding::DEFAULT, + }; + let mut builder = Builder::new(&network, height, config); + + let secp = Secp256k1::new(); + let sk = SecretKey::from_slice(&[0x42; 32]).unwrap(); + let pubkey = PublicKey::from_secret_key(&secp, &sk); + let addr = TransparentAddress::from_pubkey(&pubkey); + let coin = TxOut::new(Zatoshis::from_u64(200_000).unwrap(), addr.script().into()); + builder.add_transparent_input( + TransparentInputInfo::from_parts( + OutPoint::new([3u8; 32], 1), + coin, + SpendInfo::P2pkh { pubkey }, + ) + .unwrap(), + ); + + let osk = SpendingKey::from_bytes([7u8; 32]).unwrap(); + let fvk = FullViewingKey::from(&osk); + let to = fvk.address_at(0u32, Scope::External); + builder + .add_ironwood_output::<std::convert::Infallible>( + Some(fvk.to_ovk(Scope::External)), + to, + Zatoshis::from_u64(185_000).unwrap(), + zcash_protocol::memo::MemoBytes::empty(), + ) + .unwrap(); + + let r = builder + .build_for_pczt(OsRng, &FeeRule::standard(), |_: &orchard::note::AssetBase| false) + .unwrap(); + let pczt = Creator::build_from_parts(r.pczt_parts).unwrap(); + let (pczt, _) = IoFinalizer::new(pczt).finalize_io().unwrap(); + pczt.serialize().unwrap() + } + + /// A real Ironwood PCZT built by Cake before its `pczt` upgrade, captured + /// off the wire: the dialect the Cupcake signer still reads. + const LEGACY: &[u8] = include_bytes!("../tests/data/cake_ironwood.pczt"); /// The same transaction in the Keystone's dialect. /// /// Checked in as a golden file rather than re-derived: `pczt` 0.8.0-rc.1 - /// cannot be built alongside the lrz stack this crate pins, so the - /// device-side assertion cannot live here. These bytes were verified - /// against the firmware's own parser, which reports two Ironwood actions - /// and one signable spend; Cake's dialect yields zero of each, which is - /// the bug this module exists to fix. + /// cannot be built alongside the stack this crate pins, so the device-side + /// assertion cannot live here. These bytes were verified against the + /// firmware's own parser, which reports two Ironwood actions and one + /// signable spend. const KEYSTONE: &[u8] = include_bytes!("../tests/data/cake_ironwood.keystone.pczt"); + /// The recorded transaction in Cake's current dialect. + fn cake_fixture() -> Vec<u8> { + from_cupcake(LEGACY).expect("legacy fixture translates to Cake's dialect") + } + + #[test] + fn cake_mirror_matches_the_pinned_pczt() { + let fresh = fresh_shield_pczt(); + let p = read_cake(&fresh, "fresh").expect("mirror decodes a freshly built PCZT"); + assert_eq!(with_header(&p, fresh.len()).unwrap(), fresh); + } + + #[test] + fn cupcake_translation_is_valid_for_the_pinned_pczt() { + // What the Cupcake path hands back to the prover must be a PCZT the + // real library accepts, not just one the mirror can round trip. + pczt::Pczt::parse(&cake_fixture()).expect("pinned pczt parses the translated fixture"); + } + #[test] fn matches_what_the_device_can_read() { - assert_eq!(to_keystone(CAKE).expect("transcode"), KEYSTONE); + assert_eq!(to_keystone(&cake_fixture()).expect("transcode"), KEYSTONE); + } + + #[test] + fn round_trips_are_lossless() { + assert_eq!(from_keystone(KEYSTONE).expect("from keystone"), cake_fixture()); + assert_eq!(to_cupcake(&cake_fixture()).expect("to cupcake"), LEGACY); + + let fresh = fresh_shield_pczt(); + let via_keystone = from_keystone(&to_keystone(&fresh).unwrap()).unwrap(); + assert_eq!(via_keystone, fresh); + // The Cupcake dialect has no "empty but present" Sapling bundle (see + // to_cupcake), so compare everything else byte for byte, and check the + // pinned library still accepts the result. + let via_cupcake = from_cupcake(&to_cupcake(&fresh).unwrap()).unwrap(); + pczt::Pczt::parse(&via_cupcake).expect("pinned pczt parses the Cupcake round trip"); + let without_sapling = |b: &[u8]| { + let mut p = read_cake(b, "round trip").unwrap(); + let s = p.sapling.take(); + assert!(s.map_or(true, |s| s.spends.is_empty() && s.outputs.is_empty())); + with_header(&p, b.len()).unwrap() + }; + assert_eq!(without_sapling(&via_cupcake), without_sapling(&fresh)); } #[test] - fn round_trip_is_lossless() { - assert_eq!(from_keystone(KEYSTONE).expect("transcode back"), CAKE); + fn refuses_to_drop_a_shielded_asset() { + let fresh = fresh_shield_pczt(); + let mut p = read_cake(&fresh, "fresh").unwrap(); + p.ironwood.as_mut().unwrap().actions[1].output.asset = Some([1u8; 32]); + let tampered = with_header(&p, fresh.len()).unwrap(); + assert!(to_keystone(&tampered).is_err()); + assert!(to_cupcake(&tampered).is_err()); + assert!(to_batch_request(&[tampered]).is_err()); } #[test] fn takes_signatures_and_keeps_prover_fields() { + let original = cake_fixture(); // Stand in for the device: strip the prover-only fields it redacts, // and attach a spend authorising signature. - let mut device: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let mut device = read_cake(&original, "fixture").unwrap(); let iw = device.ironwood.as_mut().unwrap(); for a in iw.actions.iter_mut() { a.spend.fvk = None; a.spend.witness = None; a.spend.spend_auth_sig = Some([7u8; 64]); } - let device_bytes = with_header(&device, CAKE.len()).unwrap(); + let device_bytes = with_header(&device, original.len()).unwrap(); - let merged = apply_signatures(CAKE, &device_bytes).expect("apply"); - let out: src_::Pczt = postcard::from_bytes(&merged[8..]).unwrap(); + let merged = apply_signatures(&original, &device_bytes).expect("apply"); + let out = read_cake(&merged, "merged").unwrap(); let actions = &out.ironwood.as_ref().unwrap().actions; - let orig: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let orig = read_cake(&original, "fixture").unwrap(); let orig_actions = &orig.ironwood.as_ref().unwrap().actions; // Every spend ends up authorised, and a spend the wallet had not @@ -745,23 +1169,26 @@ mod tests { #[test] fn rejects_a_reply_for_a_different_transaction() { - let mut other: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let original = cake_fixture(); + let mut other = read_cake(&original, "fixture").unwrap(); other.ironwood.as_mut().unwrap().actions.truncate(1); - let bytes = with_header(&other, CAKE.len()).unwrap(); - assert!(apply_signatures(CAKE, &bytes).is_err()); + let bytes = with_header(&other, original.len()).unwrap(); + assert!(apply_signatures(&original, &bytes).is_err()); } #[test] fn rejects_a_foreign_encoding() { assert!(to_keystone(b"not a pczt at all").is_err()); - let mut v1 = CAKE.to_vec(); + assert!(to_cupcake(b"not a pczt at all").is_err()); + let mut v1 = cake_fixture(); v1[4] = 1; assert!(to_keystone(&v1).is_err()); + assert!(to_cupcake(&v1).is_err()); } #[test] fn batch_request_strips_spend_auth_sigs() { - let req = to_batch_request(&[CAKE.to_vec()]).expect("batch request"); + let req = to_batch_request(&[cake_fixture()]).expect("batch request"); // Header: "PCZB" || batch version 1 || pczt version 2, all little-endian. assert_eq!(&req[..4], b"PCZB"); assert_eq!(u32::from_le_bytes(req[4..8].try_into().unwrap()), 1); @@ -804,9 +1231,10 @@ mod tests { #[test] fn applies_batch_signatures() { + let original = cake_fixture(); // The Ironwood actions the device would sign are those the IO Finalizer // left unsigned. - let orig: src_::Pczt = postcard::from_bytes(&CAKE[8..]).unwrap(); + let orig = read_cake(&original, "fixture").unwrap(); let to_sign: Vec<u32> = orig .ironwood .as_ref() @@ -835,8 +1263,8 @@ mod tests { resp.extend_from_slice(&1u32.to_le_bytes()); let resp = postcard::to_extend(&body, resp).unwrap(); - let merged = apply_batch_sig_result(CAKE, &resp).expect("apply"); - let out: src_::Pczt = postcard::from_bytes(&merged[8..]).unwrap(); + let merged = apply_batch_sig_result(&original, &resp).expect("apply"); + let out = read_cake(&merged, "merged").unwrap(); let out_actions = &out.ironwood.as_ref().unwrap().actions; let orig_actions = &orig.ironwood.as_ref().unwrap().actions; @@ -847,23 +1275,26 @@ mod tests { let expected = b.spend.spend_auth_sig.or(Some([9u8; 64])); assert_eq!(a.spend.spend_auth_sig, expected); } + // The merged transaction is still one the pinned library accepts. + pczt::Pczt::parse(&merged).expect("pinned pczt parses the merged PCZT"); } #[test] fn rejects_a_malformed_batch_response() { + let original = cake_fixture(); // Wrong magic. - assert!(apply_batch_sig_result(CAKE, b"nope____").is_err()); + assert!(apply_batch_sig_result(&original, b"nope____").is_err()); // Right magic, unsupported version. let mut bad = Vec::new(); bad.extend_from_slice(b"PCZS"); bad.extend_from_slice(&2u32.to_le_bytes()); - assert!(apply_batch_sig_result(CAKE, &bad).is_err()); + assert!(apply_batch_sig_result(&original, &bad).is_err()); // Valid header, no signatures. let empty = BatchSignResponse { signatures: vec![vec![]] }; let mut resp = Vec::new(); resp.extend_from_slice(b"PCZS"); resp.extend_from_slice(&1u32.to_le_bytes()); let resp = postcard::to_extend(&empty, resp).unwrap(); - assert!(apply_batch_sig_result(CAKE, &resp).is_err()); + assert!(apply_batch_sig_result(&original, &resp).is_err()); } } diff --git a/rust/src/pay/plan.rs b/rust/src/pay/plan.rs index 375798951..e3b6a69c3 100644 --- a/rust/src/pay/plan.rs +++ b/rust/src/pay/plan.rs @@ -1603,7 +1603,16 @@ pub async fn prove_and_finalize( is_issuance, .. } = package; - let pczt = Pczt::parse(pczt).map_err(|e| anyhow!("failed to parse PCZT: {e:?}"))?; + // A PCZT signed by the Cupcake signer comes back in the older encoding it + // reads; translate it rather than refusing it. + let pczt = match Pczt::parse(pczt) { + Ok(pczt) => pczt, + Err(e) => { + let translated = crate::keystone_wire::from_cupcake(pczt) + .map_err(|_| anyhow!("failed to parse PCZT: {e:?}"))?; + Pczt::parse(&translated).map_err(|e| anyhow!("failed to parse PCZT: {e:?}"))? + } + }; span.in_scope(|| { info!("Adding Proofs to externally signed PCZT"); From 2c792005e1eee0abf910292bd357b84cfc1cc7f2 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 18:57:57 -0400 Subject: [PATCH 185/189] ledger: send the PCZT's own header fields, stop on an empty key chunk Audit follow-ups on the Official app path: - The PCZT_HEADER carried a hardcoded "no fallback lock time", nothing modifiable and the network's coin type rather than the PCZT's. Harmless while zkool never sets a lock time, but a future one would have produced signatures that fail verification. The fields are now read from the PCZT (the pinned pczt has no getters for them, so through the wire mirror); a coin type that disagrees with the account's network is refused, and a zero lock time is still sent as absent, so today's transactions produce exactly the header bytes the device has been signing (pinned by a test). - get_ufvk looped forever if the device answered a continuation request with success and no data. That is now a protocol error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- rust/src/ledger/official.rs | 15 +++++ rust/src/ledger/official_sign.rs | 104 +++++++++++++++++++++++++++---- 2 files changed, 108 insertions(+), 11 deletions(-) diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs index 058776c70..b07aa261a 100644 --- a/rust/src/ledger/official.rs +++ b/rust/src/ledger/official.rs @@ -119,6 +119,12 @@ pub async fn get_ufvk<D: Device>(ledger: &D, network: &Network, aindex: u32) -> if res.retcode != SW_OK { return Err(LedgerError::Execute(res.retcode, INS_GET_VK)); } + // A chunk that adds nothing would loop forever waiting for the rest. + if res.data.is_empty() { + return Err(LedgerError::Protocol( + "the device stopped sending the viewing key before it was complete".into(), + )); + } payload.extend_from_slice(&res.data); } payload.truncate(len); @@ -237,6 +243,15 @@ mod tests { assert!(sent[1..].iter().all(|c| c.p1 == P1_CONTINUE && c.data.is_empty())); } + #[tokio::test] + async fn an_empty_continuation_chunk_is_an_error_not_a_hang() { + let mut first = 300u16.to_be_bytes().to_vec(); + first.extend_from_slice(&[b'u'; 100]); + let device = Scripted::new(vec![with_sw(first, SW_OK), vec![0x90, 0x00]]); + let err = get_ufvk(&device, &Network::Main, 0).await.unwrap_err(); + assert!(matches!(err, LedgerError::Protocol(_))); + } + #[tokio::test] async fn refusing_the_export_is_reported_as_such() { let device = Scripted::new(vec![vec![0x69, 0x85]]); diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index b78d3939f..24d0e0121 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -203,6 +203,31 @@ async fn sign_transparent_input<D: Device>( }) } +// PCZT_HEADER: magic, PCZT version, transaction header, then the PCZT's own +// fallback lock time, coin type and modifiable flags. A zero fallback lock +// time is what an absent one means, and is what every transaction this wallet +// builds carries; it is sent as absent, the encoding the device has been +// signing with. +fn frame_header( + tx_version: u32, + version_group_id: u32, + consensus_branch_id: u32, + expiry_height: u32, + wire: &crate::keystone_wire::Global, +) -> Result<Vec<u8>> { + let mut data = vec![]; + data.write_all(b"PCZT")?; + data.write_u32::<LE>(PCZT_VERSION_V6)?; + data.write_u32::<LE>(tx_version)?; + data.write_u32::<LE>(version_group_id)?; + data.write_u32::<LE>(consensus_branch_id)?; + write_optional_u32(&mut data, wire.fallback_lock_time.filter(|t| *t != 0))?; + data.write_u32::<LE>(expiry_height)?; + data.write_u32::<LE>(wire.coin_type)?; + data.write_u8(wire.tx_modifiable)?; + Ok(data) +} + // Per-action spend fields: cv_net, nullifier, rk, recipient, value, rho, // rseed, alpha — one packet. fn frame_spend_small<D: Domain>(action: &Action<D>) -> Result<Vec<u8>> { @@ -570,19 +595,25 @@ where // ── Send to the device ──────────────────────────────────────────────── progress("Confirm on your Ledger".to_string()).await; + // The header carries the PCZT's own lock time, coin type and modifiable + // flags. The pinned `pczt` has no getters for them, so read them from the + // encoding. + let wire = crate::keystone_wire::read_global(&package.pczt).map_err(|e| anyhow!(e))?; + if wire.coin_type != coin_type { + anyhow::bail!( + "this transaction was built for coin type {}, but the account is on coin type {coin_type}", + wire.coin_type + ); + } let header = { let g = pczt.global(); - let mut data = vec![]; - data.write_all(b"PCZT")?; - data.write_u32::<LE>(PCZT_VERSION_V6)?; - data.write_u32::<LE>(*g.tx_version())?; - data.write_u32::<LE>(*g.version_group_id())?; - data.write_u32::<LE>(*g.consensus_branch_id())?; - data.write_u8(0x00)?; // fallback_lock_time: none (builder uses 0) - data.write_u32::<LE>(*g.expiry_height())?; - data.write_u32::<LE>(coin_type)?; - data.write_u8(0x00)?; // tx_modifiable: none - vec![data] + vec![frame_header( + *g.tx_version(), + *g.version_group_id(), + *g.consensus_branch_id(), + *g.expiry_height(), + &wire, + )?] }; send_command(ledger, INS_PCZT_HEADER, header, false).await?; @@ -698,3 +729,54 @@ where let ledger = crate::ledger::transport::connect_ledger().await?; sign_transaction(&network, connection, account, &package, Some(sink), &ledger).await } + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::BTreeMap; + + fn global(lock: Option<u32>, coin: u32, modifiable: u8) -> crate::keystone_wire::Global { + crate::keystone_wire::Global { + tx_version: 6, + version_group_id: 0xd8a2_ed98, + consensus_branch_id: 0x37a5_475b, + fallback_lock_time: lock, + expiry_height: 3_300_040, + coin_type: coin, + tx_modifiable: modifiable, + proprietary: BTreeMap::new(), + } + } + + fn header(g: &crate::keystone_wire::Global) -> Vec<u8> { + frame_header(g.tx_version, g.version_group_id, g.consensus_branch_id, g.expiry_height, g).unwrap() + } + + #[test] + fn a_zero_lock_time_keeps_the_header_the_device_signed_with() { + // The layout sent before the header read these fields: lock time + // absent, coin type from the network, nothing modifiable. + let mut before = vec![]; + before.extend_from_slice(b"PCZT"); + before.extend_from_slice(&PCZT_VERSION_V6.to_le_bytes()); + before.extend_from_slice(&6u32.to_le_bytes()); + before.extend_from_slice(&0xd8a2_ed98u32.to_le_bytes()); + before.extend_from_slice(&0x37a5_475bu32.to_le_bytes()); + before.push(0x00); + before.extend_from_slice(&3_300_040u32.to_le_bytes()); + before.extend_from_slice(&133u32.to_le_bytes()); + before.push(0x00); + + assert_eq!(header(&global(Some(0), 133, 0)), before); + assert_eq!(header(&global(None, 133, 0)), before); + } + + #[test] + fn a_real_lock_time_and_flags_are_carried() { + let h = header(&global(Some(900), 133, 0x04)); + let lock = 4 + 4 * 4; + assert_eq!(h[lock], 0x01); + assert_eq!(u32::from_le_bytes(h[lock + 1..lock + 5].try_into().unwrap()), 900); + assert_eq!(*h.last().unwrap(), 0x04); + } +} From aeb698d0e55d81f5ebfc870e1ec1d19f76c1f075 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 19:56:44 -0400 Subject: [PATCH 186/189] ledger: report "Confirm on your Ledger" once the device can show its review The progress event was sent before the transaction was streamed, so the host told the user to look at the device several seconds before it drew anything; the device's review appears only after the last packet. The streaming is now reported as "Sending to Ledger" and the confirm event follows the final packet. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- rust/src/ledger/official_sign.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index 24d0e0121..14976c2f9 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -593,7 +593,7 @@ where } // ── Send to the device ──────────────────────────────────────────────── - progress("Confirm on your Ledger".to_string()).await; + progress("Sending to Ledger".to_string()).await; // The header carries the PCZT's own lock time, coin type and modifiable // flags. The pinned `pczt` has no getters for them, so read them from the @@ -623,6 +623,9 @@ where // with 0 actions, and its last packet carries P2_FINISHED. send_command(ledger, INS_PCZT_ORCHARD_ACTION, orchard_packets, false).await?; send_command(ledger, INS_PCZT_IRONWOOD_ACTION, ironwood_packets, true).await?; + // The device draws its review only once that last packet has landed; + // this is the first moment there is anything for the user to confirm. + progress("Confirm on your Ledger".to_string()).await; // ── Collect signatures ──────────────────────────────────────────────── progress("Signing on Ledger".to_string()).await; From d34590e0d2448b60e51d4babf644a6deae5fd543 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 20:09:02 -0400 Subject: [PATCH 187/189] ledger: show the account address on the device so the imported key can be checked A review of the pairing flow pointed out that the viewing key crosses the BLE/USB link unauthenticated and the host imported whatever came back: a substituted key would have put every receive address in an attacker's hands with nothing for the user to notice. The device's own screen is the one part of the path a tampered link cannot alter. GET_SHIELD_ADDR (0x51) with display asks the device to derive the account's unified address (Orchard account path plus m/44'/coin'/account'/0/0) and show it for approval; ledger_show_address exposes that to the host, which displays the address it derived from the imported key alongside so the user can compare them. A refusal, a truncated reply, or anything that is not a unified address with an Orchard receiver is an error. Also refuses a transparent signature reply with no DER bytes instead of indexing into it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- lib/src/rust/api/ledger.dart | 16 ++ lib/src/rust/frb_generated.dart | 306 ++++++++++++++++++------------- rust/src/api/ledger.rs | 16 ++ rust/src/frb_generated.rs | 280 +++++++++++++++------------- rust/src/ledger/official.rs | 139 ++++++++++++++ rust/src/ledger/official_sign.rs | 3 + 6 files changed, 500 insertions(+), 260 deletions(-) diff --git a/lib/src/rust/api/ledger.dart b/lib/src/rust/api/ledger.dart index b1e9fdfdb..7f1dc7422 100644 --- a/lib/src/rust/api/ledger.dart +++ b/lib/src/rust/api/ledger.dart @@ -30,6 +30,22 @@ Future<String> ledgerGetUfvk({ exchange: exchange, ); +/// Has the device derive and show the account's default unified address on +/// its own screen, returning it once the user approves there. +/// +/// The screen is the one part of the path a tampered transport cannot alter, +/// so the host shows the address it derived from the imported viewing key +/// next to this call, and the user checks the two match. +Future<String> ledgerShowAddress({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, +}) => RustLib.instance.api.crateApiLedgerLedgerShowAddress( + aindex: aindex, + c: c, + exchange: exchange, +); + /// Default unified address of a viewing key, for showing which account a /// device key belongs to before the account exists in the database. String ufvkDefaultAddress({required String ufvk, required Coin c}) => diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index eb3d996cc..59d2b2b9e 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -92,7 +92,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -798327101; + int get rustContentHash => 1590632070; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -594,6 +594,12 @@ abstract class RustLibApi extends BaseApi { required FutureOr<Uint8List> Function(Uint8List) exchange, }); + Future<String> crateApiLedgerLedgerShowAddress({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }); + Stream<SigningEvent> crateApiLedgerLedgerSignTransaction({ required PcztPackage package, required Coin c, @@ -5242,6 +5248,46 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["aindex", "c", "exchange"], ); + @override + Future<String> crateApiLedgerLedgerShowAddress({ + required int aindex, + required Coin c, + required FutureOr<Uint8List> Function(Uint8List) exchange, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_u_32(aindex, serializer); + sse_encode_box_autoadd_coin(c, serializer); + sse_encode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException( + exchange, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 119, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLedgerLedgerShowAddressConstMeta, + argValues: [aindex, c, exchange], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiLedgerLedgerShowAddressConstMeta => + const TaskConstMeta( + debugName: "ledger_show_address", + argNames: ["aindex", "c", "exchange"], + ); + @override Stream<SigningEvent> crateApiLedgerLedgerSignTransaction({ required PcztPackage package, @@ -5264,7 +5310,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 119, + funcId: 120, port: port_, ); }, @@ -5297,7 +5343,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 120, + funcId: 121, port: port_, ); }, @@ -5325,7 +5371,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 121, + funcId: 122, port: port_, ); }, @@ -5353,7 +5399,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 122, + funcId: 123, port: port_, ); }, @@ -5383,7 +5429,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 123, + funcId: 124, port: port_, ); }, @@ -5413,7 +5459,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 124, + funcId: 125, port: port_, ); }, @@ -5441,7 +5487,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 125, + funcId: 126, port: port_, ); }, @@ -5469,7 +5515,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 126, + funcId: 127, port: port_, ); }, @@ -5497,7 +5543,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 127, + funcId: 128, port: port_, ); }, @@ -5525,7 +5571,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 128, + funcId: 129, port: port_, ); }, @@ -5553,7 +5599,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 129, + funcId: 130, port: port_, ); }, @@ -5581,7 +5627,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 130, + funcId: 131, port: port_, ); }, @@ -5609,7 +5655,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 131, + funcId: 132, port: port_, ); }, @@ -5643,7 +5689,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 132, + funcId: 133, port: port_, ); }, @@ -5679,7 +5725,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 133, + funcId: 134, port: port_, ); }, @@ -5710,7 +5756,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 134, + funcId: 135, port: port_, ); }, @@ -5742,7 +5788,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 135, + funcId: 136, port: port_, ); }, @@ -5770,7 +5816,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 136, + funcId: 137, port: port_, ); }, @@ -5802,7 +5848,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 137, + funcId: 138, port: port_, ); }, @@ -5833,7 +5879,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 138, + funcId: 139, )!; }, codec: SseCodec( @@ -5864,7 +5910,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 139, + funcId: 140, port: port_, ); }, @@ -5899,7 +5945,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 140, + funcId: 141, port: port_, ); }, @@ -5930,7 +5976,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 141, + funcId: 142, port: port_, ); }, @@ -5958,7 +6004,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 142, + funcId: 143, port: port_, ); }, @@ -5988,7 +6034,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 143, + funcId: 144, port: port_, ); }, @@ -6019,7 +6065,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 144, + funcId: 145, port: port_, ); }, @@ -6047,7 +6093,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 145, + funcId: 146, port: port_, ); }, @@ -6081,7 +6127,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 146, + funcId: 147, port: port_, ); }, @@ -6117,7 +6163,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 147, + funcId: 148, port: port_, ); }, @@ -6149,7 +6195,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 148, + funcId: 149, port: port_, ); }, @@ -6181,7 +6227,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 149, + funcId: 150, port: port_, ); }, @@ -6218,7 +6264,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 150, + funcId: 151, port: port_, ); }, @@ -6248,7 +6294,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 151, + funcId: 152, port: port_, ); }, @@ -6275,7 +6321,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 152, + funcId: 153, port: port_, ); }, @@ -6307,7 +6353,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 153, + funcId: 154, )!; }, codec: SseCodec( @@ -6341,7 +6387,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 154, + funcId: 155, port: port_, ); }, @@ -6376,7 +6422,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 155, + funcId: 156, port: port_, ); }, @@ -6408,7 +6454,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 156, + funcId: 157, port: port_, ); }, @@ -6445,7 +6491,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 157, + funcId: 158, port: port_, ); }, @@ -6482,7 +6528,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 158, + funcId: 159, port: port_, ); }, @@ -6513,7 +6559,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 159, + funcId: 160, port: port_, ); }, @@ -6542,7 +6588,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 160, + funcId: 161, port: port_, ); }, @@ -6574,7 +6620,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 161, + funcId: 162, port: port_, ); }, @@ -6607,7 +6653,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 162, + funcId: 163, port: port_, ); }, @@ -6640,7 +6686,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 163, + funcId: 164, port: port_, ); }, @@ -6677,7 +6723,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 164, + funcId: 165, port: port_, ); }, @@ -6713,7 +6759,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 165, + funcId: 166, port: port_, ); }, @@ -6747,7 +6793,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 166, + funcId: 167, port: port_, ); }, @@ -6783,7 +6829,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 167, + funcId: 168, port: port_, ); }, @@ -6825,7 +6871,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 168, + funcId: 169, port: port_, ); }, @@ -6855,7 +6901,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 169, + funcId: 170, )!; }, codec: SseCodec( @@ -6883,7 +6929,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 170, + funcId: 171, )!; }, codec: SseCodec( @@ -6917,7 +6963,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 171, + funcId: 172, port: port_, ); }, @@ -6954,7 +7000,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 172, + funcId: 173, port: port_, ); }, @@ -6991,7 +7037,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 173, + funcId: 174, port: port_, ); }, @@ -7028,7 +7074,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 174, + funcId: 175, port: port_, ); }, @@ -7059,7 +7105,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 175, + funcId: 176, port: port_, ); }, @@ -7092,7 +7138,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 176, + funcId: 177, port: port_, ); }, @@ -7130,7 +7176,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 177, + funcId: 178, port: port_, ); }, @@ -7167,7 +7213,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 178, + funcId: 179, port: port_, ); }, @@ -7197,7 +7243,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 179, + funcId: 180, port: port_, ); }, @@ -7235,7 +7281,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 180, + funcId: 181, port: port_, ); }, @@ -7282,7 +7328,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 181, + funcId: 182, port: port_, ); }, @@ -7333,7 +7379,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 182, + funcId: 183, )!; }, codec: SseCodec( @@ -7360,7 +7406,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 183, + funcId: 184, port: port_, ); }, @@ -7392,7 +7438,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 184, + funcId: 185, )!; }, codec: SseCodec( @@ -7421,7 +7467,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 185, + funcId: 186, port: port_, ); }, @@ -7448,7 +7494,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 186, + funcId: 187, port: port_, ); }, @@ -7475,7 +7521,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 187, + funcId: 188, port: port_, ); }, @@ -7502,7 +7548,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 188, + funcId: 189, port: port_, ); }, @@ -7529,7 +7575,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 189, + funcId: 190, port: port_, ); }, @@ -7563,7 +7609,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 190, + funcId: 191, )!; }, codec: SseCodec( @@ -7596,7 +7642,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 191, + funcId: 192, )!; }, codec: SseCodec( @@ -7626,7 +7672,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 192, + funcId: 193, port: port_, ); }, @@ -7654,7 +7700,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 193, + funcId: 194, port: port_, ); }, @@ -7686,7 +7732,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 194, + funcId: 195, port: port_, ); }, @@ -7727,7 +7773,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 195, + funcId: 196, port: port_, ); }, @@ -7764,7 +7810,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 196, + funcId: 197, port: port_, ); }, @@ -7795,7 +7841,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 197, + funcId: 198, )!; }, codec: SseCodec( @@ -7829,7 +7875,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 198, + funcId: 199, )!; }, codec: SseCodec( @@ -7863,7 +7909,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 199, + funcId: 200, port: port_, ); }, @@ -7900,7 +7946,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 200, + funcId: 201, port: port_, ); }, @@ -7937,7 +7983,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 201, + funcId: 202, port: port_, ); }, @@ -7974,7 +8020,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 202, + funcId: 203, port: port_, ); }, @@ -8013,7 +8059,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 203, + funcId: 204, port: port_, ); }, @@ -8050,7 +8096,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 204, + funcId: 205, port: port_, ); }, @@ -8087,7 +8133,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 205, + funcId: 206, port: port_, ); }, @@ -8124,7 +8170,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 206, + funcId: 207, port: port_, ); }, @@ -8161,7 +8207,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 207, + funcId: 208, port: port_, ); }, @@ -8196,7 +8242,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 208, + funcId: 209, port: port_, ); }, @@ -8237,7 +8283,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 209, + funcId: 210, port: port_, ); }, @@ -8283,7 +8329,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 210, + funcId: 211, port: port_, ); }, @@ -8327,7 +8373,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 211, + funcId: 212, port: port_, ); }, @@ -8358,7 +8404,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 212, + funcId: 213, port: port_, ); }, @@ -8393,7 +8439,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 213, + funcId: 214, port: port_, ); }, @@ -8436,7 +8482,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 214, + funcId: 215, port: port_, ); }, @@ -8480,7 +8526,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 215, + funcId: 216, port: port_, ); }, @@ -8515,7 +8561,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 216, + funcId: 217, port: port_, ); }, @@ -8552,7 +8598,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 217, + funcId: 218, port: port_, ); }, @@ -8587,7 +8633,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 218, + funcId: 219, port: port_, ); }, @@ -8618,7 +8664,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 219, + funcId: 220, port: port_, ); }, @@ -8646,7 +8692,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 220, + funcId: 221, port: port_, ); }, @@ -8684,7 +8730,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 221, + funcId: 222, port: port_, ); }, @@ -8723,7 +8769,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 222, + funcId: 223, port: port_, ); }, @@ -8760,7 +8806,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 223, + funcId: 224, port: port_, ); }, @@ -8804,7 +8850,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 224, + funcId: 225, port: port_, ); }, @@ -8859,7 +8905,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 225, + funcId: 226, port: port_, ); }, @@ -8905,7 +8951,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 226, + funcId: 227, port: port_, ); }, @@ -8954,7 +9000,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 227, + funcId: 228, port: port_, ); }, @@ -8989,7 +9035,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 228, + funcId: 229, port: port_, ); }, @@ -9024,7 +9070,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 229, + funcId: 230, port: port_, ); }, @@ -9067,7 +9113,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 230, + funcId: 231, port: port_, ); }, @@ -9112,7 +9158,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 231, + funcId: 232, port: port_, ); }, @@ -9144,7 +9190,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 232, + funcId: 233, port: port_, ); }, @@ -9187,7 +9233,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 233, + funcId: 234, port: port_, ); }, @@ -9237,7 +9283,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 234, + funcId: 235, port: port_, ); }, @@ -9285,7 +9331,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 235, + funcId: 236, port: port_, ); }, @@ -9320,7 +9366,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 236, + funcId: 237, port: port_, ); }, @@ -9365,7 +9411,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 237, + funcId: 238, port: port_, ); }, @@ -9426,7 +9472,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 238, + funcId: 239, port: port_, ); }, @@ -9487,7 +9533,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 239, + funcId: 240, port: port_, ); }, @@ -9539,7 +9585,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 240, + funcId: 241, port: port_, ); }, @@ -9584,7 +9630,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 241, + funcId: 242, port: port_, ); }, @@ -9637,7 +9683,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 242, + funcId: 243, port: port_, ); }, @@ -9674,7 +9720,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 243, + funcId: 244, port: port_, ); }, @@ -9713,7 +9759,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 244, + funcId: 245, port: port_, ); }, @@ -9752,7 +9798,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 245, + funcId: 246, port: port_, ); }, @@ -9791,7 +9837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 246, + funcId: 247, port: port_, ); }, @@ -9830,7 +9876,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { pdeCallFfi( generalizedFrbRustBinding, serializer, - funcId: 247, + funcId: 248, port: port_, ); }, diff --git a/rust/src/api/ledger.rs b/rust/src/api/ledger.rs index 6a036bda6..2b3fcf375 100644 --- a/rust/src/api/ledger.rs +++ b/rust/src/api/ledger.rs @@ -52,6 +52,22 @@ pub async fn ledger_get_ufvk( Ok(official::get_ufvk(&device, &c.network(), aindex).await?) } +/// Has the device derive and show the account's default unified address on +/// its own screen, returning it once the user approves there. +/// +/// The screen is the one part of the path a tampered transport cannot alter, +/// so the host shows the address it derived from the imported viewing key +/// next to this call, and the user checks the two match. +#[cfg(feature = "flutter")] +pub async fn ledger_show_address( + aindex: u32, + c: &Coin, + exchange: impl Fn(Vec<u8>) -> DartFnFuture<Vec<u8>> + Send + Sync + 'static, +) -> Result<String> { + let device = DartDevice::new(exchange); + Ok(official::get_shield_address(&device, &c.network(), aindex, true).await?) +} + /// Default unified address of a viewing key, for showing which account a /// device key belongs to before the account exists in the database. #[cfg(feature = "flutter")] diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 9890c2d43..9b3f77580 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -42,7 +42,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -798327101; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1590632070; // Section: executor @@ -4736,6 +4736,23 @@ let api_exchange = decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_ })().await) } }) } +fn wire__crate__api__ledger__ledger_show_address_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec,_,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "ledger_show_address", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal }, move || { + let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) }; + let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_aindex = <u32>::sse_decode(&mut deserializer); +let api_c = <crate::api::coin::Coin>::sse_decode(&mut deserializer); +let api_exchange = decode_DartFn_Inputs_list_prim_u_8_strict_Output_list_prim_u_8_strict_AnyhowException(<flutter_rust_bridge::DartOpaque>::sse_decode(&mut deserializer));deserializer.end(); move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>((move || async move { + let output_ok = crate::api::ledger::ledger_show_address(api_aindex, &api_c, api_exchange).await?; Ok(output_ok) + })().await) + } }) +} fn wire__crate__api__ledger__ledger_sign_transaction_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -13115,302 +13132,305 @@ fn pde_ffi_dispatcher_primary_impl( 116 => wire__crate__api__issuance__issue_asset_impl(port, ptr, rust_vec_len, data_len), 117 => wire__crate__api__ledger__ledger_app_version_impl(port, ptr, rust_vec_len, data_len), 118 => wire__crate__api__ledger__ledger_get_ufvk_impl(port, ptr, rust_vec_len, data_len), - 119 => wire__crate__api__ledger__ledger_sign_transaction_impl( + 119 => { + wire__crate__api__ledger__ledger_show_address_impl(port, ptr, rust_vec_len, data_len) + } + 120 => wire__crate__api__ledger__ledger_sign_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 120 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), - 121 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), - 122 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), - 123 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), - 124 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), - 125 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), - 126 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), - 127 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), - 128 => { + 121 => wire__crate__api__account__list_accounts_impl(port, ptr, rust_vec_len, data_len), + 122 => wire__crate__api__account__list_categories_impl(port, ptr, rust_vec_len, data_len), + 123 => wire__crate__api__contacts__list_contacts_impl(port, ptr, rust_vec_len, data_len), + 124 => wire__crate__api__db__list_db_accounts_impl(port, ptr, rust_vec_len, data_len), + 125 => wire__crate__api__db__list_db_names_impl(port, ptr, rust_vec_len, data_len), + 126 => wire__crate__api__account__list_folders_impl(port, ptr, rust_vec_len, data_len), + 127 => wire__crate__api__account__list_memos_impl(port, ptr, rust_vec_len, data_len), + 128 => wire__crate__api__account__list_notes_impl(port, ptr, rust_vec_len, data_len), + 129 => { wire__crate__api__account__list_owned_addresses_impl(port, ptr, rust_vec_len, data_len) } - 129 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), - 130 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), - 131 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), - 132 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), - 133 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), - 134 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), - 135 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), - 136 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), - 137 => wire__crate__api__plugin__parse_memo_with_plugins_impl( + 130 => wire__crate__api__plugin__list_plugins_impl(port, ptr, rust_vec_len, data_len), + 131 => wire__crate__api__account__list_tx_history_impl(port, ptr, rust_vec_len, data_len), + 132 => wire__crate__api__zsa__list_zsa_holdings_impl(port, ptr, rust_vec_len, data_len), + 133 => wire__crate__api__account__lock_note_impl(port, ptr, rust_vec_len, data_len), + 134 => wire__crate__api__account__lock_recent_notes_impl(port, ptr, rust_vec_len, data_len), + 135 => wire__crate__api__account__max_spendable_impl(port, ptr, rust_vec_len, data_len), + 136 => wire__crate__api__account__new_account_impl(port, ptr, rust_vec_len, data_len), + 137 => wire__crate__api__pay__pack_transaction_impl(port, ptr, rust_vec_len, data_len), + 138 => wire__crate__api__plugin__parse_memo_with_plugins_impl( port, ptr, rust_vec_len, data_len, ), - 139 => wire__crate__api__pay__pczt_apply_batch_signatures_impl( + 140 => wire__crate__api__pay__pczt_apply_batch_signatures_impl( port, ptr, rust_vec_len, data_len, ), - 140 => wire__crate__api__pay__pczt_apply_keystone_signatures_impl( + 141 => wire__crate__api__pay__pczt_apply_keystone_signatures_impl( port, ptr, rust_vec_len, data_len, ), - 141 => wire__crate__api__pay__pczt_from_cupcake_impl(port, ptr, rust_vec_len, data_len), - 142 => wire__crate__api__pay__pczt_from_keystone_impl(port, ptr, rust_vec_len, data_len), - 143 => wire__crate__api__pay__pczt_to_batch_request_impl(port, ptr, rust_vec_len, data_len), - 144 => wire__crate__api__pay__pczt_to_cupcake_impl(port, ptr, rust_vec_len, data_len), - 145 => wire__crate__api__pay__pczt_to_keystone_impl(port, ptr, rust_vec_len, data_len), - 146 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), - 147 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), - 148 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), - 149 => wire__crate__api__pay__prove_and_finalize_impl(port, ptr, rust_vec_len, data_len), - 150 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), - 151 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), - 152 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), - 154 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), - 155 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), - 156 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), - 157 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), - 158 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), - 159 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), - 160 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), - 161 => { + 142 => wire__crate__api__pay__pczt_from_cupcake_impl(port, ptr, rust_vec_len, data_len), + 143 => wire__crate__api__pay__pczt_from_keystone_impl(port, ptr, rust_vec_len, data_len), + 144 => wire__crate__api__pay__pczt_to_batch_request_impl(port, ptr, rust_vec_len, data_len), + 145 => wire__crate__api__pay__pczt_to_cupcake_impl(port, ptr, rust_vec_len, data_len), + 146 => wire__crate__api__pay__pczt_to_keystone_impl(port, ptr, rust_vec_len, data_len), + 147 => wire__crate__api__pay__prepare_impl(port, ptr, rust_vec_len, data_len), + 148 => wire__crate__api__pay__prepare_migration_impl(port, ptr, rust_vec_len, data_len), + 149 => wire__crate__api__account__print_keys_impl(port, ptr, rust_vec_len, data_len), + 150 => wire__crate__api__pay__prove_and_finalize_impl(port, ptr, rust_vec_len, data_len), + 151 => wire__crate__api__db__put_prop_impl(port, ptr, rust_vec_len, data_len), + 152 => wire__crate__api__network__query_lwd_list_impl(port, ptr, rust_vec_len, data_len), + 153 => wire__crate__api__account__receivers_default_impl(port, ptr, rust_vec_len, data_len), + 155 => wire__crate__api__account__remove_account_impl(port, ptr, rust_vec_len, data_len), + 156 => wire__crate__api__plugin__remove_plugin_impl(port, ptr, rust_vec_len, data_len), + 157 => wire__crate__api__account__rename_category_impl(port, ptr, rust_vec_len, data_len), + 158 => wire__crate__api__account__rename_folder_impl(port, ptr, rust_vec_len, data_len), + 159 => wire__crate__api__account__reorder_account_impl(port, ptr, rust_vec_len, data_len), + 160 => wire__crate__api__frost__reset_sign_impl(port, ptr, rust_vec_len, data_len), + 161 => wire__crate__api__account__reset_sync_impl(port, ptr, rust_vec_len, data_len), + 162 => { wire__crate__api__openalias__resolve_openalias_impl(port, ptr, rust_vec_len, data_len) } - 162 => wire__crate__api__openalias__resolve_openalias_all_impl( + 163 => wire__crate__api__openalias__resolve_openalias_all_impl( port, ptr, rust_vec_len, data_len, ), - 163 => wire__crate__api__openalias__resolve_openalias_raw_impl( + 164 => wire__crate__api__openalias__resolve_openalias_raw_impl( port, ptr, rust_vec_len, data_len, ), - 164 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), - 165 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), - 166 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), - 167 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), - 168 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), - 171 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), - 172 => { + 165 => wire__crate__api__sync__rewind_sync_impl(port, ptr, rust_vec_len, data_len), + 166 => wire__crate__api__pay__send_impl(port, ptr, rust_vec_len, data_len), + 167 => wire__crate__api__zsa__set_asset_name_impl(port, ptr, rust_vec_len, data_len), + 168 => wire__crate__api__frost__set_dkg_address_impl(port, ptr, rust_vec_len, data_len), + 169 => wire__crate__api__frost__set_dkg_params_impl(port, ptr, rust_vec_len, data_len), + 172 => wire__crate__api__plugin__set_plugin_enabled_impl(port, ptr, rust_vec_len, data_len), + 173 => { wire__crate__api__transaction__set_tx_category_impl(port, ptr, rust_vec_len, data_len) } - 173 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), - 174 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), - 175 => wire__crate__api__account__show_ledger_sapling_address_impl( + 174 => wire__crate__api__transaction__set_tx_price_impl(port, ptr, rust_vec_len, data_len), + 175 => wire__crate__api__transaction__set_user_memo_impl(port, ptr, rust_vec_len, data_len), + 176 => wire__crate__api__account__show_ledger_sapling_address_impl( port, ptr, rust_vec_len, data_len, ), - 176 => wire__crate__api__account__show_ledger_transparent_address_impl( + 177 => wire__crate__api__account__show_ledger_transparent_address_impl( port, ptr, rust_vec_len, data_len, ), - 177 => wire__crate__api__account__sign_ledger_transaction_impl( + 178 => wire__crate__api__account__sign_ledger_transaction_impl( port, ptr, rust_vec_len, data_len, ), - 178 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), - 179 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), - 180 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), - 181 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), - 183 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), - 185 => { + 179 => wire__crate__api__pay__sign_transaction_impl(port, ptr, rust_vec_len, data_len), + 180 => wire__crate__api__migrate__step_migration_impl(port, ptr, rust_vec_len, data_len), + 181 => wire__crate__api__pay__store_pending_tx_impl(port, ptr, rust_vec_len, data_len), + 182 => wire__crate__api__sync__synchronize_impl(port, ptr, rust_vec_len, data_len), + 184 => wire__crate__api__account__toggle_all_notes_impl(port, ptr, rust_vec_len, data_len), + 186 => { wire__crate__api__account__tx_account_default_impl(port, ptr, rust_vec_len, data_len) } - 186 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), - 187 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), - 188 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), - 189 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), - 192 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), - 193 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), - 194 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), - 195 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), - 196 => wire__crate__api__transaction__update_historical_prices_impl( + 187 => wire__crate__api__account__tx_memo_default_impl(port, ptr, rust_vec_len, data_len), + 188 => wire__crate__api__account__tx_note_default_impl(port, ptr, rust_vec_len, data_len), + 189 => wire__crate__api__account__tx_output_default_impl(port, ptr, rust_vec_len, data_len), + 190 => wire__crate__api__account__tx_spend_default_impl(port, ptr, rust_vec_len, data_len), + 193 => wire__crate__api__account__unlock_all_notes_impl(port, ptr, rust_vec_len, data_len), + 194 => wire__crate__api__pay__unpack_transaction_impl(port, ptr, rust_vec_len, data_len), + 195 => wire__crate__api__account__update_account_impl(port, ptr, rust_vec_len, data_len), + 196 => wire__crate__api__contacts__update_contact_impl(port, ptr, rust_vec_len, data_len), + 197 => wire__crate__api__transaction__update_historical_prices_impl( port, ptr, rust_vec_len, data_len, ), - 199 => { + 200 => { wire__crate__api__voting__votechain_list_rounds_impl(port, ptr, rust_vec_len, data_len) } - 200 => wire__crate__api__voting__votechain_resubmit_share_impl( + 201 => wire__crate__api__voting__votechain_resubmit_share_impl( port, ptr, rust_vec_len, data_len, ), - 201 => { + 202 => { wire__crate__api__voting__votechain_round_status_impl(port, ptr, rust_vec_len, data_len) } - 202 => { + 203 => { wire__crate__api__voting__votechain_round_tally_impl(port, ptr, rust_vec_len, data_len) } - 203 => { + 204 => { wire__crate__api__voting__votechain_share_status_impl(port, ptr, rust_vec_len, data_len) } - 204 => wire__crate__api__voting__votechain_submit_delegation_impl( + 205 => wire__crate__api__voting__votechain_submit_delegation_impl( port, ptr, rust_vec_len, data_len, ), - 205 => { + 206 => { wire__crate__api__voting__votechain_submit_share_impl(port, ptr, rust_vec_len, data_len) } - 206 => { + 207 => { wire__crate__api__voting__votechain_submit_vote_impl(port, ptr, rust_vec_len, data_len) } - 207 => wire__crate__api__voting__votechain_tx_confirmation_impl( + 208 => wire__crate__api__voting__votechain_tx_confirmation_impl( port, ptr, rust_vec_len, data_len, ), - 208 => { + 209 => { wire__crate__api__voting__voting_ballot_intents_impl(port, ptr, rust_vec_len, data_len) } - 209 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), - 210 => wire__crate__api__voting__voting_commit_with_progress_impl( + 210 => wire__crate__api__voting__voting_commit_impl(port, ptr, rust_vec_len, data_len), + 211 => wire__crate__api__voting__voting_commit_with_progress_impl( port, ptr, rust_vec_len, data_len, ), - 211 => { + 212 => { wire__crate__api__voting__voting_config_cached_impl(port, ptr, rust_vec_len, data_len) } - 212 => wire__crate__api__voting__voting_config_clear_cache_impl( + 213 => wire__crate__api__voting__voting_config_clear_cache_impl( port, ptr, rust_vec_len, data_len, ), - 213 => { + 214 => { wire__crate__api__voting__voting_config_resolve_impl(port, ptr, rust_vec_len, data_len) } - 214 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), - 215 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( + 215 => wire__crate__api__voting__voting_confirm_impl(port, ptr, rust_vec_len, data_len), + 216 => wire__crate__api__voting__voting_delegation_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 216 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), - 217 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), - 218 => { + 217 => wire__crate__api__voting__voting_drafts_load_impl(port, ptr, rust_vec_len, data_len), + 218 => wire__crate__api__voting__voting_drafts_save_impl(port, ptr, rust_vec_len, data_len), + 219 => { wire__crate__api__voting__voting_eligible_weight_impl(port, ptr, rust_vec_len, data_len) } - 219 => { + 220 => { wire__crate__api__voting__voting_hotkey_create_impl(port, ptr, rust_vec_len, data_len) } - 220 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), - 221 => wire__crate__api__voting__voting_mark_vote_submitted_impl( + 221 => wire__crate__api__voting__voting_hotkey_get_impl(port, ptr, rust_vec_len, data_len), + 222 => wire__crate__api__voting__voting_mark_vote_submitted_impl( port, ptr, rust_vec_len, data_len, ), - 222 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), - 223 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), - 224 => wire__crate__api__voting__voting_record_execution_impl( + 223 => wire__crate__api__voting__voting_payloads_impl(port, ptr, rust_vec_len, data_len), + 224 => wire__crate__api__voting__voting_plan_impl(port, ptr, rust_vec_len, data_len), + 225 => wire__crate__api__voting__voting_record_execution_impl( port, ptr, rust_vec_len, data_len, ), - 225 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( + 226 => wire__crate__api__voting__voting_recover_confirm_delegation_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 226 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( + 227 => wire__crate__api__voting__voting_recover_confirm_vote_from_tree_impl( port, ptr, rust_vec_len, data_len, ), - 227 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), - 228 => { + 228 => wire__crate__api__voting__voting_recovery_impl(port, ptr, rust_vec_len, data_len), + 229 => { wire__crate__api__voting__voting_recovery_clear_impl(port, ptr, rust_vec_len, data_len) } - 229 => wire__crate__api__voting__voting_reset_session_state_impl( + 230 => wire__crate__api__voting__voting_reset_session_state_impl( port, ptr, rust_vec_len, data_len, ), - 230 => wire__crate__api__voting__voting_round_params_json_impl( + 231 => wire__crate__api__voting__voting_round_params_json_impl( port, ptr, rust_vec_len, data_len, ), - 231 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), - 232 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), - 233 => wire__crate__api__voting__voting_set_ballot_intent_impl( + 232 => wire__crate__api__voting__voting_rounds_impl(port, ptr, rust_vec_len, data_len), + 233 => wire__crate__api__voting__voting_sessions_impl(port, ptr, rust_vec_len, data_len), + 234 => wire__crate__api__voting__voting_set_ballot_intent_impl( port, ptr, rust_vec_len, data_len, ), - 234 => wire__crate__api__voting__voting_share_add_servers_impl( + 235 => wire__crate__api__voting__voting_share_add_servers_impl( port, ptr, rust_vec_len, data_len, ), - 235 => { + 236 => { wire__crate__api__voting__voting_share_confirm_impl(port, ptr, rust_vec_len, data_len) } - 236 => { + 237 => { wire__crate__api__voting__voting_share_payloads_impl(port, ptr, rust_vec_len, data_len) } - 237 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), - 238 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), - 239 => { + 238 => wire__crate__api__voting__voting_share_plan_impl(port, ptr, rust_vec_len, data_len), + 239 => wire__crate__api__voting__voting_share_plans_impl(port, ptr, rust_vec_len, data_len), + 240 => { wire__crate__api__voting__voting_share_record_impl(port, ptr, rust_vec_len, data_len) } - 240 => wire__crate__api__voting__voting_share_unconfirmed_impl( + 241 => wire__crate__api__voting__voting_share_unconfirmed_impl( port, ptr, rust_vec_len, data_len, ), - 241 => { + 242 => { wire__crate__api__voting__voting_share_wire_json_impl(port, ptr, rust_vec_len, data_len) } - 242 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), - 243 => { + 243 => wire__crate__api__voting__voting_sync_tree_impl(port, ptr, rust_vec_len, data_len), + 244 => { wire__crate__api__voting__voting_tree_find_leaf_impl(port, ptr, rust_vec_len, data_len) } - 244 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), - 245 => wire__crate__api__voting__voting_vote_commitment_hex_impl( + 245 => wire__crate__api__voting__voting_van_witness_impl(port, ptr, rust_vec_len, data_len), + 246 => wire__crate__api__voting__voting_vote_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 246 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( + 247 => wire__crate__api__voting__voting_vote_van_commitment_hex_impl( port, ptr, rust_vec_len, data_len, ), - 247 => { + 248 => { wire__crate__api__voting__voting_vote_wire_json_impl(port, ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -13448,22 +13468,22 @@ fn pde_ffi_dispatcher_sync_impl( 114 => { wire__crate__api__key__is_valid_transparent_address_impl(ptr, rust_vec_len, data_len) } - 138 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), - 153 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), - 169 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), - 170 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), - 182 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), - 184 => wire__crate__api__openalias__try_validate_zcash_address_impl( + 139 => wire__crate__api__pay__parse_payment_uri_impl(ptr, rust_vec_len, data_len), + 154 => wire__crate__api__account__receivers_from_ua_impl(ptr, rust_vec_len, data_len), + 170 => wire__crate__api__init__set_expert_mode_impl(ptr, rust_vec_len, data_len), + 171 => wire__crate__api__init__set_log_stream_impl(ptr, rust_vec_len, data_len), + 183 => wire__crate__api__pay__to_plan_impl(ptr, rust_vec_len, data_len), + 185 => wire__crate__api__openalias__try_validate_zcash_address_impl( ptr, rust_vec_len, data_len, ), - 190 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), - 191 => wire__crate__api__ledger__ufvk_default_address_impl(ptr, rust_vec_len, data_len), - 197 => { + 191 => wire__crate__api__account__ua_from_ufvk_impl(ptr, rust_vec_len, data_len), + 192 => wire__crate__api__ledger__ufvk_default_address_impl(ptr, rust_vec_len, data_len), + 198 => { wire__crate__api__openalias__validate_openalias_name_impl(ptr, rust_vec_len, data_len) } - 198 => { + 199 => { wire__crate__api__openalias__validate_zcash_address_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), diff --git a/rust/src/ledger/official.rs b/rust/src/ledger/official.rs index b07aa261a..36baff0ba 100644 --- a/rust/src/ledger/official.rs +++ b/rust/src/ledger/official.rs @@ -25,6 +25,10 @@ pub struct OfficialApp {} const CLA: u8 = 0xE0; const INS_GET_FIRMWARE_VERSION: u8 = 0xC4; const INS_GET_VK: u8 = 0x50; +const INS_GET_SHIELD_ADDR: u8 = 0x51; +const P1_NO_DISPLAY: u8 = 0x00; +const P1_DISPLAY: u8 = 0x01; +const P2_UNIFIED_ADDRESS: u8 = 0x00; const P1_FIRST: u8 = 0x00; const P1_CONTINUE: u8 = 0x80; const P2_UFVK: u8 = 0x00; @@ -41,6 +45,81 @@ fn append_path(data: &mut Vec<u8>, purpose: u32, coin_type: u32, account: u32) - Ok(()) } +/// m/44'/coin'/account'/0/0: the external address the device puts in its +/// unified address, as GET_SHIELD_ADDR wants it. +fn append_transparent_address_path( + data: &mut Vec<u8>, + coin_type: u32, + account: u32, +) -> LedgerResult<()> { + data.write_u8(5)?; + data.write_u32::<BE>(44 | HARDENED)?; + data.write_u32::<BE>(coin_type | HARDENED)?; + data.write_u32::<BE>(account | HARDENED)?; + data.write_u32::<BE>(0)?; + data.write_u32::<BE>(0)?; + Ok(()) +} + +/// The account's default unified address as the device derives it. +/// +/// With `display`, the device shows the address on its own screen and waits +/// for the user to approve it; that screen is the only thing on the path a +/// tampered link cannot alter, so the host shows the address it derived from +/// the imported viewing key alongside, and the user compares the two. A +/// refusal on the device is reported as such. +pub async fn get_shield_address<D: Device>( + ledger: &D, + network: &Network, + aindex: u32, + display: bool, +) -> LedgerResult<String> { + let coin_type = network.coin_type(); + let mut data = vec![]; + append_path(&mut data, 32, coin_type, aindex)?; + append_transparent_address_path(&mut data, coin_type, aindex)?; + + let res = ledger + .execute(APDUCommand { + cla: CLA, + ins: INS_GET_SHIELD_ADDR, + p1: if display { P1_DISPLAY } else { P1_NO_DISPLAY }, + p2: P2_UNIFIED_ADDRESS, + data, + }) + .await?; + if res.retcode == SW_DENY { + return Err(LedgerError::Generic( + SW_DENY, + "user did not confirm the address on the device".into(), + )); + } + if res.retcode != SW_OK { + return Err(LedgerError::Execute(res.retcode, INS_GET_SHIELD_ADDR)); + } + let payload = res.data; + if payload.len() < 2 { + return Err(LedgerError::Protocol("short address response".into())); + } + let len = u16::from_be_bytes([payload[0], payload[1]]) as usize; + let body = &payload[2..]; + if body.len() < len { + return Err(LedgerError::Protocol( + "the device sent less of the address than it announced".into(), + )); + } + let address = String::from_utf8(body[..len].to_vec()) + .map_err(|_| LedgerError::Protocol("invalid utf8 in address response".into()))?; + let parsed = zcash_address::ZcashAddress::try_from_encoded(&address) + .map_err(|_| LedgerError::Protocol("device returned an invalid address".into()))?; + if !parsed.can_receive_as(zcash_protocol::PoolType::ORCHARD) { + return Err(LedgerError::Protocol( + "device address has no Orchard receiver".into(), + )); + } + Ok(address) +} + /// Version of the Zcash app open on the device, as (major, minor, patch). /// /// GET_FIRMWARE_VERSION is the Bitcoin-app style probe the Official app @@ -252,6 +331,66 @@ mod tests { assert!(matches!(err, LedgerError::Protocol(_))); } + fn account_zero_address(network: &Network) -> String { + let usk = UnifiedSpendingKey::from_seed(network, &[7u8; 32], AccountId::ZERO).unwrap(); + let ufvk = usk.to_unified_full_viewing_key(); + let (ua, _) = ufvk + .default_address(zcash_keys::keys::UnifiedAddressRequest::AllAvailableKeys) + .unwrap(); + ua.encode(network) + } + + #[tokio::test] + async fn the_device_address_is_requested_on_screen_for_the_external_path() { + let network = Network::Main; + let ua = account_zero_address(&network); + let mut reply = (ua.len() as u16).to_be_bytes().to_vec(); + reply.extend_from_slice(ua.as_bytes()); + let device = Scripted::new(vec![with_sw(reply, SW_OK)]); + + let got = get_shield_address(&device, &network, 0, true).await.unwrap(); + assert_eq!(got, ua); + + let sent = device.sent.lock().unwrap(); + assert_eq!(sent.len(), 1); + assert_eq!(sent[0].ins, INS_GET_SHIELD_ADDR); + assert_eq!(sent[0].p1, P1_DISPLAY); + assert_eq!(sent[0].p2, P2_UNIFIED_ADDRESS); + // Orchard account path, then the five-component transparent address path. + assert_eq!(&sent[0].data[0..5], &[3, 0x80, 0, 0, 32]); + assert_eq!(&sent[0].data[13..18], &[5, 0x80, 0, 0, 44]); + assert_eq!(&sent[0].data[26..34], &[0, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(sent[0].data.len(), 13 + 21); + } + + #[tokio::test] + async fn a_truncated_or_foreign_address_reply_is_refused() { + let network = Network::Main; + let ua = account_zero_address(&network); + let mut short = (ua.len() as u16).to_be_bytes().to_vec(); + short.extend_from_slice(&ua.as_bytes()[..20]); + let device = Scripted::new(vec![with_sw(short, SW_OK)]); + assert!(matches!( + get_shield_address(&device, &network, 0, true).await.unwrap_err(), + LedgerError::Protocol(_) + )); + + let junk = b"not an address"; + let mut reply = (junk.len() as u16).to_be_bytes().to_vec(); + reply.extend_from_slice(junk); + let device = Scripted::new(vec![with_sw(reply, SW_OK)]); + assert!(matches!( + get_shield_address(&device, &network, 0, true).await.unwrap_err(), + LedgerError::Protocol(_) + )); + + let device = Scripted::new(vec![vec![0x69, 0x85]]); + assert!(matches!( + get_shield_address(&device, &network, 0, true).await.unwrap_err(), + LedgerError::Generic(SW_DENY, _) + )); + } + #[tokio::test] async fn refusing_the_export_is_reported_as_such() { let device = Scripted::new(vec![vec![0x69, 0x85]]); diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index 14976c2f9..751d37e74 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -193,6 +193,9 @@ async fn sign_transparent_input<D: Device>( // tag byte (sig[0] |= 0x01). The parity is irrelevant here — the signature // verifies against the pubkey from the PCZT's hash160 preimage — so clear // it before parsing. + if der.is_empty() { + anyhow::bail!("the device returned a transparent signature with no DER bytes"); + } let mut der = der.to_vec(); der[0] &= !0x01; secp256k1::ecdsa::Signature::from_der(&der).map_err(|e| { From 67a2513eb13bd738190b9a21f03da5eb305f84ad Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 20:21:06 -0400 Subject: [PATCH 188/189] ledger: report signing only once the device has returned a signature "Signing on Ledger" was announced before the first signing command, which is the command that blocks until the user approves on the device; a host following the events told the user the transaction was being signed while the device was still waiting for them. Progress is now reported after each signature comes back ("Signed ... n/m"), so "Confirm on your Ledger" stays current until the user has acted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- rust/src/ledger/official_sign.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index 751d37e74..b19fd3d2c 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -631,30 +631,38 @@ where progress("Confirm on your Ledger".to_string()).await; // ── Collect signatures ──────────────────────────────────────────────── - progress("Signing on Ledger".to_string()).await; - + // The first signing command is the one that waits for the user's + // approval on the device, so nothing is reported as "signing" until a + // signature has actually come back; until then the user is still being + // asked to confirm. let ctin = pczt.transparent().inputs().len(); let mut tsigs = Vec::with_capacity(ctin); for index in 0..ctin { - progress(format!( - "Signing transparent input {}/{}", - index + 1, - ctin - )).await; tsigs.push(sign_transparent_input(ledger, index as u32).await?); + progress(format!("Signed transparent input {}/{}", index + 1, ctin)).await; } let mut orchard_sigs = Vec::with_capacity(package.orchard_indices.len()); - for index in &package.orchard_indices { - progress("Signing orchard spend".to_string()).await; + for (n, index) in package.orchard_indices.iter().enumerate() { orchard_sigs.push(sign_one(ledger, INS_PCZT_SIGN_ORCHARD, *index as u32).await?); + progress(format!( + "Signed orchard spend {}/{}", + n + 1, + package.orchard_indices.len() + )) + .await; } let mut ironwood_sigs = Vec::with_capacity(package.ironwood_indices.len()); - for index in &package.ironwood_indices { - progress("Signing ironwood spend".to_string()).await; + for (n, index) in package.ironwood_indices.iter().enumerate() { ironwood_sigs.push(sign_one(ledger, INS_PCZT_SIGN_IRONWOOD, *index as u32).await?); + progress(format!( + "Signed ironwood spend {}/{}", + n + 1, + package.ironwood_indices.len() + )) + .await; } // ── Apply signatures, proofs, binding signature ─────────────────────── From 8083636a44957d05a53c9b63f027f205714edea9 Mon Sep 17 00:00:00 2001 From: Vikrant Sharma <vikrantfl@me.com> Date: Wed, 16 Sep 2026 20:38:15 -0400 Subject: [PATCH 189/189] ledger: say "Confirm on your Ledger" before the final packet, not after its reply The device puts its review on screen when the packet carrying P2_FINISHED arrives and answers that packet only once the user has approved (a real send showed a 17 s gap before the reply and a signature 1 s after it). So the confirm event, sent after the reply, came after the user had already approved. It is now sent just before that packet, and the reply is what marks the approval. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --- rust/src/ledger/official_sign.rs | 42 +++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/rust/src/ledger/official_sign.rs b/rust/src/ledger/official_sign.rs index b19fd3d2c..7c5983226 100644 --- a/rust/src/ledger/official_sign.rs +++ b/rust/src/ledger/official_sign.rs @@ -103,6 +103,27 @@ async fn send_command<D: Device>( packets: Vec<Vec<u8>>, finished: bool, ) -> Result<()> { + send_command_with::<D, _, _>(ledger, ins, packets, finished, None::<fn() -> std::future::Ready<()>>) + .await +} + +/// Streams one bundle command. With `finished`, the last packet carries +/// P2_FINISHED: the device puts its review on screen when that packet +/// arrives and answers it only once the user has approved, so +/// `before_finished` runs just before it is sent -- the moment to tell the +/// user to look at the device. +async fn send_command_with<D, F, Fut>( + ledger: &D, + ins: u8, + packets: Vec<Vec<u8>>, + finished: bool, + mut before_finished: Option<F>, +) -> Result<()> +where + D: Device, + F: FnOnce() -> Fut, + Fut: std::future::Future<Output = ()>, +{ let n = packets.len(); for (i, data) in packets.into_iter().enumerate() { if data.len() > 255 { @@ -120,6 +141,11 @@ async fn send_command<D: Device>( } else { P2_CONTINUE }; + if p2 == P2_FINISHED { + if let Some(f) = before_finished.take() { + f().await; + } + } let res = ledger .execute(APDUCommand { cla: CLA, @@ -625,10 +651,18 @@ where // V6 defers the review to the ironwood command: it is always sent, even // with 0 actions, and its last packet carries P2_FINISHED. send_command(ledger, INS_PCZT_ORCHARD_ACTION, orchard_packets, false).await?; - send_command(ledger, INS_PCZT_IRONWOOD_ACTION, ironwood_packets, true).await?; - // The device draws its review only once that last packet has landed; - // this is the first moment there is anything for the user to confirm. - progress("Confirm on your Ledger".to_string()).await; + // The device draws its review when the final packet arrives and holds + // its reply until the user has approved, so the user is told to look at + // the device just before that packet goes out; the reply coming back + // means they have. + send_command_with( + ledger, + INS_PCZT_IRONWOOD_ACTION, + ironwood_packets, + true, + Some(|| progress("Confirm on your Ledger".to_string())), + ) + .await?; // ── Collect signatures ──────────────────────────────────────────────── // The first signing command is the one that waits for the user's